|
|
e2c81d |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
73b8f2 |
From: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
Date: Tue, 8 Sep 2015 16:02:59 +0100
|
|
|
e2c81d |
Subject: [PATCH] Check properly surface to be created
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Check format is valid.
|
|
|
73b8f2 |
Check stride is at least the size of required bytes for a row.
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
|
|
|
73b8f2 |
---
|
|
|
73b8f2 |
server/red_parse_qxl.c | 35 ++++++++++++++++++++++++++++++++++-
|
|
|
73b8f2 |
1 file changed, 34 insertions(+), 1 deletion(-)
|
|
|
73b8f2 |
|
|
|
73b8f2 |
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
|
|
|
73b8f2 |
index ceb2759..a7ca71d 100644
|
|
|
73b8f2 |
--- a/server/red_parse_qxl.c
|
|
|
73b8f2 |
+++ b/server/red_parse_qxl.c
|
|
|
73b8f2 |
@@ -1219,12 +1219,30 @@ void red_put_message(RedMessage *red)
|
|
|
73b8f2 |
/* nothing yet */
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
|
|
|
73b8f2 |
+static unsigned int surface_format_to_bpp(uint32_t format)
|
|
|
73b8f2 |
+{
|
|
|
73b8f2 |
+ switch (format) {
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_1_A:
|
|
|
73b8f2 |
+ return 1;
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_8_A:
|
|
|
73b8f2 |
+ return 8;
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_16_555:
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_16_565:
|
|
|
73b8f2 |
+ return 16;
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_32_xRGB:
|
|
|
73b8f2 |
+ case SPICE_SURFACE_FMT_32_ARGB:
|
|
|
73b8f2 |
+ return 32;
|
|
|
73b8f2 |
+ }
|
|
|
73b8f2 |
+ return 0;
|
|
|
73b8f2 |
+}
|
|
|
73b8f2 |
+
|
|
|
73b8f2 |
int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
RedSurfaceCmd *red, QXLPHYSICAL addr)
|
|
|
73b8f2 |
{
|
|
|
73b8f2 |
QXLSurfaceCmd *qxl;
|
|
|
73b8f2 |
uint64_t size;
|
|
|
73b8f2 |
int error;
|
|
|
73b8f2 |
+ unsigned int bpp;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
qxl = (QXLSurfaceCmd *)get_virt(slots, addr, sizeof(*qxl), group_id,
|
|
|
73b8f2 |
&error);
|
|
|
73b8f2 |
@@ -1243,9 +1261,24 @@ int red_get_surface_cmd(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
red->u.surface_create.width = qxl->u.surface_create.width;
|
|
|
73b8f2 |
red->u.surface_create.height = qxl->u.surface_create.height;
|
|
|
73b8f2 |
red->u.surface_create.stride = qxl->u.surface_create.stride;
|
|
|
73b8f2 |
+ bpp = surface_format_to_bpp(red->u.surface_create.format);
|
|
|
73b8f2 |
+
|
|
|
73b8f2 |
+ /* check if format is valid */
|
|
|
73b8f2 |
+ if (!bpp) {
|
|
|
73b8f2 |
+ return 1;
|
|
|
73b8f2 |
+ }
|
|
|
73b8f2 |
+
|
|
|
73b8f2 |
+ /* check stride is larger than required bytes */
|
|
|
73b8f2 |
+ size = ((uint64_t) red->u.surface_create.width * bpp + 7u) / 8u;
|
|
|
73b8f2 |
+ /* the uint32_t conversion is here to avoid problems with -2^31 value */
|
|
|
73b8f2 |
+ if (red->u.surface_create.stride == G_MININT32
|
|
|
73b8f2 |
+ || size > (uint32_t) abs(red->u.surface_create.stride)) {
|
|
|
73b8f2 |
+ return 1;
|
|
|
73b8f2 |
+ }
|
|
|
73b8f2 |
+
|
|
|
73b8f2 |
/* the multiplication can overflow, also abs(-2^31) may return a negative value */
|
|
|
73b8f2 |
size = (uint64_t) red->u.surface_create.height * abs(red->u.surface_create.stride);
|
|
|
73b8f2 |
- if (size > MAX_DATA_CHUNK || red->u.surface_create.stride == G_MININT32) {
|
|
|
73b8f2 |
+ if (size > MAX_DATA_CHUNK) {
|
|
|
73b8f2 |
return 1;
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
red->u.surface_create.data =
|