1 From ac5f64a80ae637742ed95fd6c98f66281b3e15c6 Mon Sep 17 00:00:00 2001
2 From: Frediano Ziglio <fziglio@redhat.com>
3 Date: Thu, 17 Sep 2015 15:00:22 +0100
4 Subject: [PATCH 04/19] Fix some integer overflow causing large memory
7 Prevent integer overflow when computing image sizes.
8 Image index computations are done using 32 bit so this can cause easily
9 security issues. MAX_DATA_CHUNK is larger than the virtual
10 card limit, so this is not going to cause change in behaviours.
11 Comparing size calculation results with MAX_DATA_CHUNK will allow us to
13 Prevent guest from allocating large amount of memory.
15 Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
17 server/red_parse_qxl.c | 15 +++++++++++----
18 1 file changed, 11 insertions(+), 4 deletions(-)
20 --- a/server/red_parse_qxl.c
21 +++ b/server/red_parse_qxl.c
22 @@ -384,7 +384,7 @@ static SpiceImage *red_get_image(RedMemS
24 SpiceImage *red = NULL;
25 SpicePalette *rp = NULL;
26 - size_t bitmap_size, size;
27 + uint64_t bitmap_size, size;
31 @@ -460,7 +460,10 @@ static SpiceImage *red_get_image(RedMemS
32 red->u.bitmap.palette = rp;
33 red->u.bitmap.palette_id = rp->unique;
35 - bitmap_size = red->u.bitmap.y * abs(red->u.bitmap.stride);
36 + bitmap_size = (uint64_t) red->u.bitmap.y * abs(red->u.bitmap.stride);
37 + if (bitmap_size > MAX_DATA_CHUNK) {
40 if (qxl_flags & QXL_BITMAP_DIRECT) {
41 red->u.bitmap.data = red_get_image_data_flat(slots, group_id,
43 @@ -1221,7 +1224,7 @@ int red_get_surface_cmd(RedMemSlotInfo *
44 RedSurfaceCmd *red, QXLPHYSICAL addr)
51 qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
52 @@ -1241,7 +1244,11 @@ int red_get_surface_cmd(RedMemSlotInfo *
53 red->u.surface_create.width = qxl->u.surface_create.width;
54 red->u.surface_create.height = qxl->u.surface_create.height;
55 red->u.surface_create.stride = qxl->u.surface_create.stride;
56 - size = red->u.surface_create.height * abs(red->u.surface_create.stride);
57 + /* the multiplication can overflow, also abs(-2^31) may return a negative value */
58 + size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride);
59 + if (size > MAX_DATA_CHUNK || red->u.surface_create.stride == G_MININT32) {
62 red->u.surface_create.data =
63 (uint8_t*)get_virt(slots, qxl->u.surface_create.data, size, group_id, &error);