[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 3/3] lzo: properly check for overruns



From: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

The lzo decompressor can, if given some really crazy data, possibly
overrun some variable types.  Modify the checking logic to properly
detect overruns before they happen.

Reported-by: "Don A. Bailey" <donb@xxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

Original Linux commit: 206a81c18401c0cde6e579164f752c4b147324ce.

This is CVE-2014-4607 (but not a security issue in Xen, since the code
is only used for loading the Dom0 kernel and _inside_ an eventual DomU
for loading its kernel).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/common/lzo.c
+++ b/xen/common/lzo.c
@@ -375,11 +375,31 @@ int lzo1x_1_compress(const unsigned char
  *  Richard Purdie <rpurdie@xxxxxxxxxxxxxx>
  */
 
-#define HAVE_IP(x)     ((size_t)(ip_end - ip) >= (size_t)(x))
-#define HAVE_OP(x)     ((size_t)(op_end - op) >= (size_t)(x))
-#define NEED_IP(x)     if (!HAVE_IP(x)) goto input_overrun
-#define NEED_OP(x)     if (!HAVE_OP(x)) goto output_overrun
-#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
+#define HAVE_IP(t, x)                              \
+    (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \
+     (((t + x) >= t) && ((t + x) >= x)))
+
+#define HAVE_OP(t, x)                              \
+    (((size_t)(op_end - op) >= (size_t)(t + x)) && \
+     (((t + x) >= t) && ((t + x) >= x)))
+
+#define NEED_IP(t, x)                \
+    do {                             \
+        if (!HAVE_IP(t, x))          \
+            goto input_overrun;      \
+    } while (0)
+
+#define NEED_OP(t, x)                \
+    do {                             \
+        if (!HAVE_OP(t, x))          \
+            goto output_overrun;     \
+    } while (0)
+
+#define TEST_LB(m_pos)               \
+    do {                             \
+        if ((m_pos) < out)           \
+            goto lookbehind_overrun; \
+    } while (0)
 
 int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
                           unsigned char *out, size_t *out_len)
@@ -414,14 +434,14 @@ int lzo1x_decompress_safe(const unsigned
                     while (unlikely(*ip == 0)) {
                         t += 255;
                         ip++;
-                        NEED_IP(1);
+                        NEED_IP(1, 0);
                     }
                     t += 15 + *ip++;
                 }
                 t += 3;
  copy_literal_run:
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-                if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
+                if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) {
                     const unsigned char *ie = ip + t;
                     unsigned char *oe = op + t;
                     do {
@@ -437,8 +457,8 @@ int lzo1x_decompress_safe(const unsigned
                 } else
 #endif
                 {
-                    NEED_OP(t);
-                    NEED_IP(t + 3);
+                    NEED_OP(t, 0);
+                    NEED_IP(t, 3);
                     do {
                         *op++ = *ip++;
                     } while (--t > 0);
@@ -451,7 +471,7 @@ int lzo1x_decompress_safe(const unsigned
                 m_pos -= t >> 2;
                 m_pos -= *ip++ << 2;
                 TEST_LB(m_pos);
-                NEED_OP(2);
+                NEED_OP(2, 0);
                 op[0] = m_pos[0];
                 op[1] = m_pos[1];
                 op += 2;
@@ -475,10 +495,10 @@ int lzo1x_decompress_safe(const unsigned
                 while (unlikely(*ip == 0)) {
                     t += 255;
                     ip++;
-                    NEED_IP(1);
+                    NEED_IP(1, 0);
                 }
                 t += 31 + *ip++;
-                NEED_IP(2);
+                NEED_IP(2, 0);
             }
             m_pos = op - 1;
             next = get_unaligned_le16(ip);
@@ -493,10 +513,10 @@ int lzo1x_decompress_safe(const unsigned
                 while (unlikely(*ip == 0)) {
                     t += 255;
                     ip++;
-                    NEED_IP(1);
+                    NEED_IP(1, 0);
                 }
                 t += 7 + *ip++;
-                NEED_IP(2);
+                NEED_IP(2, 0);
             }
             next = get_unaligned_le16(ip);
             ip += 2;
@@ -510,7 +530,7 @@ int lzo1x_decompress_safe(const unsigned
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
         if (op - m_pos >= 8) {
             unsigned char *oe = op + t;
-            if (likely(HAVE_OP(t + 15))) {
+            if (likely(HAVE_OP(t, 15))) {
                 do {
                     COPY8(op, m_pos);
                     op += 8;
@@ -520,7 +540,7 @@ int lzo1x_decompress_safe(const unsigned
                     m_pos += 8;
                 } while (op < oe);
                 op = oe;
-                if (HAVE_IP(6)) {
+                if (HAVE_IP(6, 0)) {
                     state = next;
                     COPY4(op, ip);
                     op += next;
@@ -528,7 +548,7 @@ int lzo1x_decompress_safe(const unsigned
                     continue;
                 }
             } else {
-                NEED_OP(t);
+                NEED_OP(t, 0);
                 do {
                     *op++ = *m_pos++;
                 } while (op < oe);
@@ -537,7 +557,7 @@ int lzo1x_decompress_safe(const unsigned
 #endif
         {
             unsigned char *oe = op + t;
-            NEED_OP(t);
+            NEED_OP(t, 0);
             op[0] = m_pos[0];
             op[1] = m_pos[1];
             op += 2;
@@ -550,15 +570,15 @@ int lzo1x_decompress_safe(const unsigned
         state = next;
         t = next;
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-        if (likely(HAVE_IP(6) && HAVE_OP(4))) {
+        if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) {
             COPY4(op, ip);
             op += t;
             ip += t;
         } else
 #endif
         {
-            NEED_IP(t + 3);
-            NEED_OP(t);
+            NEED_IP(t, 3);
+            NEED_OP(t, 0);
             while (t > 0) {
                 *op++ = *ip++;
                 t--;


Attachment: lzo-check-overruns.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.