mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-09 11:30:02 +00:00
lib/decompressors: use real out buf size for gunzip with kernel
commit2d3862d26eupstream. When loading x86 64bit kernel above 4GiB with patched grub2, got kernel gunzip error. | early console in decompress_kernel | decompress_kernel: | input: [0x807f2143b4-0x807ff61aee] | output: [0x807cc00000-0x807f3ea29b] 0x027ea29c: output_len | boot via startup_64 | KASLR using RDTSC... | new output: [0x46fe000000-0x470138cfff] 0x0338d000: output_run_size | decompress: [0x46fe000000-0x47007ea29b] <=== [0x807f2143b4-0x807ff61aee] | | Decompressing Linux... gz... | | uncompression error | | -- System halted the new buffer is at 0x46fe000000ULL, decompressor_gzip is using 0xffffffb901ffffff as out_len. gunzip in lib/zlib_inflate/inflate.c cap that len to 0x01ffffff and decompress fails later. We could hit this problem with crashkernel booting that uses kexec loading kernel above 4GiB. We have decompress_* support: 1. inbuf[]/outbuf[] for kernel preboot. 2. inbuf[]/flush() for initramfs 3. fill()/flush() for initrd. This bug only affect kernel preboot path that use outbuf[]. Add __decompress and take real out_buf_len for gunzip instead of guessing wrong buf size. Fixes:1431574a1c(lib/decompressors: fix "no limit" output buffer length) Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Alexandre Courbot <acourbot@nvidia.com> Cc: Jon Medhurst <tixy@linaro.org> Cc: Stephen Warren <swarren@wwwdotorg.org> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d9fe7559fd
commit
a116acdf9f
@@ -1,4 +1,5 @@
|
||||
#ifdef STATIC
|
||||
#define PREBOOT
|
||||
/* Pre-boot environment: included */
|
||||
|
||||
/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
|
||||
@@ -33,23 +34,23 @@ static long INIT nofill(void *buffer, unsigned long len)
|
||||
}
|
||||
|
||||
/* Included from initramfs et al code */
|
||||
STATIC int INIT gunzip(unsigned char *buf, long len,
|
||||
STATIC int INIT __gunzip(unsigned char *buf, long len,
|
||||
long (*fill)(void*, unsigned long),
|
||||
long (*flush)(void*, unsigned long),
|
||||
unsigned char *out_buf,
|
||||
unsigned char *out_buf, long out_len,
|
||||
long *pos,
|
||||
void(*error)(char *x)) {
|
||||
u8 *zbuf;
|
||||
struct z_stream_s *strm;
|
||||
int rc;
|
||||
size_t out_len;
|
||||
|
||||
rc = -1;
|
||||
if (flush) {
|
||||
out_len = 0x8000; /* 32 K */
|
||||
out_buf = malloc(out_len);
|
||||
} else {
|
||||
out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
|
||||
if (!out_len)
|
||||
out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
|
||||
}
|
||||
if (!out_buf) {
|
||||
error("Out of memory while allocating output buffer");
|
||||
@@ -181,4 +182,24 @@ gunzip_nomem1:
|
||||
return rc; /* returns Z_OK (0) if successful */
|
||||
}
|
||||
|
||||
#define decompress gunzip
|
||||
#ifndef PREBOOT
|
||||
STATIC int INIT gunzip(unsigned char *buf, long len,
|
||||
long (*fill)(void*, unsigned long),
|
||||
long (*flush)(void*, unsigned long),
|
||||
unsigned char *out_buf,
|
||||
long *pos,
|
||||
void (*error)(char *x))
|
||||
{
|
||||
return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
|
||||
}
|
||||
#else
|
||||
STATIC int INIT __decompress(unsigned char *buf, long len,
|
||||
long (*fill)(void*, unsigned long),
|
||||
long (*flush)(void*, unsigned long),
|
||||
unsigned char *out_buf, long out_len,
|
||||
long *pos,
|
||||
void (*error)(char *x))
|
||||
{
|
||||
return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user