Commit de462e5f authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Steven Rostedt (VMware)

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: 7684b858 ("bootconfig: Load boot config from the tail of initrd")
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 6a8b55ed
...@@ -257,6 +257,47 @@ static int __init loglevel(char *str) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment