Memory safety / Undefined behavior (NULL-pointer arithmetic)

HIGH
torvalds/linux
Commit: 4a50a141f05a
Affected: <= v7.0-rc6 (pre-fix); fixed in bootconfig patch merged for 7.2-rc1
2026-07-02 10:18 UTC

Description

The commit fixes undefined pointer arithmetic in lib/bootconfig.c: xbc_snprint_cmdline() when the function is called with a NULL buffer and size 0. The original code computed end = buf + size and used buf in pointer arithmetic, which is undefined when buf is NULL. The patch introduces a local length accumulator (size_t len) and avoids performing pointer arithmetic on buf. It uses len to track the written length and updates snprintf calls with a conditional buf ? buf + len : NULL and rest(len, size), ultimately returning len. This prevents build-time UBSan/FORTIFY_SOURCE failures and reduces risk of memory-safety issues in edge cases where a caller queries the required length (buf=NULL, size=0). While primarily a correctness/memory-safety fix, it addresses a class of undefined behavior that could otherwise crash or destabilize builds or runs under instrumentation.

Proof of Concept

// Proof-of-concept demonstrating the problematic pattern (broken version) and why the fix is needed // This reproduces a simplified scenario of pointer arithmetic on a potentially NULL buffer. // Compile with -fsanitize=undefined to observe UB when buf is NULL and size is 0. #include <stdio.h> #include <stdlib.h> #include <string.h> size_t broken_snprint(char *buf, size_t size) { // This simulates the problematic code path: end = buf + size where buf may be NULL char *end = buf + size; // undefined behavior if buf is NULL size_t len = 0; // pretend to write something, advancing len if (size) { len += 1; // pretend one byte written } // return would-be length, using the invalid end return end - buf; // UB when buf is NULL } int main(void) { // Trigger the problematic call pattern: NULL buffer, 0 size size_t r = broken_snprint(NULL, 0); printf("result=%zu\n", r); return 0; } // Expected (post-fix) behavior: calling with NULL buf and 0 size should return 0 without performing // any arithmetic on a NULL pointer. In practice, compile with UBSan to observe that the broken version // exhibits undefined behavior whereas the fixed version would avoid dereferencing or arithmetic on NULL.

Commit Details

Author: Linus Torvalds

Date: 2026-07-02 00:21 UTC

Message:

Merge tag 'bootconfig-fixes-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace Pull bootconfig fix from Masami Hiramatsu: - bootconfig: Fix NULL-pointer arithmetic Fix undefined pointer arithmetic in xbc_snprint_cmdline() when probing the buffer length with NULL and size 0. Track the written length as a size_t instead to prevent build-time UBSan/FORTIFY_SOURCE failures. * tag 'bootconfig-fixes-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline()

Triage Assessment

Vulnerability Type: Memory Safety / Undefined Behavior

Confidence: HIGH

Reasoning:

The patch fixes undefined pointer arithmetic when handling a NULL buffer and size 0, switching to tracking written length via size_t to avoid arithmetic on NULL pointers. This prevents potential memory safety vulnerabilities (UB/UBSanFORTIFY triggers) that could lead to crashes or exploitation in edge cases.

Verification Assessment

Vulnerability Type: Memory safety / Undefined behavior (NULL-pointer arithmetic)

Confidence: HIGH

Affected Versions: <= v7.0-rc6 (pre-fix); fixed in bootconfig patch merged for 7.2-rc1

Code Diff

diff --git a/lib/bootconfig.c b/lib/bootconfig.c index f445b7703fdd96..2ed9ee3dc81c72 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -427,10 +427,18 @@ static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata; int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) { struct xbc_node *knode, *vnode; - char *end = buf + size; const char *val, *q; + size_t len = 0; int ret; + /* + * Track the running written length rather than advancing @buf, so we + * never form "buf + size" or "buf += ret" while @buf is NULL (the + * size-probe call passes buf=NULL, size=0). NULL pointer arithmetic + * is undefined behavior and trips host UBSan / FORTIFY_SOURCE when + * this renderer runs at kernel build time. snprintf(NULL, 0, ...) + * itself is well defined and returns the would-be length. + */ xbc_node_for_each_key_value(root, knode, val) { ret = xbc_node_compose_key_after(root, knode, xbc_namebuf, XBC_KEYLEN_MAX); @@ -439,10 +447,11 @@ int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) vnode = xbc_node_get_child(knode); if (!vnode) { - ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf); + ret = snprintf(buf ? buf + len : NULL, rest(len, size), + "%s ", xbc_namebuf); if (ret < 0) return ret; - buf += ret; + len += ret; continue; } xbc_array_for_each_value(vnode, val) { @@ -452,15 +461,15 @@ int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root) * whitespace. */ q = strpbrk(val, " \t\r\n") ? "\"" : ""; - ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ", - xbc_namebuf, q, val, q); + ret = snprintf(buf ? buf + len : NULL, rest(len, size), + "%s=%s%s%s ", xbc_namebuf, q, val, q); if (ret < 0) return ret; - buf += ret; + len += ret; } } - return buf - (end - size); + return len; } #undef rest
← Back to Alerts View on GitHub →