Skip to content

Commit

Permalink
taint: add explicit flag to show whether lock dep is still OK.
Browse files Browse the repository at this point in the history
Fix up all callers as they were before, with make one change: an
unsigned module taints the kernel, but doesn't turn off lockdep.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Jan 21, 2013
1 parent 64748a2 commit 373d4d0
Show file tree
Hide file tree
Showing 37 changed files with 69 additions and 67 deletions.
2 changes: 1 addition & 1 deletion arch/alpha/kernel/traps.c
Expand Up @@ -186,7 +186,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
#endif
printk("%s(%d): %s %ld\n", current->comm, task_pid_nr(current), str, err);
dik_show_regs(regs, r9_15);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
dik_show_trace((unsigned long *)(regs+1));
dik_show_code((unsigned int *)regs->pc);

Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/traps.c
Expand Up @@ -296,7 +296,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr)

bust_spinlocks(0);
die_owner = -1;
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
die_nest_count--;
if (!die_nest_count)
/* Nest count reaches zero, release the lock. */
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/traps.c
Expand Up @@ -242,7 +242,7 @@ void die(const char *str, struct pt_regs *regs, int err)
crash_kexec(regs);

bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
raw_spin_unlock_irq(&die_lock);
oops_exit();

Expand Down
2 changes: 1 addition & 1 deletion arch/avr32/kernel/traps.c
Expand Up @@ -61,7 +61,7 @@ void die(const char *str, struct pt_regs *regs, long err)
show_regs_log_lvl(regs, KERN_EMERG);
show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
2 changes: 1 addition & 1 deletion arch/hexagon/kernel/traps.c
Expand Up @@ -225,7 +225,7 @@ int die(const char *str, struct pt_regs *regs, long err)
do_show_stack(current, &regs->r30, pt_elr(regs));

bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);

spin_unlock_irq(&die.lock);

Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/traps.c
Expand Up @@ -72,7 +72,7 @@ die (const char *str, struct pt_regs *regs, long err)

bust_spinlocks(0);
die.lock_owner = -1;
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die.lock);

if (!regs)
Expand Down
2 changes: 1 addition & 1 deletion arch/m68k/kernel/traps.c
Expand Up @@ -1176,7 +1176,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
console_verbose();
printk("%s: %08x\n",str,nr);
show_registers(fp);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
do_exit(SIGSEGV);
}

Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/traps.c
Expand Up @@ -396,7 +396,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)

printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
raw_spin_unlock_irq(&die_lock);

oops_exit();
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/kernel/traps.c
Expand Up @@ -282,7 +282,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)

show_regs(regs);
dump_stack();
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);

if (in_interrupt())
panic("Fatal exception in interrupt");
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/traps.c
Expand Up @@ -138,7 +138,7 @@ static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs,
{
bust_spinlocks(0);
die_owner = -1;
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
die_nest_count--;
oops_exit();
printk("\n");
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/traps.c
Expand Up @@ -271,7 +271,7 @@ void die(struct pt_regs *regs, const char *str)
print_modules();
show_regs(regs);
bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
panic("Fatal exception in interrupt");
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/traps.c
Expand Up @@ -38,7 +38,7 @@ void die(const char *str, struct pt_regs *regs, long err)
notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);

bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);
oops_exit();

Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/setup_64.c
Expand Up @@ -115,7 +115,7 @@ static void __init process_switch(char c)
break;
}
cheetah_pcache_forced_on = 1;
add_taint(TAINT_MACHINE_CHECK);
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
cheetah_enable_pcache();
break;

Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/traps_32.c
Expand Up @@ -58,7 +58,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)

printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
show_regs(regs);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);

__SAVE; __SAVE; __SAVE; __SAVE;
__SAVE; __SAVE; __SAVE; __SAVE;
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/traps_64.c
Expand Up @@ -2383,7 +2383,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw");
show_regs(regs);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
if (regs->tstate & TSTATE_PRIV) {
struct thread_info *tp = current_thread_info();
struct reg_window *rw = (struct reg_window *)
Expand Down
2 changes: 1 addition & 1 deletion arch/unicore32/kernel/traps.c
Expand Up @@ -231,7 +231,7 @@ void die(const char *str, struct pt_regs *regs, int err)
ret = __die(str, err, thread, regs);

bust_spinlocks(0);
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);
oops_exit();

Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/cpu/amd.c
Expand Up @@ -220,8 +220,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
*/
WARN_ONCE(1, "WARNING: This combination of AMD"
" processors is not suitable for SMP.\n");
if (!test_taint(TAINT_UNSAFE_SMP))
add_taint(TAINT_UNSAFE_SMP);
add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);

valid_k7:
;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/mcheck/mce.c
Expand Up @@ -1085,7 +1085,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
/*
* Set taint even when machine check was not enabled.
*/
add_taint(TAINT_MACHINE_CHECK);
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);

severity = mce_severity(&m, cfg->tolerant, NULL);

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/mcheck/p5.c
Expand Up @@ -33,7 +33,7 @@ static void pentium_machine_check(struct pt_regs *regs, long error_code)
smp_processor_id());
}

add_taint(TAINT_MACHINE_CHECK);
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
}

/* Set up machine check reporting for processors with Intel style MCE: */
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/mcheck/winchip.c
Expand Up @@ -15,7 +15,7 @@
static void winchip_machine_check(struct pt_regs *regs, long error_code)
{
printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
add_taint(TAINT_MACHINE_CHECK);
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
}

/* Set up machine check reporting on the Winchip C6 series */
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/mtrr/generic.c
Expand Up @@ -542,7 +542,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,

if (tmp != mask_lo) {
printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
add_taint(TAINT_FIRMWARE_WORKAROUND);
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
mask_lo = tmp;
}
}
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/dumpstack.c
Expand Up @@ -232,7 +232,7 @@ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)

bust_spinlocks(0);
die_owner = -1;
add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
die_nest_count--;
if (!die_nest_count)
/* Nest count reaches zero, release the lock. */
Expand Down
2 changes: 1 addition & 1 deletion arch/xtensa/kernel/traps.c
Expand Up @@ -524,7 +524,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]);

add_taint(TAINT_DIE);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/custom_method.c
Expand Up @@ -66,7 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
buf = NULL;
if (ACPI_FAILURE(status))
return -EINVAL;
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
}

return count;
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/osl.c
Expand Up @@ -661,7 +661,7 @@ static void acpi_table_taint(struct acpi_table_header *table)
pr_warn(PREFIX
"Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
table->signature, table->oem_table_id);
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
}


Expand Down
2 changes: 1 addition & 1 deletion drivers/base/regmap/regmap-debugfs.c
Expand Up @@ -267,7 +267,7 @@ static ssize_t regmap_map_write_file(struct file *file,
return -EINVAL;

/* Userspace has been fiddling around behind the kernel's back */
add_taint(TAINT_USER);
add_taint(TAINT_USER, LOCKDEP_NOW_UNRELIABLE);

regmap_write(map, reg, value);
return buf_size;
Expand Down
6 changes: 5 additions & 1 deletion include/linux/kernel.h
Expand Up @@ -398,7 +398,11 @@ extern int panic_on_unrecovered_nmi;
extern int panic_on_io_nmi;
extern int sysctl_panic_on_stackoverflow;
extern const char *print_tainted(void);
extern void add_taint(unsigned flag);
enum lockdep_ok {
LOCKDEP_STILL_OK,
LOCKDEP_NOW_UNRELIABLE
};
extern void add_taint(unsigned flag, enum lockdep_ok);
extern int test_taint(unsigned flag);
extern unsigned long get_taint(void);
extern int root_mountflags;
Expand Down
26 changes: 15 additions & 11 deletions kernel/module.c
Expand Up @@ -197,9 +197,10 @@ static inline int strong_try_module_get(struct module *mod)
return -ENOENT;
}

static inline void add_taint_module(struct module *mod, unsigned flag)
static inline void add_taint_module(struct module *mod, unsigned flag,
enum lockdep_ok lockdep_ok)
{
add_taint(flag);
add_taint(flag, lockdep_ok);
mod->taints |= (1U << flag);
}

Expand Down Expand Up @@ -727,7 +728,7 @@ static inline int try_force_unload(unsigned int flags)
{
int ret = (flags & O_TRUNC);
if (ret)
add_taint(TAINT_FORCED_RMMOD);
add_taint(TAINT_FORCED_RMMOD, LOCKDEP_NOW_UNRELIABLE);
return ret;
}
#else
Expand Down Expand Up @@ -1138,7 +1139,7 @@ static int try_to_force_load(struct module *mod, const char *reason)
if (!test_taint(TAINT_FORCED_MODULE))
printk(KERN_WARNING "%s: %s: kernel tainted.\n",
mod->name, reason);
add_taint_module(mod, TAINT_FORCED_MODULE);
add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_NOW_UNRELIABLE);
return 0;
#else
return -ENOEXEC;
Expand Down Expand Up @@ -2147,7 +2148,8 @@ static void set_license(struct module *mod, const char *license)
if (!test_taint(TAINT_PROPRIETARY_MODULE))
printk(KERN_WARNING "%s: module license '%s' taints "
"kernel.\n", mod->name, license);
add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
LOCKDEP_NOW_UNRELIABLE);
}
}

