From 2878d76d865e26a6728298c9449f56938c8c0515 Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 11 Sep 2026 23:30:20 +0900 Subject: [PATCH 1/8] bootconfig: merge _xbc_exit() into xbc_exit() Since commit 87ce9e83ab8b ("memblock, treewide: make memblock_free() handle late freeing"), both branches of xbc_free_mem() call memblock_free(), and the early argument has no effect. memblock_free() also does nothing if addr is NULL, so the check before the call is redundant. So remove the argument and the NULL check, and merge _xbc_exit() into xbc_exit(). No functional change. Link: https://lore.kernel.org/all/20260908165712.1703439-1-ekffu200098@gmail.com/ Signed-off-by: Sang-Heon Jeon Signed-off-by: Masami Hiramatsu (Google) --- include/linux/bootconfig.h | 7 +------ lib/bootconfig.c | 22 +++++++++------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index deda507500da..fdc15b6f4d1b 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -291,12 +291,7 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos); int __init xbc_get_info(int *node_size, size_t *data_size); /* XBC cleanup data structures */ -void __init _xbc_exit(bool early); - -static __always_inline void xbc_exit(void) -{ - _xbc_exit(false); -} +void __init xbc_exit(void); /* XBC embedded bootconfig data in kernel */ #ifdef CONFIG_BOOT_CONFIG_EMBED diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 89c88e359179..aba11caf6903 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -187,12 +187,9 @@ static inline void * __init xbc_alloc_mem(size_t size) return memblock_alloc(size, SMP_CACHE_BYTES); } -static inline void __init xbc_free_mem(void *addr, size_t size, bool early) +static inline void __init xbc_free_mem(void *addr, size_t size) { - if (early) - memblock_free(addr, size); - else if (addr) - memblock_free(addr, size); + memblock_free(addr, size); } #else /* !__KERNEL__ */ @@ -202,7 +199,7 @@ static inline void *xbc_alloc_mem(size_t size) return calloc(1, size); } -static inline void xbc_free_mem(void *addr, size_t size, bool early) +static inline void xbc_free_mem(void *addr, size_t size) { free(addr); } @@ -1123,20 +1120,19 @@ static int __init xbc_parse_tree(void) } /** - * _xbc_exit() - Clean up all parsed bootconfig - * @early: Set true if this is called before budy system is initialized. + * xbc_exit() - Clean up all parsed bootconfig * * This clears all data structures of parsed bootconfig on memory. * If you need to reuse xbc_init() with new boot config, you can * use this. */ -void __init _xbc_exit(bool early) +void __init xbc_exit(void) { - xbc_free_mem(xbc_data, xbc_data_size, early); + xbc_free_mem(xbc_data, xbc_data_size); xbc_data = NULL; xbc_data_size = 0; xbc_node_num = 0; - xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early); + xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX); xbc_nodes = NULL; brace_index = 0; } @@ -1189,7 +1185,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos) if (!xbc_nodes) { if (emsg) *emsg = "Failed to allocate bootconfig nodes"; - _xbc_exit(true); + xbc_exit(); return -ENOMEM; } @@ -1202,7 +1198,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos) *epos = xbc_err_pos; if (emsg) *emsg = xbc_err_msg; - _xbc_exit(true); + xbc_exit(); } else { ret = xbc_node_num; } From a57b5001e3cb4aeaf2afcca09ab731c829cb2077 Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 11 Sep 2026 01:30:48 +0900 Subject: [PATCH 2/8] bootconfig: remove redundant assignment in xbc_parse_array() After the loop, node is the last array value that xbc_add_child() added, and xbc_parse_array() sets node->child to 0. xbc_init_node() already set node->child to 0 when the value was added, and node->child is not modified after that, so the assignment is redundant. So remove the assignment. No functional change. Link: https://lore.kernel.org/all/20260910163051.1973775-1-ekffu200098@gmail.com/ Signed-off-by: Sang-Heon Jeon Signed-off-by: Masami Hiramatsu (Google) --- lib/bootconfig.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/bootconfig.c b/lib/bootconfig.c index aba11caf6903..12dd259d490e 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -833,7 +833,6 @@ static int __init xbc_parse_array(char **__v) return -ENOMEM; *__v = next; } while (c == ','); - node->child = 0; return c; } From 6dc993d4520fdaa083c8871e5fee443117d87057 Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 11 Sep 2026 01:31:50 +0900 Subject: [PATCH 3/8] tools/bootconfig: remove unused PAGE_SIZE macro PAGE_SIZE in tools/bootconfig has never been used, so remove the definition. No functional change. Link: https://lore.kernel.org/all/20260910163155.1974118-1-ekffu200098@gmail.com/ Signed-off-by: Sang-Heon Jeon Signed-off-by: Masami Hiramatsu (Google) --- tools/bootconfig/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index 17d971d47f87..522a90bb22c2 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -134,8 +134,6 @@ static void xbc_show_list(void) } } -#define PAGE_SIZE 4096 - static int load_xbc_fd(int fd, char **buf, int size) { int ret; From 958c01049e0a81a02370c9fce50670cda8478b1b Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 4 Sep 2026 00:23:15 +0900 Subject: [PATCH 4/8] bootconfig: Skip printing early params to cmdline from bootconfig If user configures `kernel.key` in bootconfig, the 'key' is shown in kernel cmdline (/proc/cmdline) and kernel boot parameter handler associated with 'key' is invoked. However, since the bootconfig does not support the parameter defined with early_param, those keys are shown in '/proc/cmdline' but not handled by kernel. This could easily mislead users who expected to be able to specify early parameters via the boot configuration, leading them to wonder why it doesn't work. Let's skip printing out early params to cmdline buffer, and warn if there is such parameters in bootconfig. Link: https://lore.kernel.org/all/178844899530.263905.7707547252181797215.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) --- include/linux/bootconfig.h | 10 ++++- init/main.c | 75 ++++++++++++++++++++++++++++++++++---- lib/bootconfig.c | 16 +++++--- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index fdc15b6f4d1b..6de07eac761b 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -266,7 +266,15 @@ int __init xbc_node_compose_key_after(struct xbc_node *root, struct xbc_node *node, char *buf, size_t size); /* Render key/value pairs under @root as a flat cmdline string */ -int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root); +typedef bool (*xbc_cmdline_filter_fn)(struct xbc_node *node, const char *key, void *data); + +int __init xbc_snprint_cmdline_filter(char *buf, size_t size, struct xbc_node *root, + xbc_cmdline_filter_fn filter, void *data); + +static inline int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) +{ + return xbc_snprint_cmdline_filter(buf, size, root, NULL, NULL); +} /** * xbc_node_compose_key() - Compose full key string of the XBC node diff --git a/init/main.c b/init/main.c index 16749bb7a219..d2ad726b515f 100644 --- a/init/main.c +++ b/init/main.c @@ -336,9 +336,64 @@ static void * __init get_boot_config_from_initrd(size_t *_size) #ifdef CONFIG_BOOT_CONFIG -/* Make an extra command line under given key word */ -static char * __init xbc_make_cmdline(const char *key) +/* Check if a parameter name matches an obs_kernel_param entry */ +static bool __init match_obs_param(const char *param, const char *pattern) { + size_t n = strlen(pattern); + + if (n > 0 && pattern[n - 1] == '=') + return parameqn(param, pattern, n - 1) && param[n - 1] == '\0'; + + return parameq(param, pattern); +} + +/* Return true if the given param is only defined by early_param(). */ +static bool __init is_early_only_param(const char *param) +{ + const struct obs_kernel_param *p; + const struct kernel_param *kp; + bool has_early = false; + + /* If handled by a regular module_param, it is not early-only */ + for (kp = __start___param; kp < __stop___param; kp++) { + if (parameq(param, kp->name)) + return false; + } + + /* Check __setup / early_param table */ + for (p = __setup_start; p < __setup_end; p++) { + if (match_obs_param(param, p->str)) { + if (!p->early) + return false; + has_early = true; + } + } + return has_early; +} + +struct xbc_filter_data { + bool warn; +}; + +static bool __init xbc_kernel_param_filter(struct xbc_node *node, + const char *key, void *data) +{ + struct xbc_filter_data *fdata = data; + + if (is_early_only_param(key)) { + if (fdata && fdata->warn) + pr_warn("bootconfig: early_param 'kernel.%s' cannot be applied from bootconfig, skipping\n", + key); + return false; + } + return true; +} + +/* Make an extra command line under given key word */ +static char * __init xbc_make_cmdline(const char *key, bool is_kernel) +{ + struct xbc_filter_data fdata = { .warn = true }; + xbc_cmdline_filter_fn filter = is_kernel ? xbc_kernel_param_filter : NULL; struct xbc_node *root; char *new_cmdline; int ret, len = 0; @@ -347,8 +402,12 @@ static char * __init xbc_make_cmdline(const char *key) if (!root) return NULL; - /* Count required buffer size */ - len = xbc_snprint_cmdline(NULL, 0, root); + /* + * Pass 1: Count required buffer size. Emit warnings for skipped early + * params in this pass so they are logged even if all parameters under + * @key are skipped and len becomes 0. + */ + len = xbc_snprint_cmdline_filter(NULL, 0, root, filter, &fdata); if (len <= 0) return NULL; @@ -358,7 +417,9 @@ static char * __init xbc_make_cmdline(const char *key) return NULL; } - ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); + /* Pass 2: Render into buffer with warnings suppressed */ + fdata.warn = false; + ret = xbc_snprint_cmdline_filter(new_cmdline, len + 1, root, filter, &fdata); if (ret < 0 || ret > len) { pr_err("Failed to print extra kernel cmdline.\n"); memblock_free(new_cmdline, len + 1); @@ -432,9 +493,9 @@ static void __init setup_boot_config(void) * before this series. */ if (!from_embedded || !xbc_embedded_cmdline_applied()) - extra_command_line = xbc_make_cmdline("kernel"); + extra_command_line = xbc_make_cmdline("kernel", true); /* Also, "init." keys are init arguments */ - extra_init_args = xbc_make_cmdline("init"); + extra_init_args = xbc_make_cmdline("init", false); } return; } diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 12dd259d490e..84d74ef234a5 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -536,18 +536,21 @@ static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata; #define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0) /** - * xbc_snprint_cmdline() - Render bootconfig keys under @root as a cmdline string + * xbc_snprint_cmdline_filter() - Render bootconfig keys as cmdline string * @buf: Destination buffer (may be NULL when @size is 0 to query the length) * @size: Size of @buf in bytes * @root: Subtree root whose key=value pairs should be rendered + * @filter: Filter callback (returns true to include, false to skip; may be NULL) + * @data: Private context passed to @filter * * Walk all key/value pairs under @root and emit them as a space-separated * cmdline string into @buf. Values containing whitespace are quoted with - * double quotes. Returns the number of bytes that would be written if @buf - * were large enough (matching snprintf semantics), or a negative errno on - * failure. + * double quotes. Keys for which @filter returns false are omitted. + * Returns the number of bytes that would be written if @buf were large enough + * (matching snprintf semantics), or a negative errno on failure. */ -int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) +int __init xbc_snprint_cmdline_filter(char *buf, size_t size, struct xbc_node *root, + xbc_cmdline_filter_fn filter, void *data) { struct xbc_node *knode, *vnode; const char *val, *q; @@ -579,6 +582,9 @@ int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) if (ret < 0) return ret; + if (filter && !filter(knode, xbc_namebuf, data)) + continue; + vnode = xbc_node_get_child(knode); if (!vnode) { ret = snprintf(buf ? buf + len : NULL, rest(len, size), From fac634087ad85d2c6845cf3ead4fbf520274ca49 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 11 Sep 2026 23:13:06 +0900 Subject: [PATCH 5/8] bootconfig: Reject unexpected data after null character If a bootconfig buffer contains an intermediate null character in the middle of the configuration, xbc_parse_tree() stops at the null character because string delimiter searches (e.g. strpbrk()) stop at '\0', and cleanly breaks out of the loop without error. As a result, any configuration data following the intermediate null character is silently ignored, allowing unparsed or potentially malicious data to be hidden after an early termination. Fix this in xbc_parse_tree() by checking that no non-null data remains between the parser termination point and the end of the input buffer. Trailing null characters (such as alignment padding in initrd) continue to be accepted as valid. Also update apply_xbc() in tools/bootconfig/main.c to calculate the buffer size based on the loaded file size rather than strlen(), so that files with intermediate null characters are not truncated before validation. Link: https://lore.kernel.org/all/178913598628.248794.1048773774471250986.stgit@devnote2/ Assisted-by: LLM Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Sang-Heon Jeon --- lib/bootconfig.c | 7 +++++++ tools/bootconfig/main.c | 4 +++- tools/bootconfig/test-bootconfig.sh | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 84d74ef234a5..d64ebfca9796 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -1121,6 +1121,13 @@ static int __init xbc_parse_tree(void) } } while (!ret); + if (!ret) { + while (p < xbc_data + xbc_data_size - 1 && *p == '\0') + p++; + if (p < xbc_data + xbc_data_size - 1) + ret = xbc_parse_error("Unexpected data after null character", p); + } + return ret; } diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index 522a90bb22c2..ba023c7ced11 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -431,7 +431,9 @@ static int apply_xbc(const char *path, const char *xbc_path) pr_err("Failed to load %s : %d\n", xbc_path, ret); return ret; } - size = strlen(buf) + 1; + size = ret; + if (size == 0 || buf[size - 1] != '\0') + size++; csum = xbc_calc_checksum(buf, size); /* Backup the bootconfig data */ diff --git a/tools/bootconfig/test-bootconfig.sh b/tools/bootconfig/test-bootconfig.sh index fc69f815ce4a..530ce7e28d63 100755 --- a/tools/bootconfig/test-bootconfig.sh +++ b/tools/bootconfig/test-bootconfig.sh @@ -180,6 +180,18 @@ EOF $BOOTCONF -a $TEMPCONF $INITRD 2> $OUTFILE xpass grep -q "1:1" $OUTFILE +echo "Intermediate null character test" +printf "key = value\n\0extra = data\n" > $TEMPCONF +xfail $BOOTCONF -a $TEMPCONF $INITRD +$BOOTCONF -a $TEMPCONF $INITRD 2> $OUTFILE +xpass grep -q "Unexpected" $OUTFILE + +echo "Trailing null character test" +printf "key = value\n\0" > $TEMPCONF +xpass $BOOTCONF -a $TEMPCONF $INITRD +$BOOTCONF $INITRD > $OUTFILE +xpass grep -q "value" $OUTFILE + echo "=== expected failure cases ===" for i in samples/bad-* ; do xfail $BOOTCONF -a $i $INITRD From 78715511921cc8f331a2de79655f9850a71ae48c Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 11 Sep 2026 23:13:15 +0900 Subject: [PATCH 6/8] tools/bootconfig: Consolidate xbc_init() to error message wrapper Use init_xbc_with_error() for all bootconfig initialization in the bootconfig tool instead of showing errors in different way. This simplifies the code logic and make it easy to maintain. Link: https://lore.kernel.org/all/178913599508.248794.10388592925402087434.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) --- tools/bootconfig/main.c | 100 +++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index ba023c7ced11..d78c5523ab54 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -21,6 +21,39 @@ #define BOOTCONFIG_FOOTER_SIZE \ (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN) +static void show_xbc_error(const char *data, const char *msg, int pos) +{ + int lin = 1, col, i; + + if (pos < 0) { + pr_err("Error: %s.\n", msg); + return; + } + + /* Note that pos starts from 0 but lin and col should start from 1. */ + col = pos + 1; + for (i = 0; i < pos; i++) { + if (data[i] == '\n') { + lin++; + col = pos - i; + } + } + pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); + +} + +static int init_xbc_with_error(char *buf, int len) +{ + const char *msg; + int ret, pos; + + ret = xbc_init(buf, len, &msg, &pos); + if (ret < 0) + show_xbc_error(buf, msg, pos); + + return ret; +} + static int xbc_show_value(struct xbc_node *node, bool semicolon) { const char *val, *eol; @@ -195,7 +228,6 @@ static int load_xbc_from_initrd(int fd, char **buf) int ret; uint32_t size = 0, csum = 0, rcsum; char magic[BOOTCONFIG_MAGIC_LEN]; - const char *msg; ret = fstat(fd, &stat); if (ret < 0) @@ -247,52 +279,9 @@ static int load_xbc_from_initrd(int fd, char **buf) return -EINVAL; } - ret = xbc_init(*buf, size, &msg, NULL); - /* Wrong data */ - if (ret < 0) { - pr_err("parse error: %s.\n", msg); - return ret; - } + ret = init_xbc_with_error(*buf, size); - return size; -} - -static void show_xbc_error(const char *data, const char *msg, int pos) -{ - int lin = 1, col, i; - - if (pos < 0) { - pr_err("Error: %s.\n", msg); - return; - } - - /* Note that pos starts from 0 but lin and col should start from 1. */ - col = pos + 1; - for (i = 0; i < pos; i++) { - if (data[i] == '\n') { - lin++; - col = pos - i; - } - } - pr_err("Parse Error: %s at %d:%d\n", msg, lin, col); - -} - -static int init_xbc_with_error(char *buf, int len) -{ - char *copy = strdup(buf); - const char *msg; - int ret, pos; - - if (!copy) - return -ENOMEM; - - ret = xbc_init(buf, len, &msg, &pos); - if (ret < 0) - show_xbc_error(copy, msg, pos); - free(copy); - - return ret; + return ret < 0 ? ret : size; } static int show_xbc_kernel_cmdline(void) @@ -421,9 +410,8 @@ static int apply_xbc(const char *path, const char *xbc_path) char *buf, *data; size_t total_size; struct stat stat; - const char *msg; uint32_t size, csum; - int pos, pad; + int pad; int ret, fd; ret = load_xbc_file(xbc_path, &buf); @@ -436,6 +424,13 @@ static int apply_xbc(const char *path, const char *xbc_path) size++; csum = xbc_calc_checksum(buf, size); + /* Verify the data format */ + ret = init_xbc_with_error(buf, size); + if (ret < 0) { + free(buf); + return ret; + } + /* Backup the bootconfig data */ data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1); if (!data) { @@ -444,15 +439,6 @@ static int apply_xbc(const char *path, const char *xbc_path) } memcpy(data, buf, size); - /* Check the data format */ - ret = xbc_init(buf, size, &msg, &pos); - if (ret < 0) { - show_xbc_error(data, msg, pos); - free(data); - free(buf); - - return ret; - } printf("Apply %s to %s\n", xbc_path, path); xbc_get_info(&ret, NULL); printf("\tNumber of nodes: %d\n", ret); From e84e60da22ea2fb48576d8d78def44fab677374e Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 11 Sep 2026 23:13:24 +0900 Subject: [PATCH 7/8] bootconfig: Skip internal tree sanity checks in kernel In xbc_verify_tree(), the loop iterating through all nodes to check that xbc_nodes[i].next < xbc_node_num and xbc_nodes[i].child < xbc_node_num is a defensive sanity check against implementation regressions (such an out-of-bounds index cannot be produced by malformed input). Running this check in the kernel adds unnecessary boot-time overhead. Split this check out into xbc_sanity_check_tree() for userspace, so that it continues to run during userspace bootconfig validation (e.g. when applying or testing bootconfig with tools/bootconfig), but is omitted in the kernel to speed up initialization. Link: https://lore.kernel.org/all/178913600409.248794.12941798680046327623.stgit@devnote2/ Reported-by: Sang-Heon Jeon Closes: https://lore.kernel.org/all/20260905141637.1547429-1-ekffu200098@gmail.com/ Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Sang-Heon Jeon --- lib/bootconfig.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/bootconfig.c b/lib/bootconfig.c index d64ebfca9796..819685d6c68d 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -1005,9 +1005,30 @@ static int __init xbc_close_brace(char **k, char *n) return __xbc_close_brace(n - 1); } +#ifndef __KERNEL__ +/* Sanity check for regression: node indices must be within bounds */ +static int __init xbc_sanity_check_tree(void) +{ + int i; + + for (i = 0; i < xbc_node_num; i++) { + if (xbc_nodes[i].next >= xbc_node_num) { + return xbc_parse_error("No closing brace", + xbc_node_get_data(xbc_nodes + i)); + } + if (xbc_nodes[i].child >= xbc_node_num) { + return xbc_parse_error("Broken child node", + xbc_node_get_data(xbc_nodes + i)); + } + } + + return 0; +} +#endif + static int __init xbc_verify_tree(void) { - int i, depth; + int depth; size_t len, wlen; struct xbc_node *n, *m; @@ -1024,17 +1045,6 @@ static int __init xbc_verify_tree(void) return -ENOENT; } - for (i = 0; i < xbc_node_num; i++) { - if (xbc_nodes[i].next >= xbc_node_num) { - return xbc_parse_error("No closing brace", - xbc_node_get_data(xbc_nodes + i)); - } - if (xbc_nodes[i].child >= xbc_node_num) { - return xbc_parse_error("Broken child node", - xbc_node_get_data(xbc_nodes + i)); - } - } - /* Key tree limitation check */ n = &xbc_nodes[0]; depth = 1; @@ -1204,6 +1214,10 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos) ret = xbc_parse_tree(); if (!ret) ret = xbc_verify_tree(); +#ifndef __KERNEL__ + if (!ret) + ret = xbc_sanity_check_tree(); +#endif if (ret < 0) { if (epos) From 677f83795fdfc25ddc51b665a9111f5ff199f7ca Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 11 Sep 2026 23:13:33 +0900 Subject: [PATCH 8/8] bootconfig: Move BOOTCONFIG_FOOTER_SIZE to include/linux/bootconfig.h BOOTCONFIG_FOOTER_SIZE was defined locally in tools/bootconfig/main.c. Move it to include/linux/bootconfig.h so that it can be shared with the kernel and user-space tools. Also, use it in init/main.c instead of the hardcoded (BOOTCONFIG_MAGIC_LEN + 8) expression when checking the initrd size. Link: https://lore.kernel.org/all/178913601321.248794.4786502771058559887.stgit@devnote2/ Suggested-by: Sang-Heon Jeon Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Sang-Heon Jeon --- include/linux/bootconfig.h | 4 ++++ init/main.c | 2 +- tools/bootconfig/main.c | 4 ---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index 6de07eac761b..260a6f46042e 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -27,6 +27,10 @@ bool __init cmdline_has_extra_options(void); #define BOOTCONFIG_ALIGN (1 << BOOTCONFIG_ALIGN_SHIFT) #define BOOTCONFIG_ALIGN_MASK (BOOTCONFIG_ALIGN - 1) +/* Bootconfig footer is [size][csum][BOOTCONFIG_MAGIC]. */ +#define BOOTCONFIG_FOOTER_SIZE \ + (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN) + /** * xbc_calc_checksum() - Calculate checksum of bootconfig * @data: Bootconfig data. diff --git a/init/main.c b/init/main.c index d2ad726b515f..861e07f6c05c 100644 --- a/init/main.c +++ b/init/main.c @@ -278,7 +278,7 @@ static void * __init get_boot_config_from_initrd(size_t *_size) int i; if (!initrd_end || initrd_end < initrd_start || - initrd_end - initrd_start < BOOTCONFIG_MAGIC_LEN + 8) + initrd_end - initrd_start < BOOTCONFIG_FOOTER_SIZE) return NULL; data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index d78c5523ab54..56d76bdeaa09 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -17,10 +17,6 @@ #define pr_err(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) -/* Bootconfig footer is [size][csum][BOOTCONFIG_MAGIC]. */ -#define BOOTCONFIG_FOOTER_SIZE \ - (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN) - static void show_xbc_error(const char *data, const char *msg, int pos) { int lin = 1, col, i;