From nobody Fri Sep 25 18:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B75D5576EB8; Wed, 9 Sep 2026 15:53:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969230; cv=none; b=KdWGVl6W9gQZ/NGmbesk2mi+d13v58bpAAD/2ZHEzoFhhf7qv/mroe0DrdB44xYXFyyuy+1yrDKBxbM4BaGV5wpKSQ7GeU5oPZGEmfRanRPNofQEortLS2n9LKrH5oXV4xGHbb7TYGVuNvCgP+2vOXCZJqTZi28m564CM/DHCp8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969230; c=relaxed/simple; bh=Lw23bxYF2SeVxe2c2uvX0H1QkXIsH944jUEI8MagQVk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fU8l64p+txa2nCUXhgBhv4/7yOZI1q/lcMYyV/GKG7Aj5BRm9YGO1dwke6IghiATLSfQUv30tbhJTQWYZgXjp4Wr+eHba4XNi0cBtjCP5pelVy2HbeAQ5gTxYnaq78z/zuhNTutVBRq4sW+DhgJ3q7md77gV3DgmCD3F4doqcsM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dlqiTQX+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dlqiTQX+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3F9701F00A3D; Wed, 9 Sep 2026 15:53:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788969228; bh=d6P8nm47c75PBnxXGfDXABoraSULENG6UjLUERO0Rq4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dlqiTQX+iMDMb1qXIXZYay9dfUlyORepD3vScebEO37aWVzwCkzCDyMAqxf+d/Yhe JYMtlmqPlcM5T73uAZF0iAA8cNO4s79GLzTFEsc5QcIjoSXK93um942NhlK+O5+qDU ErXMZo7H8Igu/mrMs5U0N8JAkPSKVTIScvIzUy1x6BJrmVltcVM1kyl+aQm06lI2Dn 1qjzk8KKcpkHTzEj9Ie5amDCq73rxHeY47gRNhMJqej7v/q94/lbyZY0AsRZVzaP0f zU87RqdgUwFcWHOZydhE/DErioLnsZk6mLON4waRp7Ag0M0r8+urlx9Fa1aOWHj1wF JM5aAGwQf7PCQ== From: "Masami Hiramatsu (Google)" To: Andrew Morton , Masami Hiramatsu Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Sang-Heon Jeon Subject: [PATCH 1/3] bootconfig: Reject unexpected data after null character Date: Thu, 10 Sep 2026 00:53:45 +0900 Message-ID: <178896922501.177508.6894964926791268965.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <178896921555.177508.434402948295885560.stgit@devnote2> References: <178896921555.177508.434402948295885560.stgit@devnote2> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) 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. Assisted-by: Antigravity:gemini-3.8-flash 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 aba11caf6903..0ec2874db9c7 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -1116,6 +1116,13 @@ static int __init xbc_parse_tree(void) } } while (!ret); =20 + if (!ret) { + while (p < xbc_data + xbc_data_size - 1 && *p =3D=3D '\0') + p++; + if (p < xbc_data + xbc_data_size - 1) + ret =3D xbc_parse_error("Unexpected data after null character", p); + } + return ret; } =20 diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index 7dc9fff9b637..6035404733c3 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -422,7 +422,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 =3D strlen(buf) + 1; + size =3D ret; + if (size =3D=3D 0 || buf[size - 1] !=3D '\0') + size++; csum =3D xbc_calc_checksum(buf, size); =20 /* Backup the bootconfig data */ diff --git a/tools/bootconfig/test-bootconfig.sh b/tools/bootconfig/test-bo= otconfig.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 =20 +echo "Intermediate null character test" +printf "key =3D value\n\0extra =3D 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 =3D value\n\0" > $TEMPCONF +xpass $BOOTCONF -a $TEMPCONF $INITRD +$BOOTCONF $INITRD > $OUTFILE +xpass grep -q "value" $OUTFILE + echo "=3D=3D=3D expected failure cases =3D=3D=3D" for i in samples/bad-* ; do xfail $BOOTCONF -a $i $INITRD From nobody Fri Sep 25 18:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A11C58123D; Wed, 9 Sep 2026 15:53:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969238; cv=none; b=GoDNJAbnhQa6txGUyAn3l6+NdpteqVYQl7T9zU5DEcN5Gbi8Lc4Q2pBUm8SBCVdzYfqak/GAQRQrYnSZSFIPfi/no2xMun7m+BF2po/OTvGDiOhJUTJ5cfg0G8EDa5eOB6MNMglHZg/f2XjTzFWQtJbqsAkG6H/g7tWX2zHtlHM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969238; c=relaxed/simple; bh=IpypP2UXfMQrqE7LCaYtWwmwQ2MQS6kVNgWvILji1o0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sWSQW3YGw4QzT6LhmHEYUX/wlxcb4ByBLW8LrPg7rnOztXJ1Ml0Bg/sLUsmFZH5aM55CRLNiaYRUlqWEIXVb7SCyiSOi9lyfLFmpwIX+gAZ1PaKuX+i9V9gJAV6eONV4A9l2tMhWXJ7l27NgI3tnoSJ7nGacLcXSgvUPUyZXTIs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Rg5HvFLF; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Rg5HvFLF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1024E1F00A3A; Wed, 9 Sep 2026 15:53:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788969237; bh=/8BAaxZyXXosOe7u2XcIyvstoN4X+pMzG1qOfmfe3A0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Rg5HvFLF1EetVjlkYKD05Y/Lc4ShWCixbc10YPriVZPBjKuMwniw1foYEl2bkUPEW KOf+46PLhrmIoQUDRGl5pdEoG0mnl8cNw1FyBi8gMZY9xr3UdOoQu1HHMlLRRJi9N7 QJoGPk+rZvN+tNQvb9IJ+jl44RQol3FZZ/r6V6TofT7gVPOkQQWdggsuSMTZulHnpl mWAT44J9aLLL1i7pvjfw8YhV1qthlK8esg5ppYN+5novVdXjVREjfDdP6GVi+ziitR EkeiJueaOm9nXBfPDpGJe9/L45EpWaCgWmzmjpR4oC2RCiQyZb99WQsW39gliX+OmW Dvwvg+gTBoDMg== From: "Masami Hiramatsu (Google)" To: Andrew Morton , Masami Hiramatsu Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Sang-Heon Jeon Subject: [PATCH 2/3] tools/bootconfig: Consolidate xbc_init() to error message wrapper Date: Thu, 10 Sep 2026 00:53:53 +0900 Message-ID: <178896923375.177508.14682854552827605824.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <178896921555.177508.434402948295885560.stgit@devnote2> References: <178896921555.177508.434402948295885560.stgit@devnote2> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) 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. Signed-off-by: Masami Hiramatsu (Google) --- tools/bootconfig/main.c | 108 ++++++++++++++++++++++---------------------= ---- 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c index 6035404733c3..7117aa9b2a83 100644 --- a/tools/bootconfig/main.c +++ b/tools/bootconfig/main.c @@ -21,6 +21,47 @@ #define BOOTCONFIG_FOOTER_SIZE \ (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN) =20 +static void show_xbc_error(const char *data, const char *msg, int pos) +{ + int lin =3D 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 =3D pos + 1; + for (i =3D 0; i < pos; i++) { + if (data[i] =3D=3D '\n') { + lin++; + col =3D 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 =3D malloc(len); + const char *msg; + int ret, pos; + + if (!copy) + return -ENOMEM; + + memcpy(copy, buf, len); + /* We do not terminate the copy with \0 for sanity checking */ + + ret =3D xbc_init(buf, len, &msg, &pos); + if (ret < 0) + show_xbc_error(copy, msg, pos); + free(copy); + + return ret; +} + static int xbc_show_value(struct xbc_node *node, bool semicolon) { const char *val, *eol; @@ -187,7 +228,6 @@ static int load_xbc_from_initrd(int fd, char **buf) int ret; uint32_t size =3D 0, csum =3D 0, rcsum; char magic[BOOTCONFIG_MAGIC_LEN]; - const char *msg; =20 ret =3D fstat(fd, &stat); if (ret < 0) @@ -238,52 +278,9 @@ static int load_xbc_from_initrd(int fd, char **buf) return -EINVAL; } =20 - ret =3D xbc_init(*buf, size, &msg, NULL); - /* Wrong data */ - if (ret < 0) { - pr_err("parse error: %s.\n", msg); - return ret; - } + ret =3D init_xbc_with_error(*buf, size); =20 - return size; -} - -static void show_xbc_error(const char *data, const char *msg, int pos) -{ - int lin =3D 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 =3D pos + 1; - for (i =3D 0; i < pos; i++) { - if (data[i] =3D=3D '\n') { - lin++; - col =3D 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 =3D strdup(buf); - const char *msg; - int ret, pos; - - if (!copy) - return -ENOMEM; - - ret =3D xbc_init(buf, len, &msg, &pos); - if (ret < 0) - show_xbc_error(copy, msg, pos); - free(copy); - - return ret; + return ret < 0 ? ret : size; } =20 static int show_xbc_kernel_cmdline(void) @@ -412,9 +409,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; =20 ret =3D load_xbc_file(xbc_path, &buf); @@ -427,6 +423,13 @@ static int apply_xbc(const char *path, const char *xbc= _path) size++; csum =3D xbc_calc_checksum(buf, size); =20 + /* Verify the data format */ + ret =3D init_xbc_with_error(buf, size); + if (ret < 0) { + free(buf); + return ret; + } + /* Backup the bootconfig data */ data =3D calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1); if (!data) { @@ -435,15 +438,6 @@ static int apply_xbc(const char *path, const char *xbc= _path) } memcpy(data, buf, size); =20 - /* Check the data format */ - ret =3D 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 nobody Fri Sep 25 18:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EC8157268E; Wed, 9 Sep 2026 15:54:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969247; cv=none; b=uIqXIdT1Gc27GHSsPsk/U/gkPDOPJZdII0+OkcPC1A8ecWem22eSvbrTywdZ51RHm0/hYg5F/V2HelvaHZj0/V2eXzalLwSTX8Nu6G5rsk9O5sZSCBkuJ+dEp2vj6RagvhDBRFmTuk5zJzAhizF7wMNc0GqG+UBUbtIZ3Ae6aBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788969247; c=relaxed/simple; bh=iiCqDt9mQIBQuWEbYlHKIjXIwZW1+sg6Y68w5Rr5kBg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hMnrQr1HV7Jzw4zg1ep6hhsBJxgQ1QuHcQkZfIP5Rz+KiSlNDRjAxXMpl76+8HltogX66+ISAEfQ37RmaW2nxfQJgKtjjmtCg6U1FvWaGsSGZgxJPnJ1Rpzk3WL89DMCY1inkxBfg/R+a5na/3MC7BH4U6FgMg2ctC5j2Zh8hTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TWYtl8p3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TWYtl8p3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BE59B1F00A3A; Wed, 9 Sep 2026 15:54:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788969246; bh=lc9EDpaTK/r+zWTBkBXV/JPAZb/7ckGcnzP62wQl6z8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TWYtl8p3uOWUXs4D4RIv5xoYkOoVPkr9NyxuLKKuHCCO52wcy8xmkpJpy5e4p0Ovk YQ5cMI6qyCWLVVd+2cIb5ERmEOvQk9nR3cY9yqECQIC2y/k+HJxTXHZ/cufz8EFJPS Fi6ujPTEsr0d9BQ/1HHj6R7uFMZa9KoULjvW/29WLlAncIdbrB+EBR2flEz04MS7ga DdoYJSmQxzwMIccBe1hgezt76XAq+t+hMUKEQq4yS+h0rqFhAC6sTjOuWnxZHG0yTO AMjmXcmqC8+HXQBda/rOOsQ91wSTzP3gUvauFvgnti52H6uHYMQcp2kCieAbUwjPhZ vN0bzUCwfONQw== From: "Masami Hiramatsu (Google)" To: Andrew Morton , Masami Hiramatsu Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Sang-Heon Jeon Subject: [PATCH 3/3] bootconfig: Skip internal tree sanity checks in kernel Date: Thu, 10 Sep 2026 00:54:02 +0900 Message-ID: <178896924262.177508.71609739247457811.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <178896921555.177508.434402948295885560.stgit@devnote2> References: <178896921555.177508.434402948295885560.stgit@devnote2> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) 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. Reported-by: Sang-Heon Jeon Closes: https://lore.kernel.org/all/20260905141637.1547429-1-ekffu200098@gm= ail.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 0ec2874db9c7..884f186b1989 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -1000,9 +1000,30 @@ static int __init xbc_close_brace(char **k, char *n) return __xbc_close_brace(n - 1); } =20 +#ifndef __KERNEL__ +/* Sanity check for regression: node indices must be within bounds */ +static int __init xbc_sanity_check_tree(void) +{ + int i; + + for (i =3D 0; i < xbc_node_num; i++) { + if (xbc_nodes[i].next >=3D xbc_node_num) { + return xbc_parse_error("No closing brace", + xbc_node_get_data(xbc_nodes + i)); + } + if (xbc_nodes[i].child >=3D 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; =20 @@ -1019,17 +1040,6 @@ static int __init xbc_verify_tree(void) return -ENOENT; } =20 - for (i =3D 0; i < xbc_node_num; i++) { - if (xbc_nodes[i].next >=3D xbc_node_num) { - return xbc_parse_error("No closing brace", - xbc_node_get_data(xbc_nodes + i)); - } - if (xbc_nodes[i].child >=3D xbc_node_num) { - return xbc_parse_error("Broken child node", - xbc_node_get_data(xbc_nodes + i)); - } - } - /* Key tree limitation check */ n =3D &xbc_nodes[0]; depth =3D 1; @@ -1199,6 +1209,10 @@ int __init xbc_init(const char *data, size_t size, c= onst char **emsg, int *epos) ret =3D xbc_parse_tree(); if (!ret) ret =3D xbc_verify_tree(); +#ifndef __KERNEL__ + if (!ret) + ret =3D xbc_sanity_check_tree(); +#endif =20 if (ret < 0) { if (epos)