Commit bcdcd8e7 authored by Pavel Emelianov's avatar Pavel Emelianov Committed by Linus Torvalds

Report that kernel is tainted if there was an OOPS

If the kernel OOPSed or BUGed then it probably should be considered as
tainted.  Thus, all subsequent OOPSes and SysRq dumps will report the
tainted kernel.  This saves a lot of time explaining oddities in the
calltraces.
Signed-off-by: default avatarPavel Emelianov <xemul@openvz.org>
Acked-by: default avatarRandy Dunlap <randy.dunlap@oracle.com>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
[ Added parisc patch from Matthew Wilson  -Linus ]
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 74489a91
...@@ -251,6 +251,8 @@ characters, each representing a particular tainted value. ...@@ -251,6 +251,8 @@ characters, each representing a particular tainted value.
7: 'U' if a user or user application specifically requested that the 7: 'U' if a user or user application specifically requested that the
Tainted flag be set, ' ' otherwise. Tainted flag be set, ' ' otherwise.
8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
The primary reason for the 'Tainted: ' string is to tell kernel The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is occurred. Tainting is permanent: even if an offending module is
......
...@@ -184,6 +184,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) ...@@ -184,6 +184,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
#endif #endif
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
dik_show_regs(regs, r9_15); dik_show_regs(regs, r9_15);
add_taint(TAINT_DIE);
dik_show_trace((unsigned long *)(regs+1)); dik_show_trace((unsigned long *)(regs+1));
dik_show_code((unsigned int *)regs->pc); dik_show_code((unsigned int *)regs->pc);
......
...@@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) ...@@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(1); bust_spinlocks(1);
__die(str, err, thread, regs); __die(str, err, thread, regs);
bust_spinlocks(0); bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (in_interrupt()) if (in_interrupt())
......
...@@ -185,6 +185,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) ...@@ -185,6 +185,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
printk("Internal error: %s: %x\n", str, err); printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d\n", smp_processor_id()); printk("CPU: %d\n", smp_processor_id());
show_regs(regs); show_regs(regs);
add_taint(TAINT_DIE);
printk("Process %s (pid: %d, stack limit = 0x%p)\n", printk("Process %s (pid: %d, stack limit = 0x%p)\n",
current->comm, current->pid, end_of_stack(tsk)); current->comm, current->pid, end_of_stack(tsk));
......
...@@ -56,6 +56,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) ...@@ -56,6 +56,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
show_regs_log_lvl(regs, KERN_EMERG); show_regs_log_lvl(regs, KERN_EMERG);
show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
bust_spinlocks(0); bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (in_interrupt()) if (in_interrupt())
......
...@@ -433,6 +433,7 @@ void die(const char * str, struct pt_regs * regs, long err) ...@@ -433,6 +433,7 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(0); bust_spinlocks(0);
die.lock_owner = -1; die.lock_owner = -1;
add_taint(TAINT_DIE);
spin_unlock_irqrestore(&die.lock, flags); spin_unlock_irqrestore(&die.lock, flags);
if (!regs) if (!regs)
......
...@@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err) ...@@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err)
bust_spinlocks(0); bust_spinlocks(0);
die.lock_owner = -1; die.lock_owner = -1;
add_taint(TAINT_DIE);
spin_unlock_irq(&die.lock); spin_unlock_irq(&die.lock);
if (panic_on_oops) if (panic_on_oops)
......
...@@ -1170,6 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) ...@@ -1170,6 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
console_verbose(); console_verbose();
printk("%s: %08x\n",str,nr); printk("%s: %08x\n",str,nr);
show_registers(fp); show_registers(fp);
add_taint(TAINT_DIE);
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -83,6 +83,7 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr) ...@@ -83,6 +83,7 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr)
printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, PAGE_SIZE+(unsigned long)current); current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
show_stack(NULL, (unsigned long *)fp); show_stack(NULL, (unsigned long *)fp);
add_taint(TAINT_DIE);
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) ...@@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs)
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter); printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs); show_registers(regs);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (in_interrupt()) if (in_interrupt())
......
...@@ -264,6 +264,7 @@ KERN_CRIT " || ||\n"); ...@@ -264,6 +264,7 @@ KERN_CRIT " || ||\n");
show_regs(regs); show_regs(regs);
dump_stack(); dump_stack();
add_taint(TAINT_DIE);
if (in_interrupt()) if (in_interrupt())
panic("Fatal exception in interrupt"); panic("Fatal exception in interrupt");
......
...@@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err) ...@@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err)
bust_spinlocks(0); bust_spinlocks(0);
die.lock_owner = -1; die.lock_owner = -1;
add_taint(TAINT_DIE);
spin_unlock_irqrestore(&die.lock, flags); spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current) || if (kexec_should_crash(current) ||
......
...@@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err) ...@@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err)
if (nl) if (nl)
printk("\n"); printk("\n");
show_regs(fp); show_regs(fp);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
/* do_exit() should take care of panic'ing from an interrupt /* do_exit() should take care of panic'ing from an interrupt
* context so we don't handle it here * context so we don't handle it here
......
...@@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err) ...@@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err)
print_modules(); print_modules();
show_regs(regs); show_regs(regs);
bust_spinlocks(0); bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (in_interrupt()) if (in_interrupt())
panic("Fatal exception in interrupt"); panic("Fatal exception in interrupt");
......
...@@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err) ...@@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err)
(unsigned long)task_stack_page(current)); (unsigned long)task_stack_page(current));
bust_spinlocks(0); bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (kexec_should_crash(current)) if (kexec_should_crash(current))
......
...@@ -101,6 +101,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) ...@@ -101,6 +101,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
show_regs(regs); show_regs(regs);
add_taint(TAINT_DIE);
__SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE;
__SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE;
......
...@@ -2225,6 +2225,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) ...@@ -2225,6 +2225,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw"); __asm__ __volatile__("flushw");
__show_regs(regs); __show_regs(regs);
add_taint(TAINT_DIE);
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
struct reg_window *rw = (struct reg_window *) struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS); (regs->u_regs[UREG_FP] + STACK_BIAS);
......
...@@ -518,6 +518,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) ...@@ -518,6 +518,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk("\n"); printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
show_registers(regs); show_registers(regs);
add_taint(TAINT_DIE);
/* Executive summary in case the oops scrolled away */ /* Executive summary in case the oops scrolled away */
printk(KERN_ALERT "RIP "); printk(KERN_ALERT "RIP ");
printk_address(regs->rip); printk_address(regs->rip);
......
...@@ -482,6 +482,7 @@ void die(const char * str, struct pt_regs * regs, long err) ...@@ -482,6 +482,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (!user_mode(regs)) if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]); show_stack(NULL, (unsigned long*)regs->areg[1]);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
if (in_interrupt()) if (in_interrupt())
......
...@@ -210,6 +210,7 @@ extern enum system_states { ...@@ -210,6 +210,7 @@ extern enum system_states {
#define TAINT_MACHINE_CHECK (1<<4) #define TAINT_MACHINE_CHECK (1<<4)
#define TAINT_BAD_PAGE (1<<5) #define TAINT_BAD_PAGE (1<<5)
#define TAINT_USER (1<<6) #define TAINT_USER (1<<6)
#define TAINT_DIE (1<<7)
extern void dump_stack(void); extern void dump_stack(void);
......
...@@ -159,14 +159,15 @@ const char *print_tainted(void) ...@@ -159,14 +159,15 @@ const char *print_tainted(void)
{ {
static char buf[20]; static char buf[20];
if (tainted) { if (tainted) {
snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c", snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c",
tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ', tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
tainted & TAINT_BAD_PAGE ? 'B' : ' ', tainted & TAINT_BAD_PAGE ? 'B' : ' ',
tainted & TAINT_USER ? 'U' : ' '); tainted & TAINT_USER ? 'U' : ' ',
tainted & TAINT_DIE ? 'D' : ' ');
} }
else else
snprintf(buf, sizeof(buf), "Not tainted"); snprintf(buf, sizeof(buf), "Not tainted");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment