[Spice-devel] [spice v13 03/29] server: Add a GStreamer 1.0 MJPEG video encoder and use it by default

Francois Gouget fgouget at codeweavers.com
Tue May 24 18:45:06 UTC 2016


On Fri, 13 May 2016, Christophe Fergeau wrote:
[...]
> Yeah, the only reason for these questions is to know whether a malicious
> client could trigger misbehaviour in this part of the code by sending us
> some unexpected data. I agree when all is good, this does not make
> sense/should not happen, but I'd prefer to be 100% sure it cannot happen
> regardless of what we receive from the guest.

By 'malicious client' I guess you don't mean Spicy (since the video 
doesn't flow upstream). So presumably you're concerned by a buggy/rogue 
QXL driver in a VM.

In the video streaming case, both stream_stride and bitmap->stride come 
from RedDrawable.u.copy:
 * bitmap is the SpiceCopy.src_bitmap field
 * stream_stride is computed from the SpiceCopy.src_area field
  (src_area.right - src_area.left).

Now if the content of SpiceCopy cannot be trusted, the GStreamer encoder 
is the wrong place to check for issues : there are at least three places 
where the SpiceCopy bitmap can be used: the MJPEG encoder, the GStreamer 
encoder and the regular screen update code (which may or may not involve 
the JPEG encoder) [1].

Duplicating checks all over the place can only lead to maintenance 
issues and incomplete checks. So validating the SpiceCopy structure 
should be done before it is sent down one or the other path. The best 
place would probably be either before red_get_native_drawable() is 
called, inside red_get_native_drawable(), or in the relevant 
red_get_XXX_ptr() helper.

However I don't see any such check there or down the path:
 * red-parse-qxl.c never dereferences src_area.
 * dcc-send.c does not check consistency.

In fact I suggest trying variations of the following patch:

diff --git a/server/red-parse-qxl.c b/server/red-parse-qxl.c
index 0dafbef..965b5ef 100644
--- a/server/red-parse-qxl.c
+++ b/server/red-parse-qxl.c
@@ -682,6 +682,8 @@ static int red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
         return 1;
     }
     red_get_rect_ptr(&red->src_area, &qxl->src_area);
+    red->src_area.right += 10;
+    red->src_area.bottom += 10;
     red->rop_descriptor  = qxl->rop_descriptor;
     red->scale_mode      = qxl->scale_mode;
     red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask, flags);


Everything with go fine, modulo significant display issues in the 
client[2], until the MJPEG encoder tries to handle the first frame and 
the JPEG library kills the process with:

Improper call to JPEG library in state 101




[1] To be fair it looks like this last case is handled by sending the 
    whole bitmap (see spice_marshall_Copy() & spice_marshall_Image()), 
    even if only a small bit is supposed to be copied. That does not 
    seem very bandwidth efficient but it side-steps any src_bitmap vs. 
    src_area consistency issues.

[2] So the client does not validate the SpiceCopy object either. Whether 
    its behavior is sensible is not clear however.

-- 
Francois Gouget <fgouget at codeweavers.com>


More information about the Spice-devel mailing list