Commit 2f183c68 authored by Jani Nikula's avatar Jani Nikula Committed by Andrew Morton
Browse files

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: default avatarJani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent f36fc96c
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ struct taint_flag {
	char c_true;		/* character printed when tainted */
	char c_false;		/* character printed when not tainted */
	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];
@@ -90,6 +91,7 @@ enum lockdep_ok {
};

extern const char *print_tainted(void);
extern const char *print_tainted_verbose(void);
extern void add_taint(unsigned flag, enum lockdep_ok);
extern int test_taint(unsigned flag);
extern unsigned long get_taint(void);
+34 −11
Original line number Diff line number Diff line
@@ -475,6 +475,7 @@ EXPORT_SYMBOL(panic);
	[ TAINT_##taint ] = {						\
		.c_true = _c_true, .c_false = _c_false,			\
		.module = _module,					\
		.desc = #taint,						\
	}

/*
@@ -505,8 +506,9 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {

#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;

	if (!tainted_mask) {
@@ -520,9 +522,31 @@ static void print_tainted_seq(struct seq_buf *s)
		bool is_set = test_bit(i, &tainted_mask);
		char c = is_set ? t->c_true : t->c_false;

		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.
@@ -534,16 +558,15 @@ static void print_tainted_seq(struct seq_buf *s)
 */
const char *print_tainted(void)
{
	static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
	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);
	return _print_tainted(false);
}

	return seq_buf_str(&s);
/**
 * print_tainted_verbose - A more verbose version of print_tainted()
 */
const char *print_tainted_verbose(void)
{
	return _print_tainted(true);
}

int test_taint(unsigned flag)
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ void dump_stack_print_info(const char *log_lvl)
	       (int)strcspn(init_utsname()->version, " "),
	       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')
		printk("%sHardware name: %s\n",
		       log_lvl, dump_stack_arch_desc_str);