Skip to content

Commit

Permalink
bootconfig: Fix to remove bootconfig data from initrd while boot
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: [email protected]
Fixes: 7684b85 ("bootconfig: Load boot config from the tail of initrd")
Signed-off-by: Masami Hiramatsu <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
  • Loading branch information
mhiramat authored and rostedt committed May 6, 2020
1 parent 6a8b55e commit de462e5
Showing 1 changed file with 52 additions and 17 deletions.
69 changes: 52 additions & 17 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,47 @@ static int __init loglevel(char *str)

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

char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
Expand Down Expand Up @@ -357,37 +398,25 @@ static void __init setup_boot_config(const char *cmdline)
int pos;
u32 size, csum;
char *data, *copy;
u32 *hdr;
int ret;

data = get_boot_config_from_initrd(&size, &csum);
if (!data)
goto not_found;

strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
bootconfig_params);

if (!bootconfig_found)
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) {
pr_err("bootconfig size %d greater than max size %d\n",
size, XBC_DATA_MAX);
return;
}

data = ((void *)hdr) - size;
if ((unsigned long)data < initrd_start)
goto not_found;

if (boot_config_checksum((unsigned char *)data, size) != csum) {
pr_err("bootconfig checksum failed\n");
return;
Expand Down Expand Up @@ -420,8 +449,14 @@ static void __init setup_boot_config(const char *cmdline)
not_found:
pr_err("'bootconfig' found on command line, but no bootconfig found\n");
}

#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)
{
Expand Down

0 comments on commit de462e5

Please sign in to comment.