Expand Down Expand Up @@ -2700,10 +2702,10 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
}

if (!get_modinfo(info, "intree"))
add_taint_module(mod, TAINT_OOT_MODULE);
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);

if (get_modinfo(info, "staging")) {
add_taint_module(mod, TAINT_CRAP);
add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
printk(KERN_WARNING "%s: module is from the staging directory,"
" the quality is unknown, you have been warned.\n",
mod->name);
Expand Down Expand Up @@ -2869,15 +2871,17 @@ static int check_module_license_and_versions(struct module *mod)
* using GPL-only symbols it needs.
*/
if (strcmp(mod->name, "ndiswrapper") == 0)
add_taint(TAINT_PROPRIETARY_MODULE);
add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);

/* driverloader was caught wrongly pretending to be under GPL */
if (strcmp(mod->name, "driverloader") == 0)
add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
LOCKDEP_NOW_UNRELIABLE);

/* lve claims to be GPL but upstream won't provide source */
if (strcmp(mod->name, "lve") == 0)
add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
LOCKDEP_NOW_UNRELIABLE);

#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !mod->crcs)
Expand Down Expand Up @@ -3197,7 +3201,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
"%s: module verification failed: signature and/or"
" required key missing - tainting kernel\n",
mod->name);
add_taint_module(mod, TAINT_FORCED_MODULE);
add_taint_module(mod, TAINT_FORCED_MODULE, LOCKDEP_STILL_OK);
}
#endif

Expand Down
34 changes: 14 additions & 20 deletions kernel/panic.c
Expand Up @@ -259,26 +259,19 @@ unsigned long get_taint(void)
return tainted_mask;
}

void add_taint(unsigned flag)
/**
* add_taint: add a taint flag if not already set.
* @flag: one of the TAINT_* constants.
* @lockdep_ok: whether lock debugging is still OK.
*
* If something bad has gone wrong, you'll want @lockdebug_ok = false, but for
* some notewortht-but-not-corrupting cases, it can be set to true.
*/
void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
{
/*
* Can't trust the integrity of the kernel anymore.
* We don't call directly debug_locks_off() because the issue
* is not necessarily serious enough to set oops_in_progress to 1
* Also we want to keep up lockdep for staging/out-of-tree
* development and post-warning case.
*/
switch (flag) {
case TAINT_CRAP:
case TAINT_OOT_MODULE:
case TAINT_WARN:
case TAINT_FIRMWARE_WORKAROUND:
break;

default:
if (__debug_locks_off())
printk(KERN_WARNING "Disabling lock debugging due to kernel taint\n");
}
if (lockdep_ok == LOCKDEP_NOW_UNRELIABLE && __debug_locks_off())
printk(KERN_WARNING
"Disabling lock debugging due to kernel taint\n");

set_bit(flag, &tainted_mask);
}
Expand Down Expand Up @@ -421,7 +414,8 @@ static void warn_slowpath_common(const char *file, int line, void *caller,
print_modules();
dump_stack();
print_oops_end_marker();
add_taint(taint);
/* Just a warning, don't kill lockdep. */
add_taint(taint, LOCKDEP_STILL_OK);
}

void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
Expand Down
2 changes: 1 addition & 1 deletion kernel/sched/core.c
Expand Up @@ -2785,7 +2785,7 @@ static noinline void __schedule_bug(struct task_struct *prev)
if (irqs_disabled())
print_irqtrace_events(prev);
dump_stack();
add_taint(TAINT_WARN);
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion kernel/sysctl.c
Expand Up @@ -2006,7 +2006,7 @@ static int proc_taint(struct ctl_table *table, int write,
int i;
for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
if ((tmptaint >> i) & 1)
add_taint(i);
add_taint(i, LOCKDEP_STILL_OK);
}
}

Expand Down

0 comments on commit 373d4d0

Please sign in to comment.