]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Fix LZ4_uncompress_unknownOutputSize caused panic
authorFeng Sun <loyou85@gmail.com>
Fri, 19 May 2017 20:45:46 +0000 (04:45 +0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 19 May 2017 20:45:46 +0000 (13:45 -0700)
Sync with kernel patches for lz4

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/log/lib/lz4

4a3a99 lz4: add overrun checks to lz4_uncompress_unknownoutputsize()
d5e7ca LZ4 : fix the data abort issue
bea2b5 lib/lz4: Pull out constant tables
99b7e9 lz4: fix system halt at boot kernel on x86_64

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Feng Sun <loyou85@gmail.com>
Closes #5975
Closes #5973

module/zfs/lz4.c

index 54e5be659a7a2c6f82294b2bd182aeee95b989ab..9b9a2e6936e05d343ba2021e527e2e132a91d5b8 100644 (file)
@@ -873,6 +873,11 @@ real_LZ4_compress(const char *source, char *dest, int isize, int osize)
  *     its code is not present here.
  */
 
+static const int dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+static const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
 static int
 LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
     int maxOutputSize)
@@ -886,11 +891,6 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
        BYTE *const oend = op + maxOutputSize;
        BYTE *cpy;
 
-       size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
-#if LZ4_ARCH64
-       size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
-#endif
-
        /* Main Loop */
        while (ip < iend) {
                unsigned token;
@@ -902,6 +902,8 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
                        int s = 255;
                        while ((ip < iend) && (s == 255)) {
                                s = *ip++;
+                               if (unlikely(length > (size_t)(length + s)))
+                                       goto _output_error;
                                length += s;
                        }
                }
@@ -944,6 +946,8 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
                if ((length = (token & ML_MASK)) == ML_MASK) {
                        while (ip < iend) {
                                int s = *ip++;
+                               if (unlikely(length > (size_t)(length + s)))
+                                       goto _output_error;
                                length += s;
                                if (s == 255)
                                        continue;
@@ -953,7 +957,7 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
                /* copy repeated sequence */
                if (unlikely(op - ref < STEPSIZE)) {
 #if LZ4_ARCH64
-                       size_t dec64 = dec64table[op-ref];
+                       int dec64 = dec64table[op - ref];
 #else
                        const int dec64 = 0;
 #endif
@@ -963,7 +967,7 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
                        op[3] = ref[3];
                        op += 4;
                        ref += 4;
-                       ref -= dec32table[op-ref];
+                       ref -= dec32table[op - ref];
                        A32(op) = A32(ref);
                        op += STEPSIZE - 4;
                        ref -= dec64;
@@ -978,6 +982,13 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
                                 * destination buffer
                                 */
                                goto _output_error;
+#if LZ4_ARCH64
+                       if ((ref + COPYLENGTH) > oend)
+#else
+                       if ((ref + COPYLENGTH) > oend ||
+                           (op + COPYLENGTH) > oend)
+#endif
+                               goto _output_error;
                        LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
                        while (op < cpy)
                                *op++ = *ref++;
@@ -999,7 +1010,7 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
 
        /* write overflow error detected */
        _output_error:
-       return (int)(-(((char *)ip) - source));
+       return (-1);
 }
 
 void