lkml.org 
[lkml]   [2020]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.6 018/606] bootconfig: Fix to remove bootconfig data from initrd while boot
    Date
    From: Masami Hiramatsu <mhiramat@kernel.org>

    commit de462e5f10718517bacf2f84c8aa2804567ef7df upstream.

    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: 7684b8582c24 ("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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    init/main.c | 69 ++++++++++++++++++++++++++++++++++++++++-------------
    1 file changed, 52 insertions(+), 17 deletions(-)

    diff --git a/init/main.c b/init/main.c
    index 9c7948b3763a..ee0345e7e9f1 100644
    --- a/init/main.c
    +++ b/init/main.c
    @@ -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;
    @@ -355,9 +396,12 @@ static void __init setup_boot_config(const char *cmdline)
    static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
    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);
    @@ -365,27 +409,12 @@ static void __init setup_boot_config(const char *cmdline)
    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;
    @@ -414,8 +443,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)
    {
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-06-09 02:42    [W:2.870 / U:0.352 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site