mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-01 12:04:08 +00:00
bootconfig: Fix to remove bootconfig data from initrd while boot
If there is a bootconfig data in the tail of initrd/initramfs,
initrd image sanity check caused an error while decompression
stage as follows.
[ 0.883882] Unpacking initramfs...
[ 2.696429] Initramfs unpacking failed: invalid magic at start of compressed archive
This error will be ignored if CONFIG_BLK_DEV_RAM=n,
but CONFIG_BLK_DEV_RAM=y the kernel failed to mount rootfs
and causes a panic.
To fix this issue, shrink down the initrd_end for removing
tailing bootconfig data while boot the kernel.
Link: http://lkml.kernel.org/r/158788401014.24243.17424755854115077915.stgit@devnote2
Cc: Borislav Petkov <bp@alien8.de>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: stable@vger.kernel.org
Fixes: 7684b8582c
("bootconfig: Load boot config from the tail of initrd")
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
6a8b55ed40
commit
de462e5f10
1 changed files with 52 additions and 17 deletions
69
init/main.c
69
init/main.c
|
@ -257,6 +257,47 @@ static int __init loglevel(char *str)
|
||||||
|
|
||||||
early_param("loglevel", loglevel);
|
early_param("loglevel", loglevel);
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
|
static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
|
||||||
|
{
|
||||||
|
u32 size, csum;
|
||||||
|
char *data;
|
||||||
|
u32 *hdr;
|
||||||
|
|
||||||
|
if (!initrd_end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
|
||||||
|
if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hdr = (u32 *)(data - 8);
|
||||||
|
size = hdr[0];
|
||||||
|
csum = hdr[1];
|
||||||
|
|
||||||
|
data = ((void *)hdr) - size;
|
||||||
|
if ((unsigned long)data < initrd_start) {
|
||||||
|
pr_err("bootconfig size %d is greater than initrd size %ld\n",
|
||||||
|
size, initrd_end - initrd_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove bootconfig from initramfs/initrd */
|
||||||
|
initrd_end = (unsigned long)data;
|
||||||
|
if (_size)
|
||||||
|
*_size = size;
|
||||||
|
if (_csum)
|
||||||
|
*_csum = csum;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_BOOT_CONFIG
|
#ifdef CONFIG_BOOT_CONFIG
|
||||||
|
|
||||||
char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
|
char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
|
||||||
|
@ -357,9 +398,12 @@ static void __init setup_boot_config(const char *cmdline)
|
||||||
int pos;
|
int pos;
|
||||||
u32 size, csum;
|
u32 size, csum;
|
||||||
char *data, *copy;
|
char *data, *copy;
|
||||||
u32 *hdr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
data = get_boot_config_from_initrd(&size, &csum);
|
||||||
|
if (!data)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
||||||
parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
|
parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
|
||||||
bootconfig_params);
|
bootconfig_params);
|
||||||
|
@ -367,27 +411,12 @@ static void __init setup_boot_config(const char *cmdline)
|
||||||
if (!bootconfig_found)
|
if (!bootconfig_found)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!initrd_end)
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
|
|
||||||
if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
hdr = (u32 *)(data - 8);
|
|
||||||
size = hdr[0];
|
|
||||||
csum = hdr[1];
|
|
||||||
|
|
||||||
if (size >= XBC_DATA_MAX) {
|
if (size >= XBC_DATA_MAX) {
|
||||||
pr_err("bootconfig size %d greater than max size %d\n",
|
pr_err("bootconfig size %d greater than max size %d\n",
|
||||||
size, XBC_DATA_MAX);
|
size, XBC_DATA_MAX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = ((void *)hdr) - size;
|
|
||||||
if ((unsigned long)data < initrd_start)
|
|
||||||
goto not_found;
|
|
||||||
|
|
||||||
if (boot_config_checksum((unsigned char *)data, size) != csum) {
|
if (boot_config_checksum((unsigned char *)data, size) != csum) {
|
||||||
pr_err("bootconfig checksum failed\n");
|
pr_err("bootconfig checksum failed\n");
|
||||||
return;
|
return;
|
||||||
|
@ -420,8 +449,14 @@ static void __init setup_boot_config(const char *cmdline)
|
||||||
not_found:
|
not_found:
|
||||||
pr_err("'bootconfig' found on command line, but no bootconfig found\n");
|
pr_err("'bootconfig' found on command line, but no bootconfig found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define setup_boot_config(cmdline) do { } while (0)
|
|
||||||
|
static void __init setup_boot_config(const char *cmdline)
|
||||||
|
{
|
||||||
|
/* Remove bootconfig data from initrd */
|
||||||
|
get_boot_config_from_initrd(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int __init warn_bootconfig(char *str)
|
static int __init warn_bootconfig(char *str)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue