From a75d207916de0909e2244bc66a44d72fadbcf383 Mon Sep 17 00:00:00 2001 From: Rio Date: Fri, 20 Feb 2026 20:45:00 +0530 Subject: kernel/panic: increase buffer size for verbose taint logging The verbose 'Tainted: ...' string in print_tainted_seq can total to 327 characters while the buffer defined in _print_tainted is 320 bytes. Increase its size to 350 characters to hold all flags, along with some headroom. [akpm@linux-foundation.org: fix spello, add comment] Link: https://lkml.kernel.org/r/20260220151500.13585-1-rioo.tsukatsukii@gmail.com Signed-off-by: Rio Cc: Joel Granados Cc: Petr Mladek Cc: Wang Jinchao Signed-off-by: Andrew Morton --- kernel/panic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'kernel/panic.c') diff --git a/kernel/panic.c b/kernel/panic.c index c78600212b6c..75368738d32d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -801,6 +801,8 @@ EXPORT_SYMBOL(panic); * Documentation/admin-guide/tainted-kernels.rst, including its * small shell script that prints the TAINT_FLAGS_COUNT bits of * /proc/sys/kernel/tainted. + * + * Also, update TAINT_BUF_MAX below. */ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { TAINT_FLAG(PROPRIETARY_MODULE, 'P', 'G'), @@ -854,10 +856,12 @@ static void print_tainted_seq(struct seq_buf *s, bool verbose) } } +/* 350 can accommodate all taint flags in verbose mode, with some headroom */ +#define TAINT_BUF_MAX 350 + static const char *_print_tainted(bool verbose) { - /* FIXME: what should the size be? */ - static char buf[sizeof(taint_flags)]; + static char buf[TAINT_BUF_MAX]; struct seq_buf s; BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT); -- cgit v1.2.3 From a9dff0d0d11ce9aeebdd52ecf1469895e336c87e Mon Sep 17 00:00:00 2001 From: Rio Date: Sun, 22 Feb 2026 19:38:04 +0530 Subject: kernel/panic: allocate taint string buffer dynamically The buffer used to hold the taint string is statically allocated, which requires updating whenever a new taint flag is added. Instead, allocate the exact required length at boot once the allocator is available in an init function. The allocation sums the string lengths in taint_flags[], along with space for separators and formatting. print_tainted() is switched to use this dynamically allocated buffer. If allocation fails, print_tainted() warns about the failure and continues to use the original static buffer as a fallback. Link: https://lkml.kernel.org/r/20260222140804.22225-1-rioo.tsukatsukii@gmail.com Signed-off-by: Rio Cc: Joel Granados Cc: Petr Mladek Cc: Wang Jinchao Signed-off-by: Andrew Morton --- kernel/panic.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'kernel/panic.c') diff --git a/kernel/panic.c b/kernel/panic.c index 75368738d32d..5d498ff8a18b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -802,7 +802,7 @@ EXPORT_SYMBOL(panic); * small shell script that prints the TAINT_FLAGS_COUNT bits of * /proc/sys/kernel/tainted. * - * Also, update TAINT_BUF_MAX below. + * Also, update INIT_TAINT_BUF_MAX below. */ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { TAINT_FLAG(PROPRIETARY_MODULE, 'P', 'G'), @@ -856,17 +856,58 @@ static void print_tainted_seq(struct seq_buf *s, bool verbose) } } -/* 350 can accommodate all taint flags in verbose mode, with some headroom */ -#define TAINT_BUF_MAX 350 +/* The initial buffer can accommodate all taint flags in verbose + * mode, with some headroom. Once the allocator is available, the + * exact size is allocated dynamically; the initial buffer remains + * as a fallback if allocation fails. + * + * The verbose taint string currently requires up to 327 characters. + */ +#define INIT_TAINT_BUF_MAX 350 + +static char init_taint_buf[INIT_TAINT_BUF_MAX]; +static char *taint_buf = init_taint_buf; +static size_t taint_buf_size = INIT_TAINT_BUF_MAX; + +static __init int alloc_taint_buf(void) +{ + int i; + char *buf; + size_t size = 0; + + size += sizeof("Tainted: ") - 1; + for (i = 0; i < TAINT_FLAGS_COUNT; i++) { + size += 2; /* For ", " */ + size += 4; /* For "[%c]=" */ + size += strlen(taint_flags[i].desc); + } + + size += 1; /* For NULL terminator */ + + buf = kmalloc(size, GFP_KERNEL); + + if (!buf) { + /* Allocation may fail; this warning explains possibly + * truncated taint strings + */ + pr_warn_once("taint string buffer allocation failed, using fallback buffer\n"); + return 0; + } + + taint_buf = buf; + taint_buf_size = size; + + return 0; +} +postcore_initcall(alloc_taint_buf); static const char *_print_tainted(bool verbose) { - static char buf[TAINT_BUF_MAX]; struct seq_buf s; BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT); - seq_buf_init(&s, buf, sizeof(buf)); + seq_buf_init(&s, taint_buf, taint_buf_size); print_tainted_seq(&s, verbose); -- cgit v1.2.3 From 48d76a8282c9d99ec123d5f09cf6e485e5cb8734 Mon Sep 17 00:00:00 2001 From: Rio Date: Mon, 23 Feb 2026 09:29:14 +0530 Subject: kernel/panic: mark init_taint_buf as __initdata and panic instead of warning in alloc_taint_buf() However there's a convention of assuming that __init-time allocations cannot fail. Because if a kmalloc() were to fail at this time, the kernel is hopelessly messed up anyway. So simply panic() if that kmalloc failed, then make that 350-byte buffer __initdata. Link: https://lkml.kernel.org/r/20260223035914.4033-1-rioo.tsukatsukii@gmail.com Signed-off-by: Rio Cc: Joel Granados Cc: Petr Mladek Cc: Wang Jinchao Signed-off-by: Andrew Morton --- kernel/panic.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'kernel/panic.c') diff --git a/kernel/panic.c b/kernel/panic.c index 5d498ff8a18b..20feada5319d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -865,8 +865,8 @@ static void print_tainted_seq(struct seq_buf *s, bool verbose) */ #define INIT_TAINT_BUF_MAX 350 -static char init_taint_buf[INIT_TAINT_BUF_MAX]; -static char *taint_buf = init_taint_buf; +static char init_taint_buf[INIT_TAINT_BUF_MAX] __initdata; +static char *taint_buf __refdata = init_taint_buf; static size_t taint_buf_size = INIT_TAINT_BUF_MAX; static __init int alloc_taint_buf(void) @@ -887,11 +887,7 @@ static __init int alloc_taint_buf(void) buf = kmalloc(size, GFP_KERNEL); if (!buf) { - /* Allocation may fail; this warning explains possibly - * truncated taint strings - */ - pr_warn_once("taint string buffer allocation failed, using fallback buffer\n"); - return 0; + panic("Failed to allocate taint string buffer"); } taint_buf = buf; -- cgit v1.2.3