mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing
@ 2026-10-08 16:40 Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 1/8] genksyms: fix infinite loop on declarations with parameter lists Leizhen Zhang
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

This series fixes bugs in kbuild host programs found by building them
with AddressSanitizer and UndefinedBehaviorSanitizer and fuzzing their
inputs. Most patches include a reproducer.

Patch 1 fixes a bug that also triggers without sanitizers: a declaration
such as "int a, f(int);" makes genksyms loop forever while allocating
memory (since v6.14; earlier versions silently recorded wrong types for
such declarations).

Patches 2-8 fix out-of-bounds reads (fixdep, modpost) and undefined
behaviour reported by UBSan (kallsyms, modpost, sorttable,
tools/include byteshift helpers), several of which trigger on every
normal x86_64 build when the host tools are built with UBSan.

The series is based on next-20261002. With it applied, a defconfig +
MODULES + MODVERSIONS x86_64 build succeeds, and for genksyms, the
symtypes/CRCs of 149 preprocessed kernel sources are unchanged.

Changes in v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.
 - Drop "kconfig: fix NULL pointer dereference for defaults taken from
   choice members"; Julian Braha will fix that issue differently.

v1: https://lore.kernel.org/r/20261005104050.1786222-1-lzsx618@gmail.com

Leizhen Zhang (8):
  genksyms: fix infinite loop on declarations with parameter lists
  fixdep: fix out-of-bounds read on a comment ending with a backslash
  kallsyms: do not call qsort() with a NULL table
  modpost: fix stack out-of-bounds read for unterminated PNP ids
  modpost: fix handling of short reads in read_text_file()
  modpost: fix pointer arithmetic on NULL in parse_source_files()
  sorttable: avoid pointer arithmetic overflow when locating sort_needed
  tools/include: fix signed shift overflow in 32-bit unaligned accessors

 scripts/basic/fixdep.c             |  2 +-
 scripts/genksyms/parse.y           | 23 +++++++++++++++++++----
 scripts/kallsyms.c                 |  6 ++++--
 scripts/mod/file2alias.c           | 10 ++++++----
 scripts/mod/modpost.c              |  6 +++++-
 scripts/mod/sumversion.c           |  3 ++-
 scripts/sorttable.c                |  2 +-
 tools/include/tools/be_byteshift.h |  2 +-
 tools/include/tools/le_byteshift.h |  2 +-
 9 files changed, 40 insertions(+), 16 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/8] genksyms: fix infinite loop on declarations with parameter lists
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 2/8] fixdep: fix out-of-bounds read on a comment ending with a backslash Leizhen Zhang
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

decl_specifier_seq updates the global decl_spec, which is used by the ','
action of init_declarator_list to give each further declarator the
specifiers of the declaration. However, decl_specifier_seq is also used
for parameter declarations, so for a declaration such as

  int a, f(int);

decl_spec is clobbered by the specifiers of the parameter "int" by the
time the ',' action runs. The action then links the parameter's own token
node back into its chain, creating a cycle, and copy_list_range() loops
forever while allocating memory:

  $ printf 'int a, f(int);\n' | scripts/genksyms/genksyms
  (hangs)

