Skip to content

Commit 7fd8329

Browse files
pmladekJessica Yu
authored andcommitted
taint/module: Clean up global and module taint flags handling
The commit 66cc69e ("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 2bc2d61 ("[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 25ddbb1 ("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>
1 parent c7d47f2 commit 7fd8329

4 files changed

Lines changed: 48 additions & 49 deletions

File tree

include/linux/kernel.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,15 @@ extern enum system_states {
506506
#define TAINT_UNSIGNED_MODULE 13
507507
#define TAINT_SOFTLOCKUP 14
508508
#define TAINT_LIVEPATCH 15
509+
#define TAINT_FLAGS_COUNT 16
510+
511+
struct 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+
517+
extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
509518

510519
extern const char hex_asc[];
511520
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]

include/linux/module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ struct module {
399399
/* Arch-specific module values */
400400
struct mod_arch_specific arch;
401401

402-
unsigned int taints; /* same bits as kernel:tainted */
402+
unsigned long taints; /* same bits as kernel:taint_flags */
403403

404404
#ifdef CONFIG_GENERIC_BUG
405405
/* Support for BUG */

kernel/module.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
330330
enum lockdep_ok lockdep_ok)
331331
{
332332
add_taint(flag, lockdep_ok);
333-
mod->taints |= (1U << flag);
333+
set_bit(flag, &mod->taints);
334334
}
335335

336336
/*
@@ -1138,24 +1138,13 @@ static inline int module_unload_init(struct module *mod)
11381138
static size_t module_flags_taint(struct module *mod, char *buf)
11391139
{
11401140
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+
}
11411147

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-
*/
11591148
return l;
11601149
}
11611150

@@ -4041,6 +4030,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
40414030
}
40424031
#endif /* CONFIG_KALLSYMS */
40434032

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 !!! */
40444037
static char *module_flags(struct module *mod, char *buf)
40454038
{
40464039
int bx = 0;
@@ -4085,7 +4078,7 @@ static void m_stop(struct seq_file *m, void *p)
40854078
static int m_show(struct seq_file *m, void *p)
40864079
{
40874080
struct module *mod = list_entry(p, struct module, list);
4088-
char buf[8];
4081+
char buf[MODULE_FLAGS_BUF_SIZE];
40894082

40904083
/* We always ignore unformed modules. */
40914084
if (mod->state == MODULE_STATE_UNFORMED)
@@ -4256,7 +4249,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
42564249
void print_modules(void)
42574250
{
42584251
struct module *mod;
4259-
char buf[8];
4252+
char buf[MODULE_FLAGS_BUF_SIZE];
42604253

42614254
printk(KERN_DEFAULT "Modules linked in:");
42624255
/* Most callers should already have preempt disabled, but make sure */

kernel/panic.c

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -298,30 +298,27 @@ void panic(const char *fmt, ...)
298298

299299
EXPORT_SYMBOL(panic);
300300

301-
302-
struct tnt {
303-
u8 bit;
304-
char true;
305-
char false;
306-
};
307-
308-
static const struct tnt tnts[] = {
309-
{ TAINT_PROPRIETARY_MODULE, 'P', 'G' },
310-
{ TAINT_FORCED_MODULE, 'F', ' ' },
311-
{ TAINT_CPU_OUT_OF_SPEC, 'S', ' ' },
312-
{ TAINT_FORCED_RMMOD, 'R', ' ' },
313-
{ TAINT_MACHINE_CHECK, 'M', ' ' },
314-
{ TAINT_BAD_PAGE, 'B', ' ' },
315-
{ TAINT_USER, 'U', ' ' },
316-
{ TAINT_DIE, 'D', ' ' },
317-
{ TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
318-
{ TAINT_WARN, 'W', ' ' },
319-
{ TAINT_CRAP, 'C', ' ' },
320-
{ TAINT_FIRMWARE_WORKAROUND, 'I', ' ' },
321-
{ TAINT_OOT_MODULE, 'O', ' ' },
322-
{ TAINT_UNSIGNED_MODULE, 'E', ' ' },
323-
{ TAINT_SOFTLOCKUP, 'L', ' ' },
324-
{ TAINT_LIVEPATCH, 'K', ' ' },
301+
/*
302+
* TAINT_FORCED_RMMOD could be a per-module flag but the module
303+
* is being removed anyway.
304+
*/
305+
const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
306+
{ 'P', 'G', true }, /* TAINT_PROPRIETARY_MODULE */
307+
{ 'F', ' ', true }, /* TAINT_FORCED_MODULE */
308+
{ 'S', ' ', false }, /* TAINT_CPU_OUT_OF_SPEC */
309+
{ 'R', ' ', false }, /* TAINT_FORCED_RMMOD */
310+
{ 'M', ' ', false }, /* TAINT_MACHINE_CHECK */
311+
{ 'B', ' ', false }, /* TAINT_BAD_PAGE */
312+
{ 'U', ' ', false }, /* TAINT_USER */
313+
{ 'D', ' ', false }, /* TAINT_DIE */
314+
{ 'A', ' ', false }, /* TAINT_OVERRIDDEN_ACPI_TABLE */
315+
{ 'W', ' ', false }, /* TAINT_WARN */
316+
{ 'C', ' ', true }, /* TAINT_CRAP */
317+
{ 'I', ' ', false }, /* TAINT_FIRMWARE_WORKAROUND */
318+
{ 'O', ' ', true }, /* TAINT_OOT_MODULE */
319+
{ 'E', ' ', true }, /* TAINT_UNSIGNED_MODULE */
320+
{ 'L', ' ', false }, /* TAINT_SOFTLOCKUP */
321+
{ 'K', ' ', true }, /* TAINT_LIVEPATCH */
325322
};
326323

327324
/**
@@ -348,16 +345,16 @@ static const struct tnt tnts[] = {
348345
*/
349346
const char *print_tainted(void)
350347
{
351-
static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ")];
348+
static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
352349

353350
if (tainted_mask) {
354351
char *s;
355352
int i;
356353

357354
s = buf + sprintf(buf, "Tainted: ");
358-
for (i = 0; i < ARRAY_SIZE(tnts); i++) {
359-
const struct tnt *t = &tnts[i];
360-
*s++ = test_bit(t->bit, &tainted_mask) ?
355+
for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
356+
const struct taint_flag *t = &taint_flags[i];
357+
*s++ = test_bit(i, &tainted_mask) ?
361358
t->true : t->false;
362359
}
363360
*s = 0;

0 commit comments

Comments
 (0)