aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2016-09-21 07:47:22 -0400
committerJessica Yu <jeyu@redhat.com>2016-11-26 14:18:01 -0500
commit7fd8329ba502ef76dd91db561c7aed696b2c7720 (patch)
tree1cd64753819f07f811f0c0daabfdf72c952a089f
parentc7d47f26df949f0031fe2905068ee85db1b63ed9 (diff)
taint/module: Clean up global and module taint flags handling
The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints: add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to potentially print one more character. But it did not increase the size of the corresponding buffers in m_show() and print_modules(). We have recently done the same mistake when adding a taint flag for livepatching, see https://lkml.kernel.org/r/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com Also struct module uses an incompatible type for mod-taints flags. It survived from the commit 2bc2d61a9638dab670d ("[PATCH] list module taint flags in Oops/panic"). There was used "int" for the global taint flags at these times. But only the global tain flags was later changed to "unsigned long" by the commit 25ddbb18aae33ad2 ("Make the taint flags reliable"). This patch defines TAINT_FLAGS_COUNT that can be used to create arrays and buffers of the right size. Note that we could not use enum because the taint flag indexes are used also in assembly code. Then it reworks the table that describes the taint flags. The TAINT_* numbers can be used as the index. Instead, we add information if the taint flag is also shown per-module. Finally, it uses "unsigned long", bit operations, and the updated taint_flags table also for mod->taints. It is not optimal because only few taint flags can be printed by module_taint_flags(). But better be on the safe side. IMHO, it is not worth the optimization and this is a good compromise. Signed-off-by: Petr Mladek <pmladek@suse.com> Link: http://lkml.kernel.org/r/1474458442-21581-1-git-send-email-pmladek@suse.com [jeyu@redhat.com: fix broken lkml link in changelog] Signed-off-by: Jessica Yu <jeyu@redhat.com>
-rw-r--r--include/linux/kernel.h9
-rw-r--r--include/linux/module.h2
-rw-r--r--kernel/module.c33
-rw-r--r--kernel/panic.c53
4 files changed, 48 insertions, 49 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index bc6ed52a39b9..441def77246d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -506,6 +506,15 @@ extern enum system_states {
506#define TAINT_UNSIGNED_MODULE 13 506#define TAINT_UNSIGNED_MODULE 13
507#define TAINT_SOFTLOCKUP 14 507#define TAINT_SOFTLOCKUP 14
508#define TAINT_LIVEPATCH 15 508#define TAINT_LIVEPATCH 15
509#define TAINT_FLAGS_COUNT 16
510
511struct taint_flag {
512 char true; /* character printed when tainted */
513 char false; /* character printed when not tainted */
514 bool module; /* also show as a per-module taint flag */
515};
516
517extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
509 518
510extern const char hex_asc[]; 519extern const char hex_asc[];
511#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] 520#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
diff --git a/include/linux/module.h b/include/linux/module.h
index 0c3207d26ac0..f6ee569c62bb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -399,7 +399,7 @@ struct module {
399 /* Arch-specific module values */ 399 /* Arch-specific module values */
400 struct mod_arch_specific arch; 400 struct mod_arch_specific arch;
401 401
402 unsigned int taints; /* same bits as kernel:tainted */ 402 unsigned long taints; /* same bits as kernel:taint_flags */
403 403
404#ifdef CONFIG_GENERIC_BUG 404#ifdef CONFIG_GENERIC_BUG
405 /* Support for BUG */ 405 /* Support for BUG */
diff --git a/kernel/module.c b/kernel/module.c
index f57dd63186e6..a4acd8f403ae 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -330,7 +330,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
330 enum lockdep_ok lockdep_ok) 330 enum lockdep_ok lockdep_ok)
331{ 331{
332 add_taint(flag, lockdep_ok); 332 add_taint(flag, lockdep_ok);
333 mod->taints |= (1U << flag); 333 set_bit(flag, &mod->taints);
334} 334}
335 335
336/* 336/*
@@ -1138,24 +1138,13 @@ static inline int module_unload_init(struct module *mod)
1138static size_t module_flags_taint(struct module *mod, char *buf) 1138static size_t module_flags_taint(struct module *mod, char *buf)
1139{ 1139{
1140 size_t l = 0; 1140 size_t l = 0;
1141 int i;
1142
1143 for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
1144 if (taint_flags[i].module && test_bit(i, &mod->taints))
1145 buf[l++] = taint_flags[i].true;
1146 }
1141 1147
1142 if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
1143 buf[l++] = 'P';
1144 if (mod->taints & (1 << TAINT_OOT_MODULE))
1145 buf[l++] = 'O';
1146 if (mod->taints & (1 << TAINT_FORCED_MODULE))
1147 buf[l++] = 'F';
1148 if (mod->taints & (1 << TAINT_CRAP))
1149 buf[l++] = 'C';
1150 if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
1151 buf[l++] = 'E';
1152 if (mod->taints & (1 << TAINT_LIVEPATCH))
1153 buf[l++] = 'K';
1154 /*
1155 * TAINT_FORCED_RMMOD: could be added.
1156 * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
1157 * apply to modules.
1158 */
1159 return l; 1148 return l;
1160} 1149}
1161 1150
@@ -4041,6 +4030,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
4041} 4030}
4042#endif /* CONFIG_KALLSYMS */ 4031#endif /* CONFIG_KALLSYMS */
4043 4032
4033/* Maximum number of characters written by module_flags() */
4034#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
4035
4036/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
4044static char *module_flags(struct module *mod, char *buf) 4037static char *module_flags(struct module *mod, char *buf)
4045{ 4038{
4046 int bx = 0; 4039 int bx = 0;
@@ -4085,7 +4078,7 @@ static void m_stop(struct seq_file *m, void *p)
4085static int m_show(struct seq_file *m, void *p) 4078static int m_show(struct seq_file *m, void *p)
4086{ 4079{
4087 struct module *mod = list_entry(p, struct module, list); 4080 struct module *mod = list_entry(p, struct module, list);
4088 char buf[8]; 4081 char buf[MODULE_FLAGS_BUF_SIZE];
4089 4082
4090 /* We always ignore unformed modules. */ 4083 /* We always ignore unformed modules. */
4091 if (mod->state == MODULE_STATE_UNFORMED) 4084 if (mod->state == MODULE_STATE_UNFORMED)
@@ -4256,7 +4249,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
4256void print_modules(void) 4249void print_modules(void)
4257{ 4250{
4258 struct module *mod; 4251 struct module *mod;
4259 char buf[8]; 4252 char buf[MODULE_FLAGS_BUF_SIZE];
4260 4253
4261 printk(KERN_DEFAULT "Modules linked in:"); 4254 printk(KERN_DEFAULT "Modules linked in:");
4262 /* Most callers should already have preempt disabled, but make sure */ 4255 /* Most callers should already have preempt disabled, but make sure */
diff --git a/kernel/panic.c b/kernel/panic.c
index e6480e20379e..c51edaa04fce 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -298,30 +298,27 @@ void panic(const char *fmt, ...)
298 298
299EXPORT_SYMBOL(panic); 299EXPORT_SYMBOL(panic);
300 300
301 301/*
302struct tnt { 302 * TAINT_FORCED_RMMOD could be a per-module flag but the module
303 u8 bit; 303 * is being removed anyway.
304 char true; 304 */
305 char false; 305const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
306}; 306 { 'P', 'G', true }, /* TAINT_PROPRIETARY_MODULE */
307 307 { 'F', ' ', true }, /* TAINT_FORCED_MODULE */
308static const struct tnt tnts[] = { 308 { 'S', ' ', false }, /* TAINT_CPU_OUT_OF_SPEC */
309 { TAINT_PROPRIETARY_MODULE, 'P', 'G' }, 309 { 'R', ' ', false }, /* TAINT_FORCED_RMMOD */
310 { TAINT_FORCED_MODULE, 'F', ' ' }, 310 { 'M', ' ', false }, /* TAINT_MACHINE_CHECK */
311 { TAINT_CPU_OUT_OF_SPEC, 'S', ' ' }, 311 { 'B', ' ', false }, /* TAINT_BAD_PAGE */
312 { TAINT_FORCED_RMMOD, 'R', ' ' }, 312 { 'U', ' ', false }, /* TAINT_USER */
313 { TAINT_MACHINE_CHECK, 'M', ' ' }, 313 { 'D', ' ', false }, /* TAINT_DIE */
314 { TAINT_BAD_PAGE, 'B', ' ' }, 314 { 'A', ' ', false }, /* TAINT_OVERRIDDEN_ACPI_TABLE */
315 { TAINT_USER, 'U', ' ' }, 315 { 'W', ' ', false }, /* TAINT_WARN */
316 { TAINT_DIE, 'D', ' ' }, 316 { 'C', ' ', true }, /* TAINT_CRAP */
317 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' }, 317 { 'I', ' ', false }, /* TAINT_FIRMWARE_WORKAROUND */
318 { TAINT_WARN, 'W', ' ' }, 318 { 'O', ' ', true }, /* TAINT_OOT_MODULE */
319 { TAINT_CRAP, 'C', ' ' }, 319 { 'E', ' ', true }, /* TAINT_UNSIGNED_MODULE */
320 { TAINT_FIRMWARE_WORKAROUND, 'I', ' ' }, 320 { 'L', ' ', false }, /* TAINT_SOFTLOCKUP */
321 { TAINT_OOT_MODULE, 'O', ' ' }, 321 { 'K', ' ', true }, /* TAINT_LIVEPATCH */
322 { TAINT_UNSIGNED_MODULE, 'E', ' ' },
323 { TAINT_SOFTLOCKUP, 'L', ' ' },
324 { TAINT_LIVEPATCH, 'K', ' ' },
325}; 322};
326 323
327/** 324/**
@@ -348,16 +345,16 @@ static const struct tnt tnts[] = {
348 */ 345 */
349const char *print_tainted(void) 346const char *print_tainted(void)
350{ 347{
351 static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ")]; 348 static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
352 349
353 if (tainted_mask) { 350 if (tainted_mask) {
354 char *s; 351 char *s;
355 int i; 352 int i;
356 353
357 s = buf + sprintf(buf, "Tainted: "); 354 s = buf + sprintf(buf, "Tainted: ");
358 for (i = 0; i < ARRAY_SIZE(tnts); i++) { 355 for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
359 const struct tnt *t = &tnts[i]; 356 const struct taint_flag *t = &taint_flags[i];
360 *s++ = test_bit(t->bit, &tainted_mask) ? 357 *s++ = test_bit(i, &tainted_mask) ?
361 t->true : t->false; 358 t->true : t->false;
362 } 359 }
363 *s = 0; 360 *s = 0;