Skip to content

Commit

Permalink
display: ensure qxl log_buf is a nul terminated string
Browse files Browse the repository at this point in the history
The QXL_IO_LOG command allows the guest to send log messages to the host
via a buffer in the QXLRam struct. QEMU prints these to the console if
the qxl 'guestdebug' option is set to non-zero. It will also feed them
to the trace subsystem if any backends are built-in.

In both cases the log_buf data will get treated as being as a nul
terminated string, by the printf '%s' format specifier and / or other
code reading the buffer.

QEMU does nothing to guarantee that the log_buf really is nul terminated,
so there is potential for out of bounds array access.

This would affect any QEMU which has the log, syslog or ftrace trace
backends built into QEMU. It can only be triggered if the 'qxl_io_log'
trace event is enabled, however, so they are not vulnerable without
specific administrative action to enable this.

It would also affect QEMU if the 'guestdebug' parameter is set to a
non-zero value, which again is not the default and requires explicit
admin opt-in.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-id: 20190123120016.4538-2-berrange@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
berrange authored and stefanhaRH committed Jan 24, 2019
1 parent f6b06fc commit 00f4269
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
14 changes: 10 additions & 4 deletions hw/display/qxl.c
Expand Up @@ -1763,10 +1763,16 @@ static void ioport_write(void *opaque, hwaddr addr,
qxl_set_mode(d, val, 0);
break;
case QXL_IO_LOG:
trace_qxl_io_log(d->id, d->ram->log_buf);
if (d->guestdebug) {
fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf);
if (TRACE_QXL_IO_LOG_ENABLED || d->guestdebug) {
/* We cannot trust the guest to NUL terminate d->ram->log_buf */
char *log_buf = g_strndup((const char *)d->ram->log_buf,
sizeof(d->ram->log_buf));
trace_qxl_io_log(d->id, log_buf);
if (d->guestdebug) {
fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), log_buf);
}
g_free(log_buf);
}
break;
case QXL_IO_RESET:
Expand Down
2 changes: 1 addition & 1 deletion hw/display/trace-events
Expand Up @@ -72,7 +72,7 @@ qxl_interface_update_area_complete_rest(int qid, uint32_t num_updated_rects) "%d
qxl_interface_update_area_complete_overflow(int qid, int max) "%d max=%d"
qxl_interface_update_area_complete_schedule_bh(int qid, uint32_t num_dirty) "%d #dirty=%d"
qxl_io_destroy_primary_ignored(int qid, const char *mode) "%d %s"
qxl_io_log(int qid, const uint8_t *log_buf) "%d %s"
qxl_io_log(int qid, const char *log_buf) "%d %s"
qxl_io_read_unexpected(int qid) "%d"
qxl_io_unexpected_vga_mode(int qid, uint64_t addr, uint64_t val, const char *desc) "%d 0x%"PRIx64"=%"PRIu64" (%s)"
qxl_io_write(int qid, const char *mode, uint64_t addr, const char *aname, uint64_t val, unsigned size, int async) "%d %s addr=%"PRIu64 " (%s) val=%"PRIu64" size=%u async=%d"
Expand Down

0 comments on commit 00f4269

Please sign in to comment.