Before commit 45c9c4101d3d ("genksyms: fix memory leak when the same
symbol is added from source") the same corruption did not hang but
silently recorded a wrong type for subsequent declarators (e.g. for
"int f(long), a;" the type of "a" was recorded as "int f ( long a").

Only set decl_spec in decl_specifier_seq_opt, which is used at the
declaration level, and let decl_specifier_seq just return the last
specifier. Struct and union member declarations use a new
member_decl_specifier_seq_opt that does not touch decl_spec, so a
struct body nested in a parameter list cannot clobber it either.

The generated symtypes and CRCs for 149 preprocessed kernel source files
(1128 exported symbols) are unchanged, and no new bison conflicts are
introduced.

Found by fuzzing genksyms with ASan/UBSan.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Claude:claude-opus-5-5 ASan UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-3-lzsx618@gmail.com

 scripts/genksyms/parse.y | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index cabcd146f3..7cc0336a79 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -201,13 +201,28 @@ init_declarator:
 /* Hang on to the specifiers so that we can reuse them.  */
 decl_specifier_seq_opt:
 	/* empty */				{ decl_spec = NULL; }
+	| decl_specifier_seq			{ decl_spec = *$1; }
+	;
+
+/*
+ * Unlike decl_specifier_seq_opt, this does not touch decl_spec, so that
+ * a struct/union body nested in a parameter list does not clobber the
+ * specifiers of the enclosing declaration.
+ */
+member_decl_specifier_seq_opt:
+	/* empty */				{ $$ = NULL; }
 	| decl_specifier_seq
 	;
 
+/*
+ * Do not set decl_spec here; decl_specifier_seq is also used for parameter
+ * declarations, which would clobber the specifiers of the enclosing
+ * declaration, e.g. "int a, f(long);".
+ */
 decl_specifier_seq:
-	attribute_opt decl_specifier		{ decl_spec = *$2; }
-	| decl_specifier_seq decl_specifier	{ decl_spec = *$2; }
-	| decl_specifier_seq ATTRIBUTE_PHRASE	{ decl_spec = *$2; }
+	attribute_opt decl_specifier		{ $$ = $2; }
+	| decl_specifier_seq decl_specifier	{ $$ = $2; }
+	| decl_specifier_seq ATTRIBUTE_PHRASE	{ $$ = $2; }
 	;
 
 decl_specifier:
@@ -456,7 +471,7 @@ member_specification:
 	;
 
 member_declaration:
-	decl_specifier_seq_opt member_declarator_list_opt ';'
+	member_decl_specifier_seq_opt member_declarator_list_opt ';'
 		{ $$ = $3; dont_want_type_specifier = false; }
 	| error ';'
 		{ $$ = $2; dont_want_type_specifier = false; }
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/8] fixdep: fix out-of-bounds read on a comment ending with a backslash
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 1/8] genksyms: fix infinite loop on declarations with parameter lists Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 3/8] kallsyms: do not call qsort() with a NULL table Leizhen Zhang
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

When skipping a comment, parse_dep_file() treats a backslash as escaping
the next character and skips it unconditionally. If the backslash is the
last character of the file, this steps over the terminating NUL and the
loop keeps reading beyond the end of the buffer:

  $ printf 'foo.o: foo.c\n# x\\' > foo.d
  $ touch foo.c
  $ scripts/basic/fixdep foo.d foo.o cc
  AddressSanitizer: heap-buffer-overflow ... in parse_dep_file

Only skip the character after the backslash if it is not the terminating
NUL.

Found by fuzzing fixdep with ASan/UBSan.

Fixes: bc6df812a152 ("fixdep: parse Makefile more correctly to handle comments etc.")
Assisted-by: Claude:claude-opus-5-5 ASan UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-4-lzsx618@gmail.com

 scripts/basic/fixdep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 54063d9804..9b57fe5554 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -280,7 +280,7 @@ static void parse_dep_file(char *p, const char *target)
 				 * escaped newlines continue the comment across
 				 * multiple lines.
 				 */
-				if (*p == '\\')
+				if (*p == '\\' && *(p + 1) != '\0')
 					p++;
 				p++;
 			}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 3/8] kallsyms: do not call qsort() with a NULL table
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 1/8] genksyms: fix infinite loop on declarations with parameter lists Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 2/8] fixdep: fix out-of-bounds read on a comment ending with a backslash Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 4/8] modpost: fix stack out-of-bounds read for unterminated PNP ids Leizhen Zhang
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

