Taint addresses

Borislav Petkov posted 1 patch 3 years, 11 months ago
Taint addresses
Posted by Borislav Petkov 3 years, 11 months ago
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
Re: Taint addresses
Posted by Luck, Tony 3 years, 11 months ago
On Thu, May 26, 2022 at 02:11:12PM +0200, Borislav Petkov wrote:
> 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

Maybe something a little more user friendly than addresses?

If there was a new macro:

#define add_taint(flag, lockdep) __add_taint(flag, lockdep, __FILE__, __LINE__)

then renmame existing add_taint() to __add_taint() and have it save the
file/line values.

Then you could print filename:line

Also: Is it more useful to store the most recent taint of each type,
or the first of each type?

-Tony
Re: Taint addresses
Posted by Borislav Petkov 3 years, 11 months ago
On Thu, May 26, 2022 at 09:41:06AM -0700, Luck, Tony wrote:
> Also: Is it more useful to store the most recent taint of each type,
> or the first of each type?

Yeah, all good suggestions and valid questions. However, I'm still not
sure about this and would like to keep it in the bag until an actual use
case appears...

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette