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>
This commit is contained in:
parent
f36fc96c15
commit
2f183c6834
@ -77,9 +77,10 @@ static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout)
|
|||||||
#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
|
#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
|
||||||
|
|
||||||
struct taint_flag {
|
struct taint_flag {
|
||||||
char c_true; /* character printed when tainted */
|
char c_true; /* character printed when tainted */
|
||||||
char c_false; /* character printed when not tainted */
|
char c_false; /* character printed when not tainted */
|
||||||
bool module; /* also show as a per-module taint flag */
|
bool module; /* also show as a per-module taint flag */
|
||||||
|
const char *desc; /* verbose description of the set taint flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
|
extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
|
||||||
@ -90,6 +91,7 @@ enum lockdep_ok {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const char *print_tainted(void);
|
extern const char *print_tainted(void);
|
||||||
|
extern const char *print_tainted_verbose(void);
|
||||||
extern void add_taint(unsigned flag, enum lockdep_ok);
|
extern void add_taint(unsigned flag, enum lockdep_ok);
|
||||||
extern int test_taint(unsigned flag);
|
extern int test_taint(unsigned flag);
|
||||||
extern unsigned long get_taint(void);
|
extern unsigned long get_taint(void);
|
||||||
|
@ -475,6 +475,7 @@ EXPORT_SYMBOL(panic);
|
|||||||
[ TAINT_##taint ] = { \
|
[ TAINT_##taint ] = { \
|
||||||
.c_true = _c_true, .c_false = _c_false, \
|
.c_true = _c_true, .c_false = _c_false, \
|
||||||
.module = _module, \
|
.module = _module, \
|
||||||
|
.desc = #taint, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -505,8 +506,9 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
|
|||||||
|
|
||||||
#undef TAINT_FLAG
|
#undef TAINT_FLAG
|
||||||
|
|
||||||
static void print_tainted_seq(struct seq_buf *s)
|
static void print_tainted_seq(struct seq_buf *s, bool verbose)
|
||||||
{
|
{
|
||||||
|
const char *sep = "";
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!tainted_mask) {
|
if (!tainted_mask) {
|
||||||
@ -520,10 +522,32 @@ static void print_tainted_seq(struct seq_buf *s)
|
|||||||
bool is_set = test_bit(i, &tainted_mask);
|
bool is_set = test_bit(i, &tainted_mask);
|
||||||
char c = is_set ? t->c_true : t->c_false;
|
char c = is_set ? t->c_true : t->c_false;
|
||||||
|
|
||||||
seq_buf_putc(s, c);
|
if (verbose) {
|
||||||
|
if (is_set) {
|
||||||
|
seq_buf_printf(s, "%s[%c]=%s", sep, c, t->desc);
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
seq_buf_putc(s, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *_print_tainted(bool verbose)
|
||||||
|
{
|
||||||
|
/* FIXME: what should the size be? */
|
||||||
|
static char buf[sizeof(taint_flags)];
|
||||||
|
struct seq_buf s;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT);
|
||||||
|
|
||||||
|
seq_buf_init(&s, buf, sizeof(buf));
|
||||||
|
|
||||||
|
print_tainted_seq(&s, verbose);
|
||||||
|
|
||||||
|
return seq_buf_str(&s);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* print_tainted - return a string to represent the kernel taint state.
|
* print_tainted - return a string to represent the kernel taint state.
|
||||||
*
|
*
|
||||||
@ -534,16 +558,15 @@ static void print_tainted_seq(struct seq_buf *s)
|
|||||||
*/
|
*/
|
||||||
const char *print_tainted(void)
|
const char *print_tainted(void)
|
||||||
{
|
{
|
||||||
static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
|
return _print_tainted(false);
|
||||||
struct seq_buf s;
|
}
|
||||||
|
|
||||||
BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT);
|
/**
|
||||||
|
* print_tainted_verbose - A more verbose version of print_tainted()
|
||||||
seq_buf_init(&s, buf, sizeof(buf));
|
*/
|
||||||
|
const char *print_tainted_verbose(void)
|
||||||
print_tainted_seq(&s);
|
{
|
||||||
|
return _print_tainted(true);
|
||||||
return seq_buf_str(&s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_taint(unsigned flag)
|
int test_taint(unsigned flag)
|
||||||
|
@ -62,6 +62,9 @@ void dump_stack_print_info(const char *log_lvl)
|
|||||||
(int)strcspn(init_utsname()->version, " "),
|
(int)strcspn(init_utsname()->version, " "),
|
||||||
init_utsname()->version, BUILD_ID_VAL);
|
init_utsname()->version, BUILD_ID_VAL);
|
||||||
|
|
||||||
|
if (get_taint())
|
||||||
|
printk("%s%s\n", log_lvl, print_tainted_verbose());
|
||||||
|
|
||||||
if (dump_stack_arch_desc_str[0] != '\0')
|
if (dump_stack_arch_desc_str[0] != '\0')
|
||||||
printk("%sHardware name: %s\n",
|
printk("%sHardware name: %s\n",
|
||||||
log_lvl, dump_stack_arch_desc_str);
|
log_lvl, dump_stack_arch_desc_str);
|
||||||
|
Loading…
Reference in New Issue
Block a user