diff options
author | Feng Sun <[email protected]> | 2017-05-20 04:45:46 +0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-05-19 13:45:46 -0700 |
commit | f871ab6ea2dd9a3b9fae157ff0a7665bb269c565 (patch) | |
tree | eed5d96ae5d009b943d08f93b95643ec5015809a /module/zfs | |
parent | bec1067d54a004cb52a4a6762bfa1d4a30300865 (diff) |
Fix LZ4_uncompress_unknownOutputSize caused panic
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 <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Feng Sun <[email protected]>
Closes #5975
Closes #5973
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/lz4.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/module/zfs/lz4.c b/module/zfs/lz4.c index 54e5be659..9b9a2e693 100644 --- a/module/zfs/lz4.c +++ b/module/zfs/lz4.c @@ -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 |