Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kernel/panic: add verbose logging of kernel taints in backtraces

With nearly 20 taint flags and respective characters, it's getting a bit
difficult to remember what each taint flag character means. Add verbose
logging of the set taints in the format:

Tainted: [P]=PROPRIETARY_MODULE, [W]=WARN

in dump_stack_print_info() when there are taints.

Note that the "negative flag" G is not included.

Link: https://lkml.kernel.org/r/7321e306166cb2ca2807ab8639e665baa2462e9c.1717146197.git.jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Jani Nikula and committed by
Andrew Morton
2f183c68 f36fc96c

+42 -14
+5 -3
include/linux/panic.h
··· 77 77 #define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1) 78 78 79 79 struct taint_flag { 80 - char c_true; /* character printed when tainted */ 81 - char c_false; /* character printed when not tainted */ 82 - bool module; /* also show as a per-module taint flag */ 80 + char c_true; /* character printed when tainted */ 81 + char c_false; /* character printed when not tainted */ 82 + bool module; /* also show as a per-module taint flag */ 83 + const char *desc; /* verbose description of the set taint flag */ 83 84 }; 84 85 85 86 extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT]; ··· 91 90 }; 92 91 93 92 extern const char *print_tainted(void); 93 + extern const char *print_tainted_verbose(void); 94 94 extern void add_taint(unsigned flag, enum lockdep_ok); 95 95 extern int test_taint(unsigned flag); 96 96 extern unsigned long get_taint(void);
+34 -11
kernel/panic.c
··· 475 475 [ TAINT_##taint ] = { \ 476 476 .c_true = _c_true, .c_false = _c_false, \ 477 477 .module = _module, \ 478 + .desc = #taint, \ 478 479 } 479 480 480 481 /* ··· 506 505 507 506 #undef TAINT_FLAG 508 507 509 - static void print_tainted_seq(struct seq_buf *s) 508 + static void print_tainted_seq(struct seq_buf *s, bool verbose) 510 509 { 510 + const char *sep = ""; 511 511 int i; 512 512 513 513 if (!tainted_mask) { ··· 522 520 bool is_set = test_bit(i, &tainted_mask); 523 521 char c = is_set ? t->c_true : t->c_false; 524 522 525 - seq_buf_putc(s, c); 523 + if (verbose) { 524 + if (is_set) { 525 + seq_buf_printf(s, "%s[%c]=%s", sep, c, t->desc); 526 + sep = ", "; 527 + } 528 + } else { 529 + seq_buf_putc(s, c); 530 + } 526 531 } 532 + } 533 + 534 + static const char *_print_tainted(bool verbose) 535 + { 536 + /* FIXME: what should the size be? */ 537 + static char buf[sizeof(taint_flags)]; 538 + struct seq_buf s; 539 + 540 + BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT); 541 + 542 + seq_buf_init(&s, buf, sizeof(buf)); 543 + 544 + print_tainted_seq(&s, verbose); 545 + 546 + return seq_buf_str(&s); 527 547 } 528 548 529 549 /** ··· 558 534 */ 559 535 const char *print_tainted(void) 560 536 { 561 - static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")]; 562 - struct seq_buf s; 537 + return _print_tainted(false); 538 + } 563 539 564 - BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT); 565 - 566 - seq_buf_init(&s, buf, sizeof(buf)); 567 - 568 - print_tainted_seq(&s); 569 - 570 - return seq_buf_str(&s); 540 + /** 541 + * print_tainted_verbose - A more verbose version of print_tainted() 542 + */ 543 + const char *print_tainted_verbose(void) 544 + { 545 + return _print_tainted(true); 571 546 } 572 547 573 548 int test_taint(unsigned flag)
+3
lib/dump_stack.c
··· 62 62 (int)strcspn(init_utsname()->version, " "), 63 63 init_utsname()->version, BUILD_ID_VAL); 64 64 65 + if (get_taint()) 66 + printk("%s%s\n", log_lvl, print_tainted_verbose()); 67 + 65 68 if (dump_stack_arch_desc_str[0] != '\0') 66 69 printk("%sHardware name: %s\n", 67 70 log_lvl, dump_stack_arch_desc_str);