[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Yo9uYL9eL9KBuzam@zn.tnic>
Date: Thu, 26 May 2022 14:11:12 +0200
From: Borislav Petkov <bp@...en8.de>
To: "Luck, Tony" <tony.luck@...el.com>
Cc: Peter Zijlstra <peterz@...radead.org>, X86 ML <x86@...nel.org>,
LKML <linux-kernel@...r.kernel.org>
Subject: Taint addresses
I guess something like this:
...
[ 2.591532] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[ 2.592678] CPU: 2 PID: 1 Comm: swapper/0 Tainted: G S C 5.18.0+ #7
[ 2.593079] Last taint addresses:
[ 2.593079] S:start_kernel+0x614/0x634
[ 2.593079] C:kernel_init+0x70/0x140
[ 2.593079] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[ 2.593079] Call Trace:
[ 2.593079] <TASK>
[ 2.593079] dump_stack_lvl+0x38/0x49
[ 2.593079] ? rest_init+0xd0/0xd0
[ 2.593079] kernel_init+0x75/0x140
[ 2.593079] ret_from_fork+0x22/0x30
[ 2.593079] </TASK>
---
I probably should put the taint addresses after the stack trace but
other than that, it gives you where the taint was added last.
diff --git a/include/linux/panic.h b/include/linux/panic.h
index f5844908a089..7e3aeddece5f 100644
--- a/include/linux/panic.h
+++ b/include/linux/panic.h
@@ -94,5 +94,6 @@ extern const char *print_tainted(void);
extern void add_taint(unsigned flag, enum lockdep_ok);
extern int test_taint(unsigned flag);
extern unsigned long get_taint(void);
+void print_tainted_addresses(const char *log_lvl);
#endif /* _LINUX_PANIC_H */
diff --git a/kernel/panic.c b/kernel/panic.c
index eb4dfb932c85..78b541c8da99 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -49,6 +49,7 @@ unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;
static unsigned long tainted_mask =
IS_ENABLED(CONFIG_GCC_PLUGIN_RANDSTRUCT) ? (1 << TAINT_RANDSTRUCT) : 0;
+static unsigned long taint_addrs[TAINT_FLAGS_COUNT];
static int pause_on_oops;
static int pause_on_oops_flag;
static DEFINE_SPINLOCK(pause_on_oops_lock);
@@ -437,6 +438,23 @@ const char *print_tainted(void)
return buf;
}
+void print_tainted_addresses(const char *log_lvl)
+{
+ int i;
+
+ if (!tainted_mask)
+ return;
+
+ printk("%sLast taint addresses:\n", log_lvl);
+
+ for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
+ const struct taint_flag *t = &taint_flags[i];
+
+ if (test_bit(i, &tainted_mask))
+ printk("%s %c:%pS\n", log_lvl, t->c_true, (void *)taint_addrs[i]);
+ }
+}
+
int test_taint(unsigned flag)
{
return test_bit(flag, &tainted_mask);
@@ -461,7 +479,11 @@ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
if (lockdep_ok == LOCKDEP_NOW_UNRELIABLE && __debug_locks_off())
pr_warn("Disabling lock debugging due to kernel taint\n");
+ if (WARN_ON_ONCE(flag >= TAINT_FLAGS_COUNT))
+ return;
+
set_bit(flag, &tainted_mask);
+ taint_addrs[flag] = _RET_IP_;
if (tainted_mask & panic_on_taint) {
panic_on_taint = 0;
diff --git a/lib/dump_stack.c b/lib/dump_stack.c
index 6b7f1bf6715d..595fa8757916 100644
--- a/lib/dump_stack.c
+++ b/lib/dump_stack.c
@@ -62,6 +62,8 @@ void dump_stack_print_info(const char *log_lvl)
(int)strcspn(init_utsname()->version, " "),
init_utsname()->version, BUILD_ID_VAL);
+ print_tainted_addresses(log_lvl);
+
if (dump_stack_arch_desc_str[0] != '\0')
printk("%sHardware name: %s\n",
log_lvl, dump_stack_arch_desc_str);
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
Powered by blists - more mailing lists