Blame SOURCES/0003-lz-More-checks-on-image-sizes.patch

39a9e2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
39a9e2
From: Frediano Ziglio <fziglio@redhat.com>
39a9e2
Date: Mon, 25 Jun 2018 14:16:10 +0100
39a9e2
Subject: [PATCH spice-common 2/2] lz: More checks on image sizes
39a9e2
39a9e2
Extend sizes check also to decoding, actually the source data
39a9e2
decoding images should be less safe than encoding.
39a9e2
This avoids different integer overflows and buffer overflows.
39a9e2
To avoid potential issues images are limited to 1GB.
39a9e2
39a9e2
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
39a9e2
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
39a9e2
---
39a9e2
 common/lz.c | 68 ++++++++++++++++++++++++++++++++++++-----------------
39a9e2
 1 file changed, 46 insertions(+), 22 deletions(-)
39a9e2
39a9e2
diff --git a/spice-common/common/lz.c b/spice-common/common/lz.c
39a9e2
index 2c5d5e2..167e118 100644
39a9e2
--- a/spice-common/common/lz.c
39a9e2
+++ b/spice-common/common/lz.c
39a9e2
@@ -53,6 +53,8 @@
39a9e2
 #define HASH_SIZE (1 << HASH_LOG)
39a9e2
 #define HASH_MASK (HASH_SIZE - 1)
39a9e2
 
39a9e2
+/* Maximum image size, mainly to avoid possible integer overflows */
39a9e2
+#define SPICE_MAX_IMAGE_SIZE (1024 * 1024 * 1024 - 1)
39a9e2
 
39a9e2
 typedef struct LzImageSegment LzImageSegment;
39a9e2
 struct LzImageSegment {
39a9e2
@@ -481,33 +483,53 @@ typedef uint16_t rgb16_pixel_t;
39a9e2
 #undef LZ_UNEXPECT_CONDITIONAL
39a9e2
 #undef LZ_EXPECT_CONDITIONAL
39a9e2
 
39a9e2
-int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down,
39a9e2
-              uint8_t *lines, unsigned int num_lines, int stride,
39a9e2
-              uint8_t *io_ptr, unsigned int num_io_bytes)
39a9e2
+static void lz_set_sizes(Encoder *encoder, int type, int width, int height, int stride)
39a9e2
 {
39a9e2
-    Encoder *encoder = (Encoder *)lz;
39a9e2
-    uint8_t *io_ptr_end = io_ptr + num_io_bytes;
39a9e2
-
39a9e2
-    encoder->type = type;
39a9e2
-    encoder->width = width;
39a9e2
-    encoder->height = height;
39a9e2
-    encoder->stride = stride;
39a9e2
+    if (width < 0) {
39a9e2
+        encoder->usr->error(encoder->usr, "invalid lz width %d\n", width);
39a9e2
+    }
39a9e2
+    if (height < 0) {
39a9e2
+        encoder->usr->error(encoder->usr, "invalid lz height %d\n", height);
39a9e2
+    }
39a9e2
+    if (stride < 0) {
39a9e2
+        encoder->usr->error(encoder->usr, "invalid lz stride %d\n", stride);
39a9e2
+    }
39a9e2
 
39a9e2
-    if (IS_IMAGE_TYPE_PLT[encoder->type]) {
39a9e2
-        if (encoder->stride > (width / PLT_PIXELS_PER_BYTE[encoder->type])) {
39a9e2
-            if (((width % PLT_PIXELS_PER_BYTE[encoder->type]) == 0) || (
39a9e2
-                    (encoder->stride - (width / PLT_PIXELS_PER_BYTE[encoder->type])) > 1)) {
39a9e2
+    if (IS_IMAGE_TYPE_PLT[type]) {
39a9e2
+        if (stride > (width / PLT_PIXELS_PER_BYTE[type])) {
39a9e2
+            if (((width % PLT_PIXELS_PER_BYTE[type]) == 0) || (
39a9e2
+                    (stride - (width / PLT_PIXELS_PER_BYTE[type])) > 1)) {
39a9e2
                 encoder->usr->error(encoder->usr, "stride overflows (plt)\n");
39a9e2
             }
39a9e2
         }
39a9e2
     } else {
39a9e2
-        if (encoder->stride != width * RGB_BYTES_PER_PIXEL[encoder->type]) {
39a9e2
+        if (stride != width * RGB_BYTES_PER_PIXEL[type]) {
39a9e2
             encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb) %d != %d * %d (%d)\n",
39a9e2
-                                encoder->stride, width, RGB_BYTES_PER_PIXEL[encoder->type],
39a9e2
-                                encoder->type);
39a9e2
+                                stride, width, RGB_BYTES_PER_PIXEL[type],
39a9e2
+                                type);
39a9e2
         }
39a9e2
     }
39a9e2
 
39a9e2
+    // avoid too big images
39a9e2
+    if ((uint64_t) stride * height > SPICE_MAX_IMAGE_SIZE) {
39a9e2
+        encoder->usr->error(encoder->usr, "image too large\n");
39a9e2
+    }
39a9e2
+
39a9e2
+    encoder->type = type;
39a9e2
+    encoder->width = width;
39a9e2
+    encoder->height = height;
39a9e2
+    encoder->stride = stride;
39a9e2
+}
39a9e2
+
39a9e2
+int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down,
39a9e2
+              uint8_t *lines, unsigned int num_lines, int stride,
39a9e2
+              uint8_t *io_ptr, unsigned int num_io_bytes)
39a9e2
+{
39a9e2
+    Encoder *encoder = (Encoder *)lz;
39a9e2
+    uint8_t *io_ptr_end = io_ptr + num_io_bytes;
39a9e2
+
39a9e2
+    lz_set_sizes(encoder, type, width, height, stride);
39a9e2
+
39a9e2
     // assign the output buffer
39a9e2
     if (!encoder_reset(encoder, io_ptr, io_ptr_end)) {
39a9e2
         encoder->usr->error(encoder->usr, "lz encoder io reset failed\n");
39a9e2
@@ -592,13 +614,15 @@ void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes,
39a9e2
         encoder->usr->error(encoder->usr, "bad version\n");
39a9e2
     }
39a9e2
 
39a9e2
-    encoder->type = (LzImageType)decode_32(encoder);
39a9e2
-    if (encoder->type <= LZ_IMAGE_TYPE_INVALID || encoder->type > LZ_IMAGE_TYPE_A8) {
39a9e2
+    int type = decode_32(encoder);
39a9e2
+    if (type <= LZ_IMAGE_TYPE_INVALID || type > LZ_IMAGE_TYPE_A8) {
39a9e2
         encoder->usr->error(encoder->usr, "invalid lz type %d\n", encoder->type);
39a9e2
     }
39a9e2
-    encoder->width = decode_32(encoder);
39a9e2
-    encoder->height = decode_32(encoder);
39a9e2
-    encoder->stride = decode_32(encoder);
39a9e2
+    int width = decode_32(encoder);
39a9e2
+    int height = decode_32(encoder);
39a9e2
+    int stride = decode_32(encoder);
39a9e2
+    lz_set_sizes(encoder, type, width, height, stride);
39a9e2
+
39a9e2
     *out_top_down = decode_32(encoder);
39a9e2
 
39a9e2
     *out_width = encoder->width;