link-vmlinux.sh runs kallsyms on an empty input for the first link, in
which case table is NULL and table_cnt is 0. Passing NULL to qsort() is
undefined behaviour even for zero elements, and UBSan reports:

  scripts/kallsyms.c: runtime error: null pointer passed as argument 1,
  which is declared to never be null

Skip the sort when there are no symbols.

Fixes: c442db3f49f2 ("kbuild: remove PROVIDE() for kallsyms symbols")
Assisted-by: Claude:claude-opus-5-5 UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-5-lzsx618@gmail.com

 scripts/kallsyms.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index bd9e9ce20e..9300e10ad6 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -390,7 +390,8 @@ static int compare_names(const void *a, const void *b)
 
 static void sort_symbols_by_name(void)
 {
-	qsort(table, table_cnt, sizeof(table[0]), compare_names);
+	if (table_cnt)
+		qsort(table, table_cnt, sizeof(table[0]), compare_names);
 }
 
 static void write_src(FILE *out_bin_file, const char *out_bin_name)
@@ -822,7 +823,8 @@ static int compare_symbols(const void *a, const void *b)
 
 static void sort_symbols(void)
 {
-	qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
+	if (table_cnt)
+		qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
 }
 
 int main(int argc, char **argv)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 4/8] modpost: fix stack out-of-bounds read for unterminated PNP ids
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
                   ` (2 preceding siblings ...)
  2026-10-08 16:40 ` [PATCH v2 3/8] kallsyms: do not call qsort() with a NULL table Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 5/8] modpost: fix handling of short reads in read_text_file() Leizhen Zhang
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

do_pnp_device_entry() and do_pnp_card_entry() copy the PNP id into a
local acpi_id[PNP_ID_LEN] buffer to upper-case it, and then print it with
"%s". A PNP id that uses all PNP_ID_LEN characters, e.g. "PNP0C0F1", is
accepted by the compiler without a terminating NUL (the kernel is built
with -Wno-unterminated-string-initialization), so the local copy is not
NUL-terminated and printing it reads past the end of the stack buffer:

  AddressSanitizer: stack-buffer-overflow ... in printf_common
    ... do_pnp_device_entry scripts/mod/file2alias.c

Limit the printed length to the size of the id buffers.

Found by fuzzing modpost with ASan/UBSan.

Fixes: 72638f598ec9 ("PNP: fix broken pnp lowercasing for acpi module aliases")
Assisted-by: Claude:claude-opus-5-5 ASan UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-6-lzsx618@gmail.com

 scripts/mod/file2alias.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 61a831c187..7685fb5135 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -573,8 +573,9 @@ static void do_pnp_device_entry(struct module *mod, void *symval)
 	/* fix broken pnp bus lowercasing */
 	for (unsigned int i = 0; i < sizeof(acpi_id); i++)
 		acpi_id[i] = toupper((*id)[i]);
-	module_alias_printf(mod, false, "pnp:d%s*", *id);
-	module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
+	module_alias_printf(mod, false, "pnp:d%.*s*", (int)sizeof(*id), *id);
+	module_alias_printf(mod, false, "acpi*:%.*s:*",
+			    (int)sizeof(acpi_id), acpi_id);
 }
 
 /* looks like: "pnp:dD" for every device of the card */
@@ -594,8 +595,9 @@ static void do_pnp_card_entry(struct module *mod, void *symval)
 			acpi_id[j] = toupper(id[j]);
 
 		/* add an individual alias for every device entry */
-		module_alias_printf(mod, false, "pnp:d%s*", id);
-		module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
+		module_alias_printf(mod, false, "pnp:d%.*s*", PNP_ID_LEN, id);
+		module_alias_printf(mod, false, "acpi*:%.*s:*",
+				    PNP_ID_LEN, acpi_id);
 	}
 }
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 5/8] modpost: fix handling of short reads in read_text_file()
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
                   ` (3 preceding siblings ...)
  2026-10-08 16:40 ` [PATCH v2 4/8] modpost: fix stack out-of-bounds read for unterminated PNP ids Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 6/8] modpost: fix pointer arithmetic on NULL in parse_source_files() Leizhen Zhang
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

