From 00f426974367a660d5228418b9b5843d969f4ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 23 Jan 2019 12:00:13 +0000 Subject: display: ensure qxl log_buf is a nul terminated string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Daniel P. Berrangé Message-id: 20190123120016.4538-2-berrange@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/display/qxl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'hw/display/qxl.c') diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 8e9a65e75b..da8fd5a40a 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1763,10 +1763,16 @@ async_common: 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: -- cgit v1.2.3