diff options
Diffstat (limited to 'kernel/panic.c')
| -rw-r--r-- | kernel/panic.c | 116 | 
1 files changed, 79 insertions, 37 deletions
| diff --git a/kernel/panic.c b/kernel/panic.c index 8bff183d6180..f861bedc1925 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -35,6 +35,7 @@  #include <linux/debugfs.h>  #include <linux/sysfs.h>  #include <linux/context_tracking.h> +#include <linux/seq_buf.h>  #include <trace/events/error_report.h>  #include <asm/sections.h> @@ -470,32 +471,83 @@ void panic(const char *fmt, ...)  EXPORT_SYMBOL(panic); +#define TAINT_FLAG(taint, _c_true, _c_false, _module)			\ +	[ TAINT_##taint ] = {						\ +		.c_true = _c_true, .c_false = _c_false,			\ +		.module = _module,					\ +		.desc = #taint,						\ +	} +  /*   * TAINT_FORCED_RMMOD could be a per-module flag but the module   * is being removed anyway.   */  const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { -	[ TAINT_PROPRIETARY_MODULE ]	= { 'P', 'G', true }, -	[ TAINT_FORCED_MODULE ]		= { 'F', ' ', true }, -	[ TAINT_CPU_OUT_OF_SPEC ]	= { 'S', ' ', false }, -	[ TAINT_FORCED_RMMOD ]		= { 'R', ' ', false }, -	[ TAINT_MACHINE_CHECK ]		= { 'M', ' ', false }, -	[ TAINT_BAD_PAGE ]		= { 'B', ' ', false }, -	[ TAINT_USER ]			= { 'U', ' ', false }, -	[ TAINT_DIE ]			= { 'D', ' ', false }, -	[ TAINT_OVERRIDDEN_ACPI_TABLE ]	= { 'A', ' ', false }, -	[ TAINT_WARN ]			= { 'W', ' ', false }, -	[ TAINT_CRAP ]			= { 'C', ' ', true }, -	[ TAINT_FIRMWARE_WORKAROUND ]	= { 'I', ' ', false }, -	[ TAINT_OOT_MODULE ]		= { 'O', ' ', true }, -	[ TAINT_UNSIGNED_MODULE ]	= { 'E', ' ', true }, -	[ TAINT_SOFTLOCKUP ]		= { 'L', ' ', false }, -	[ TAINT_LIVEPATCH ]		= { 'K', ' ', true }, -	[ TAINT_AUX ]			= { 'X', ' ', true }, -	[ TAINT_RANDSTRUCT ]		= { 'T', ' ', true }, -	[ TAINT_TEST ]			= { 'N', ' ', true }, +	TAINT_FLAG(PROPRIETARY_MODULE,		'P', 'G', true), +	TAINT_FLAG(FORCED_MODULE,		'F', ' ', true), +	TAINT_FLAG(CPU_OUT_OF_SPEC,		'S', ' ', false), +	TAINT_FLAG(FORCED_RMMOD,		'R', ' ', false), +	TAINT_FLAG(MACHINE_CHECK,		'M', ' ', false), +	TAINT_FLAG(BAD_PAGE,			'B', ' ', false), +	TAINT_FLAG(USER,			'U', ' ', false), +	TAINT_FLAG(DIE,				'D', ' ', false), +	TAINT_FLAG(OVERRIDDEN_ACPI_TABLE,	'A', ' ', false), +	TAINT_FLAG(WARN,			'W', ' ', false), +	TAINT_FLAG(CRAP,			'C', ' ', true), +	TAINT_FLAG(FIRMWARE_WORKAROUND,		'I', ' ', false), +	TAINT_FLAG(OOT_MODULE,			'O', ' ', true), +	TAINT_FLAG(UNSIGNED_MODULE,		'E', ' ', true), +	TAINT_FLAG(SOFTLOCKUP,			'L', ' ', false), +	TAINT_FLAG(LIVEPATCH,			'K', ' ', true), +	TAINT_FLAG(AUX,				'X', ' ', true), +	TAINT_FLAG(RANDSTRUCT,			'T', ' ', true), +	TAINT_FLAG(TEST,			'N', ' ', true),  }; +#undef TAINT_FLAG + +static void print_tainted_seq(struct seq_buf *s, bool verbose) +{ +	const char *sep = ""; +	int i; + +	if (!tainted_mask) { +		seq_buf_puts(s, "Not tainted"); +		return; +	} + +	seq_buf_printf(s, "Tainted: "); +	for (i = 0; i < TAINT_FLAGS_COUNT; i++) { +		const struct taint_flag *t = &taint_flags[i]; +		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.   * @@ -506,25 +558,15 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {   */  const char *print_tainted(void)  { -	static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")]; - -	BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT); - -	if (tainted_mask) { -		char *s; -		int i; - -		s = buf + sprintf(buf, "Tainted: "); -		for (i = 0; i < TAINT_FLAGS_COUNT; i++) { -			const struct taint_flag *t = &taint_flags[i]; -			*s++ = test_bit(i, &tainted_mask) ? -					t->c_true : t->c_false; -		} -		*s = 0; -	} else -		snprintf(buf, sizeof(buf), "Not tainted"); +	return _print_tainted(false); +} -	return buf; +/** + * 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) |