summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorFeng Sun <[email protected]>2017-05-20 04:45:46 +0800
committerBrian Behlendorf <[email protected]>2017-05-19 13:45:46 -0700
commitf871ab6ea2dd9a3b9fae157ff0a7665bb269c565 (patch)
treeeed5d96ae5d009b943d08f93b95643ec5015809a /module/zfs
parentbec1067d54a004cb52a4a6762bfa1d4a30300865 (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.c27
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