read_text_file() loops until the whole file has been read, but every
read() call writes to the start of the buffer, so after a short read the
data already read is overwritten and the end of the buffer is left
uninitialized. If read() returns 0 before the expected size has been
read, the loop never terminates.

Read into the correct offset of the buffer, and treat an unexpected end
of file as an error.

This was confirmed by limiting read() to 64 bytes per call with an
LD_PRELOAD shim, which makes modpost fail with a parse error on a valid
Module.symvers.

Fixes: ac5100f54329 ("modpost: add read_text_file() and get_line() helpers")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-7-lzsx618@gmail.com

 scripts/mod/modpost.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 75374c64b8..1772068dc6 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -143,11 +143,15 @@ char *read_text_file(const char *filename)
 	while (nbytes) {
 		ssize_t bytes_read;
 
-		bytes_read = read(fd, buf, nbytes);
+		bytes_read = read(fd, buf + st.st_size - nbytes, nbytes);
 		if (bytes_read < 0) {
 			perror(filename);
 			exit(1);
 		}
+		if (bytes_read == 0) {
+			fprintf(stderr, "%s: unexpected end of file\n", filename);
+			exit(1);
+		}
 
 		nbytes -= bytes_read;
 	}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 6/8] modpost: fix pointer arithmetic on NULL in parse_source_files()
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
                   ` (4 preceding siblings ...)
  2026-10-08 16:40 ` [PATCH v2 5/8] modpost: fix handling of short reads in read_text_file() Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 7/8] sorttable: avoid pointer arithmetic overflow when locating sort_needed Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 8/8] tools/include: fix signed shift overflow in 32-bit unaligned accessors Leizhen Zhang
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

parse_source_files() checks whether a dependency is in the same directory
as the object file with

  (strstr(line, dir) + strlen(dir) - 1) == strrchr(line, '/')

When the dependency is not below dir, strstr() returns NULL and the
pointer arithmetic on NULL is undefined behaviour. This happens for
every module with dependencies outside its own directory, and UBSan
reports:

  scripts/mod/sumversion.c: runtime error: applying non-zero offset
  to null pointer

Check the result of strstr() before using it.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Claude:claude-opus-5-5 UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-8-lzsx618@gmail.com

 scripts/mod/sumversion.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 3dd28b4d00..4c59e7cfbc 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -364,7 +364,8 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
 		}
 
 		/* Check if this file is in same dir as objfile */
