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 <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Feng Sun <loyou85@gmail.com>
Closes #5975 
Closes #5973
This commit is contained in:
Feng Sun 2017-05-20 04:45:46 +08:00 committed by Brian Behlendorf
parent bec1067d54
commit f871ab6ea2

View File

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