Patch "lib/decompressors: use real out buf size for gunzip with kernel" has been added to the 4.1-stable tree
Subsystems (8)
This is a note to let you know that I've just added the patch titled
lib/decompressors: use real out buf size for gunzip with kernel
to the 4.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
lib-decompressors-use-real-out-buf-size-for-gunzip-with-kernel.patch
and it can be found in the queue-4.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
2d3862d26e67a59340ba1cf1748196c76c5787deMon Sep 17 00:00:00 2001
From: Yinghai Lu <[email protected]>
Date: Wed, 9 Sep 2015 15:39:12 -0700
Subject: lib/decompressors: use real out buf size for gunzip with kernel
From: Yinghai Lu <[email protected]>
commit 2d3862d26e67a59340ba1cf1748196c76c5787de upstream.
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.
--- arch/arm/boot/compressed/decompress.c | 2 +- arch/m32r/boot/compressed/misc.c | 3 ++- arch/mips/boot/compressed/decompress.c | 4 ++-- arch/s390/boot/compressed/misc.c | 2 +- arch/sh/boot/compressed/misc.c | 2 +- arch/unicore32/boot/compressed/misc.c | 4 ++-- arch/x86/boot/compressed/misc.c | 3 ++- lib/decompress_bunzip2.c | 6 +++--- lib/decompress_inflate.c | 31 ++++++++++++++++++++++++++----- lib/decompress_unlz4.c | 6 +++--- lib/decompress_unlzma.c | 7 +++---- lib/decompress_unlzo.c | 13 ++++++++++++- lib/decompress_unxz.c | 12 +++++++++++- 13 files changed, 69 insertions(+), 26 deletions(-)
arch/arm/boot/compressed/decompress.c +1 -1
@@ -57,5 +57,5 @@ extern char * strstr(const char * s1, coint do_decompress (u8 *input,int len,u8 *output,void (*error)(char *x)) { -return decompress (input, len,NULL ,NULL , output,NULL , error); +return __decompress (input, len,NULL ,NULL , output,0 ,NULL , error); }
arch/m32r/boot/compressed/misc.c +2 -1
@@ -86,6 +86,7 @@ decompress_kernel(int mmu_on, unsigned c free_mem_end_ptr = free_mem_ptr +BOOT_HEAP_SIZE ;puts ("\nDecompressing Linux... " ); -decompress (input_data, input_len,NULL ,NULL , output_data,NULL , error); +__decompress (input_data, input_len,NULL ,NULL , output_data,0 , +NULL , error);puts ("done.\nBooting the kernel.\n" ); }
arch/mips/boot/compressed/decompress.c +2 -2
@@ -111,8 +111,8 @@ void decompress_kernel(unsigned long booputs ("\n" );/* Decompress the kernel with according algorithm */ -decompress ((char *)zimage_start, zimage_size,0 ,0 , - (void *)VMLINUX_LOAD_ADDRESS_ULL ,0 , error); +__decompress ((char *)zimage_start, zimage_size,0 ,0 , + (void *)VMLINUX_LOAD_ADDRESS_ULL ,0 ,0 , error);/* FIXME: should we flush cache here? */ puts ("Now, booting the kernel...\n" );
arch/s390/boot/compressed/misc.c +1 -1
@@ -167,7 +167,7 @@ unsigned long decompress_kernel(void)#endif puts ("Uncompressing Linux... " ); -decompress (input_data, input_len,NULL ,NULL , output,NULL , error); +__decompress (input_data, input_len,NULL ,NULL , output,0 ,NULL , error);puts ("Ok, booting the kernel.\n" );return (unsigned long ) output; }
arch/sh/boot/compressed/misc.c +1 -1
@@ -132,7 +132,7 @@ void decompress_kernel(void)puts ("Uncompressing Linux... " );cache_control (CACHE_ENABLE ); -decompress (input_data, input_len,NULL ,NULL , output,NULL , error); +__decompress (input_data, input_len,NULL ,NULL , output,0 ,NULL , error);cache_control (CACHE_DISABLE );puts ("Ok, booting the kernel.\n" ); }
arch/unicore32/boot/compressed/misc.c +2 -2
@@ -119,8 +119,8 @@ unsigned long decompress_kernel(unsigned output_ptr =get_unaligned_le32 (tmp);arch_decomp_puts ("Uncompressing Linux..." ); -decompress (input_data, input_data_end - input_data,NULL ,NULL , - output_data,NULL , error); +__decompress (input_data, input_data_end - input_data,NULL ,NULL , + output_data,0 ,NULL , error);arch_decomp_puts (" done, booting the kernel.\n" );return output_ptr; }
arch/x86/boot/compressed/misc.c +2 -1
@@ -424,7 +424,8 @@ asmlinkage __visible void *decompress_ke#endif debug_putstr ("\nDecompressing Linux... " ); -decompress (input_data, input_len,NULL ,NULL , output,NULL , error); +__decompress (input_data, input_len,NULL ,NULL , output, output_len, +NULL , error);parse_elf (output);/* * 32-bit always performs relocations. 64-bit relocations are only
lib/decompress_bunzip2.c +3 -3
@@ -743,12 +743,12 @@ exit_0: }#ifdef PREBOOT -STATIC int INIT decompress(unsigned char *buf, long len, +STATIC int INIT __decompress(unsigned char *buf, long len,long (*fill)(void *,unsigned long ),long (*flush)(void *,unsigned long ), -unsigned char *outbuf, +unsigned char *outbuf,long olen,long *pos, -void (*error)(char *x)) +void (*error)(char *x)) {return bunzip2 (buf, len -4 , fill, flush, outbuf, pos, error); }
lib/decompress_inflate.c +26 -5
@@ -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, un }/* 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
lib/decompress_unlz4.c +3 -3
@@ -196,12 +196,12 @@ exit_0: }#ifdef PREBOOT -STATIC int INIT decompress(unsigned char *buf, long in_len, +STATIC int INIT __decompress(unsigned char *buf, long in_len,long (*fill)(void *,unsigned long ),long (*flush)(void *,unsigned long ), -unsigned char *output, +unsigned char *output,long out_len,long *posp, -void (*error)(char *x) +void (*error)(char *x) ) {return unlz4 (buf, in_len -4 , fill, flush, output, posp, error);
lib/decompress_unlzma.c +3 -4
@@ -667,13 +667,12 @@ exit_0: }#ifdef PREBOOT -STATIC int INIT decompress(unsigned char *buf, long in_len, +STATIC int INIT __decompress(unsigned char *buf, long in_len,long (*fill)(void *,unsigned long ),long (*flush)(void *,unsigned long ), -unsigned char *output, +unsigned char *output,long out_len,long *posp, -void (*error)(char *x) - ) +void (*error)(char *x)) {return unlzma (buf, in_len -4 , fill, flush, output, posp, error); }
lib/decompress_unlzo.c +12 -1
@@ -31,6 +31,7 @@*/ #ifdef STATIC +#define PREBOOT #include "lzo/lzo1x_decompress_safe.c" #else #include <linux/decompress/unlzo.h>
@@ -287,4 +288,14 @@ exit:return ret; } -#define decompress unlzo +#ifdef PREBOOT +STATIC int INIT __decompress(unsigned char *buf, long len, +long (*fill)(void *,unsigned long ), +long (*flush)(void *,unsigned long ), +unsigned char *out_buf,long olen, +long *pos, +void (*error)(char *x)) +{ +return unlzo (buf, len, fill, flush, out_buf, pos, error); +} +#endif
lib/decompress_unxz.c +11 -1
@@ -394,4 +394,14 @@ error_alloc_state:* This macro is used by architecture-specific files to decompress * the kernel image. */ -#define decompress unxz +#ifdef XZ_PREBOOT +STATIC int INIT __decompress(unsigned char *buf, long len, +long (*fill)(void *,unsigned long ), +long (*flush)(void *,unsigned long ), +unsigned char *out_buf,long olen, +long *pos, +void (*error)(char *x)) +{ +return unxz (buf, len, fill, flush, out_buf, pos, error); +} +#endif
Patches currently in stable-queue which might be from [email protected] are
queue-4.1/x86-mm-initialize-pmd_idx-in-page_table_range_init_count.patch queue-4.1/lib-decompressors-use-real-out-buf-size-for-gunzip-with-kernel.patch queue-4.1/mm-check-if-section-present-during-memory-block-registering.patch