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

[Xen-changelog] [xen master] lzo: properly check for overruns



commit 504f70b624063bbb32d43cdfe6e8409eaac1fa8e
Author:     Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
AuthorDate: Thu Jul 3 16:39:30 2014 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Jul 3 16:39:30 2014 +0200

    lzo: properly check for overruns
    
    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>
    Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 xen/common/lzo.c |   62 +++++++++++++++++++++++++++++++++++------------------
 1 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/xen/common/lzo.c b/xen/common/lzo.c
index 7338aee..0bec625 100644
--- a/xen/common/lzo.c
+++ b/xen/common/lzo.c
@@ -375,11 +375,31 @@ int lzo1x_1_compress(const unsigned char *in, size_t 
in_len,
  *  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 char *in, size_t 
in_len,
                     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 char *in, size_t 
in_len,
                 } 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 char *in, size_t 
in_len,
                 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 char *in, size_t 
in_len,
                 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 char *in, size_t 
in_len,
                 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 char *in, size_t 
in_len,
 #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 char *in, size_t 
in_len,
                     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 char *in, size_t 
in_len,
                     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 char *in, size_t 
in_len,
 #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 char *in, size_t 
in_len,
         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--;
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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