mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 15:14:30 -04:00
Historically calls to __decompress() didn't specify "out_len" parameter
on many architectures including s390, expecting that no writes beyond
uncompressed kernel image are performed. This has changed since commit
2aa14b1ab2 ("zstd: import usptream v1.5.2") which includes zstd library
commit 6a7ede3dfccb ("Reduce size of dctx by reutilizing dst buffer
(#2751)"). Now zstd decompression code might store literal buffer in
the unwritten portion of the destination buffer. Since "out_len" is
not set, it is considered to be unlimited and hence free to use for
optimization needs. On s390 this might corrupt initrd or ipl report
which are often placed right after the decompressor buffer. Luckily the
size of uncompressed kernel image is already known to the decompressor,
so to avoid the problem simply specify it in the "out_len" parameter.
Link: https://github.com/facebook/zstd/commit/6a7ede3dfccb
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Link: https://lore.kernel.org/r/patch-1.thread-41c676.git-41c676c2d153.your-ad-here.call-01675030179-ext-9637@work.hours
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
86 lines
1.9 KiB
C
86 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Definitions and wrapper functions for kernel decompressor
|
|
*
|
|
* Copyright IBM Corp. 2010
|
|
*
|
|
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <asm/page.h>
|
|
#include "decompressor.h"
|
|
|
|
/*
|
|
* gzip declarations
|
|
*/
|
|
#define STATIC static
|
|
|
|
#undef memset
|
|
#undef memcpy
|
|
#undef memmove
|
|
#define memmove memmove
|
|
#define memzero(s, n) memset((s), 0, (n))
|
|
|
|
#if defined(CONFIG_KERNEL_BZIP2)
|
|
#define BOOT_HEAP_SIZE 0x400000
|
|
#elif defined(CONFIG_KERNEL_ZSTD)
|
|
#define BOOT_HEAP_SIZE 0x30000
|
|
#else
|
|
#define BOOT_HEAP_SIZE 0x10000
|
|
#endif
|
|
|
|
static unsigned long free_mem_ptr = (unsigned long) _end;
|
|
static unsigned long free_mem_end_ptr = (unsigned long) _end + BOOT_HEAP_SIZE;
|
|
|
|
#ifdef CONFIG_KERNEL_GZIP
|
|
#include "../../../../lib/decompress_inflate.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_BZIP2
|
|
#include "../../../../lib/decompress_bunzip2.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_LZ4
|
|
#include "../../../../lib/decompress_unlz4.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_LZMA
|
|
#include "../../../../lib/decompress_unlzma.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_LZO
|
|
#include "../../../../lib/decompress_unlzo.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_XZ
|
|
#include "../../../../lib/decompress_unxz.c"
|
|
#endif
|
|
|
|
#ifdef CONFIG_KERNEL_ZSTD
|
|
#include "../../../../lib/decompress_unzstd.c"
|
|
#endif
|
|
|
|
#define decompress_offset ALIGN((unsigned long)_end + BOOT_HEAP_SIZE, PAGE_SIZE)
|
|
|
|
unsigned long mem_safe_offset(void)
|
|
{
|
|
/*
|
|
* due to 4MB HEAD_SIZE for bzip2
|
|
* 'decompress_offset + vmlinux.image_size' could be larger than
|
|
* kernel at final position + its .bss, so take the larger of two
|
|
*/
|
|
return max(decompress_offset + vmlinux.image_size,
|
|
vmlinux.default_lma + vmlinux.image_size + vmlinux.bss_size);
|
|
}
|
|
|
|
void *decompress_kernel(void)
|
|
{
|
|
void *output = (void *)decompress_offset;
|
|
|
|
__decompress(_compressed_start, _compressed_end - _compressed_start,
|
|
NULL, NULL, output, vmlinux.image_size, NULL, error);
|
|
return output;
|
|
}
|