On Fri, 11 Sep 2026 01:29:48 +0900 Sang-Heon Jeon <[email protected]> wrote:
> On Fri, Sep 11, 2026 at 12:15 AM Masami Hiramatsu (Google) > <[email protected]> wrote: > > > > From: Masami Hiramatsu (Google) <[email protected]> > > > > Sashiko reported that in get_boot_config_from_initrd(), a crafted initrd > > with a huge bootconfig size (such as 0xFFFFFFFF) can cause the pointer > > arithmetic: > > > > data = ((void *)hdr) - size; > > > > to wrap around on 32-bit systems (or when pointer subtraction overflows). > > Because data wraps around, the subsequent bounds check: > > > > if ((unsigned long)data < initrd_start) > > > > evaluates to false, bypassing the check. The kernel then calls > > xbc_calc_checksum(data, size), which attempts to read 4GB of memory, > > hitting unmapped pages and triggering a fatal kernel page fault during > > early boot. Furthermore, on 64-bit systems with an initrd > 4.29 GB, an > > unbounded 32-bit size can similarly bypass the initrd_start check. > > > > Fix this by: > > 1. Ensuring the initrd is at least large enough to contain the bootconfig > > footer and verifying hdr is within the initrd bounds. > > 2. Checking that size does not exceed XBC_DATA_MAX and does not exceed > > the available space between initrd_start and hdr before performing > > pointer subtraction. > > > > Fixes: de462e5f1071 ("bootconfig: Fix to remove bootconfig data from initrd > > while boot") > > Cc: [email protected] > > Reported-by: Sashiko <[email protected]> > > Closes: > > https://lore.kernel.org/all/[email protected]/ > > Assisted-by: Antigravity:gemini-3.8-flash > > Signed-off-by: Masami Hiramatsu (Google) <[email protected]> > > --- > > Changes in v4: > > - Accurate the error message for size > XBC_DATA_MAX in > > get_boot_config_from_initrd(). > > - Remove redundant (and wrong) size >= XBC_DATA_MAX check from > > setup_boot_config(). > > --- > > init/main.c | 25 +++++++++++++++---------- > > 1 file changed, 15 insertions(+), 10 deletions(-) > > > > diff --git a/init/main.c b/init/main.c > > index 2613d3f9b3ce..16749bb7a219 100644 > > --- a/init/main.c > > +++ b/init/main.c > > @@ -277,7 +277,8 @@ static void * __init get_boot_config_from_initrd(size_t > > *_size) > > u8 *hdr; > > int i; > > > > - if (!initrd_end) > > + if (!initrd_end || initrd_end < initrd_start || > > + initrd_end - initrd_start < BOOTCONFIG_MAGIC_LEN + 8) > > return NULL; > > (nit) how about moving BOOTCONFIG_FOOTER_SIZE from tools and using it instead? OK, that will be done in cleanup patch. > > > data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; > > @@ -294,16 +295,26 @@ static void * __init > > get_boot_config_from_initrd(size_t *_size) > > > > found: > > hdr = (u8 *)(data - 8); > > + if ((unsigned long)hdr < initrd_start) > > + return NULL; > > + > > size = get_unaligned_le32(hdr); > > csum = get_unaligned_le32(hdr + 4); > > > > - data = ((void *)hdr) - size; > > - if ((unsigned long)data < initrd_start) { > > - pr_err("bootconfig size %d is greater than initrd size > > %ld\n", > > + if (size > XBC_DATA_MAX) { > > + pr_err("bootconfig size %u is greater than max size %d\n", > > + size, XBC_DATA_MAX); > > + return NULL; > > + } > > + > > + if (size > ((unsigned long)hdr - initrd_start)) { > > + pr_err("bootconfig size %u is greater than initrd size > > %lu\n", > > size, initrd_end - initrd_start); > > return NULL; > > } > > > > + data = ((void *)hdr) - size; > > + > > if (xbc_calc_checksum(data, size) != csum) { > > pr_err("bootconfig checksum failed\n"); > > return NULL; > > @@ -394,12 +405,6 @@ static void __init setup_boot_config(void) > > return; > > } > > > > - if (size >= XBC_DATA_MAX) { > > - pr_err("bootconfig size %ld greater than max size %d\n", > > - (long)size, XBC_DATA_MAX); > > - return; > > - } > > - > > Nice cleanup! > > > ret = xbc_init(data, size, &msg, &pos); > > if (ret < 0) { > > if (pos < 0) > > > > Thanks for doing this work! > > Reviewed-by: Sang-Heon Jeon <[email protected]> > Thanks! -- Masami Hiramatsu (Google) <[email protected]>
