]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/bug: Fix BUG_FORMAT vs KASLR
authorPeter Zijlstra <peterz@infradead.org>
Wed, 26 Nov 2025 09:55:17 +0000 (10:55 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Thu, 27 Nov 2025 08:32:47 +0000 (09:32 +0100)
Encoding a relative NULL pointer doesn't work for KASLR, when the
whole kernel image gets shifted, the __bug_table and the target string
get shifted by the same amount and the relative offset is preserved.

However when the target is an absolute 0 value and the __bug_table
gets moved about, the end result in a pointer equivalent to
kaslr_offset(), not NULL.

Notably, this will generate SHN_UNDEF relocations, and Ard would
really like to not have those at all.

Use the empty string to denote no-string.

Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
arch/x86/include/asm/bug.h
lib/bug.c

index d0a96ff5c02c0baa80ac92f53dfc5c891c592b3b..4b5ab56903bb784e40105cafdc7605ba40cdd748 100644 (file)
@@ -86,7 +86,7 @@ extern void __WARN_trap(struct bug_entry *bug, ...);
 #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
 #define WARN_CONDITION_STR(cond_str) cond_str
 #else
-#define WARN_CONDITION_STR(cond_str) NULL
+#define WARN_CONDITION_STR(cond_str) ""
 #endif
 
 #define _BUG_FLAGS(cond_str, ins, flags, extra)                                \
@@ -103,8 +103,12 @@ do {                                                                       \
 } while (0)
 
 #define ARCH_WARN_ASM(file, line, flags, size)                         \
+       ".pushsection .rodata.str1.1, \"aMS\", @progbits, 1\n"          \
+       "99:\n"                                                         \
+       "\t.string \"\"\n"                                              \
+       ".popsection\n"                                                 \
        "1:\t " ASM_UD2 "\n"                                            \
-       _BUG_FLAGS_ASM("0", file, line, flags, size, "")
+       _BUG_FLAGS_ASM("99b", file, line, flags, size, "")
 
 #else
 
index 581a66b88c5c04646bbc9000c97a014494995e75..edd9041f89f3aa613af71e4f107b52a4f4dc71f4 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -144,7 +144,17 @@ static const char *bug_get_format(struct bug_entry *bug)
        const char *format = NULL;
 #ifdef HAVE_ARCH_BUG_FORMAT
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
-       format = (const char *)&bug->format_disp + bug->format_disp;
+       /*
+        * Allow an architecture to:
+        *  - relative encode NULL (difficult vs KASLR);
+        *  - use a literal 0 (there are no valid objects inside
+        *    the __bug_table itself to refer to after all);
+        *  - use an empty string.
+        */
+       if (bug->format_disp)
+               format = (const char *)&bug->format_disp + bug->format_disp;
+       if (format && format[0] == '\0')
+               format = NULL;
 #else
        format = bug->format;
 #endif