]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
xen/console: Properly buffer domU output when using CONSOLEIO_write
authorJulien Grall <julien.grall@arm.com>
Tue, 2 Apr 2019 16:42:35 +0000 (17:42 +0100)
committerJulien Grall <julien.grall@arm.com>
Tue, 9 Apr 2019 10:23:07 +0000 (11:23 +0100)
The output will be buffered if the buffer provided by the DomU does not
contain a newline. This can also happen if buffer provided by DomU is
split in multiple part (Xen can only process 127 characters at the time).

As Xen will remove any non-printable characters, the output buffer may
be smaller than the buffer provided. However, Xen will buffer using the
original length. This means that the NUL character and garbagge will be
copied in the internal buffer.

Once the newline is found or the internal buffer is full, only part of
the internal buffer will end up to be printed.

An easy way to reproduce it is:

HYPERVISOR_consoleio(CONSOLEIO_write, "\33", 1);
HYPERVISOR_consoleio(CONSOLEIO_write, "d", 1);
HYPERVISOR_consoleio(CONSOLEIO_write, "\n", 1);

In the current code, the character 'd' will not be printed.

This problem can be solved by computing the size of the output buffer
(i.e the buffer without the non-printable characters).

Signed-off-by: Julien Grall <julien.grall@arm.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
xen/drivers/char/console.c

index 5f0f54201b28786376497c67048d229a9e0e2c6e..9bbcb0f57a843d41823962b3e098d6d573b17afc 100644 (file)
@@ -592,11 +592,11 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, int count)
                 guest_printk(cd, XENLOG_G_DEBUG "%s%s\n", cd->pbuf, kbuf);
                 cd->pbuf_idx = 0;
             }
-            else if ( cd->pbuf_idx + kcount < (DOMAIN_PBUF_SIZE - 1) )
+            else if ( cd->pbuf_idx + (kout - kbuf) < (DOMAIN_PBUF_SIZE - 1) )
             {
                 /* buffer the output until a newline */
-                memcpy(cd->pbuf + cd->pbuf_idx, kbuf, kcount);
-                cd->pbuf_idx += kcount;
+                memcpy(cd->pbuf + cd->pbuf_idx, kbuf, kout - kbuf);
+                cd->pbuf_idx += (kout - kbuf);
             }
             else
             {