-		if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
+		p = strstr(line, dir);
+		if (p && p + dirlen - 1 == strrchr(line, '/')) {
 			if (!parse_file(line, md)) {
 				warn("could not open %s: %s\n",
 				     line, strerror(errno));
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 7/8] sorttable: avoid pointer arithmetic overflow when locating sort_needed
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
                   ` (5 preceding siblings ...)
  2026-10-08 16:40 ` [PATCH v2 6/8] modpost: fix pointer arithmetic on NULL in parse_source_files() Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  2026-10-08 16:40 ` [PATCH v2 8/8] tools/include: fix signed shift overflow in 32-bit unaligned accessors Leizhen Zhang
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

The location of the main_extable_sort_needed variable is computed as

  (void *)ehdr + shdr_offset(sec) + sym_value(sym) - shdr_addr(sec)

which first adds the symbol's virtual address (e.g. 0xffffffff8...) to
the pointer and only then subtracts the section address. The
intermediate pointer overflows, which is undefined behaviour and is
reported by UBSan.

Subtract the section address from the symbol value first.

Fixes: a79f248b9b30 ("scripts: Add sortextable to sort the kernel's exception table.")
Assisted-by: Claude:claude-opus-5-5 UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-9-lzsx618@gmail.com

 scripts/sorttable.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 88e49a5c42..0425e00c49 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -788,7 +788,7 @@ static int do_sort(Elf_Ehdr *ehdr,
 	sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index);
 	sort_needed_loc = (void *)ehdr +
 		shdr_offset(sort_needed_sec) +
-		sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec);
+		(sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec));
 
 	/* extable has been sorted, clear the flag */
 	elf_parser.w(0, sort_needed_loc);
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 8/8] tools/include: fix signed shift overflow in 32-bit unaligned accessors
  2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
                   ` (6 preceding siblings ...)
  2026-10-08 16:40 ` [PATCH v2 7/8] sorttable: avoid pointer arithmetic overflow when locating sort_needed Leizhen Zhang
@ 2026-10-08 16:40 ` Leizhen Zhang
  7 siblings, 0 replies; 9+ messages in thread
From: Leizhen Zhang @ 2026-10-08 16:40 UTC (permalink / raw)
  To: nathan, nsc; +Cc: rostedt, linux-kbuild, linux-kernel

In __get_unaligned_le32() and __get_unaligned_be32() the most significant
byte is promoted to int before being shifted left by 24. If the byte is
0x80 or higher, the result does not fit in an int, which is undefined
behaviour. This happens for every kernel virtual address, e.g. in
sorttable, and UBSan reports:

  tools/include/tools/le_byteshift.h:14: runtime error: left shift of
  255 by 24 places cannot be represented in type 'int'

Cast the byte to uint32_t before shifting.

Fixes: a07f7672d7cf ("tools/include: Add byteshift headers for endian access")
Assisted-by: Claude:claude-opus-5-5 UBSan
Signed-off-by: Leizhen Zhang <lzsx618@gmail.com>
---
v2:
 - Use my real name in the From and Signed-off-by lines. No code
   changes.

v1: https://lore.kernel.org/r/20261005104050.1786222-10-lzsx618@gmail.com

 tools/include/tools/be_byteshift.h | 2 +-
 tools/include/tools/le_byteshift.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h
index f7d1d16989..2bda8d199c 100644
--- a/tools/include/tools/be_byteshift.h
+++ b/tools/include/tools/be_byteshift.h
@@ -11,7 +11,7 @@ static inline uint16_t __get_unaligned_be16(const uint8_t *p)
 
 static inline uint32_t __get_unaligned_be32(const uint8_t *p)
 {
-	return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+	return (uint32_t)p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
 }
 
 static inline uint64_t __get_unaligned_be64(const uint8_t *p)
diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h
index dc8565f397..e5c78a48a7 100644
--- a/tools/include/tools/le_byteshift.h
+++ b/tools/include/tools/le_byteshift.h
@@ -11,7 +11,7 @@ static inline uint16_t __get_unaligned_le16(const uint8_t *p)
 
 static inline uint32_t __get_unaligned_le32(const uint8_t *p)
 {
-	return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+	return p[0] | p[1] << 8 | p[2] << 16 | (uint32_t)p[3] << 24;
 }
 
 static inline uint64_t __get_unaligned_le64(const uint8_t *p)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-08 16:41 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-08 16:40 [PATCH v2 0/8] kbuild: fix memory safety and UB bugs in host tools found by fuzzing Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 1/8] genksyms: fix infinite loop on declarations with parameter lists Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 2/8] fixdep: fix out-of-bounds read on a comment ending with a backslash Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 3/8] kallsyms: do not call qsort() with a NULL table Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 4/8] modpost: fix stack out-of-bounds read for unterminated PNP ids Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 5/8] modpost: fix handling of short reads in read_text_file() Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 6/8] modpost: fix pointer arithmetic on NULL in parse_source_files() Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 7/8] sorttable: avoid pointer arithmetic overflow when locating sort_needed Leizhen Zhang
2026-10-08 16:40 ` [PATCH v2 8/8] tools/include: fix signed shift overflow in 32-bit unaligned accessors Leizhen Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®