Skip to content

Commit

Permalink
Report that kernel is tainted if there was an OOPS
Browse files Browse the repository at this point in the history
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: Pavel Emelianov <xemul@openvz.org>
Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ Added parisc patch from Matthew Wilson  -Linus ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Pavel Emelianov authored and Linus Torvalds committed Jul 17, 2007
1 parent 74489a9 commit bcdcd8e
Show file tree
Hide file tree
Showing 21 changed files with 24 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Documentation/oops-tracing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ characters, each representing a particular tainted value.
7: 'U' if a user or user application specifically requested that the
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
debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is
Expand Down
1 change: 1 addition & 0 deletions arch/alpha/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,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, current->pid, str, err);
dik_show_regs(regs, r9_15);
add_taint(TAINT_DIE);
dik_show_trace((unsigned long *)(regs+1));
dik_show_code((unsigned int *)regs->pc);

Expand Down
1 change: 1 addition & 0 deletions arch/arm/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(1);
__die(str, err, thread, regs);
bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
1 change: 1 addition & 0 deletions arch/arm26/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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("CPU: %d\n", smp_processor_id());
show_regs(regs);
add_taint(TAINT_DIE);
printk("Process %s (pid: %d, stack limit = 0x%p)\n",
current->comm, current->pid, end_of_stack(tsk));

Expand Down
1 change: 1 addition & 0 deletions arch/avr32/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
1 change: 1 addition & 0 deletions arch/i386/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ void die(const char * str, struct pt_regs * regs, long err)

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

if (!regs)
Expand Down
1 change: 1 addition & 0 deletions arch/ia64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err)

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

if (panic_on_oops)
Expand Down
1 change: 1 addition & 0 deletions arch/m68k/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,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);
do_exit(SIGSEGV);
}

Expand Down
1 change: 1 addition & 0 deletions arch/m68knommu/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
show_stack(NULL, (unsigned long *)fp);
add_taint(TAINT_DIE);
do_exit(SIGSEGV);
}

Expand Down
1 change: 1 addition & 0 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs)
#endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
1 change: 1 addition & 0 deletions arch/parisc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ KERN_CRIT " || ||\n");

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

if (in_interrupt())
panic("Fatal exception in interrupt");
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err)

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

if (kexec_should_crash(current) ||
Expand Down
1 change: 1 addition & 0 deletions arch/ppc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err)
if (nl)
printk("\n");
show_regs(fp);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
/* do_exit() should take care of panic'ing from an interrupt
* context so we don't handle it here
Expand Down
1 change: 1 addition & 0 deletions arch/s390/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err)
print_modules();
show_regs(regs);
bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
panic("Fatal exception in interrupt");
Expand Down
1 change: 1 addition & 0 deletions arch/sh/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err)
(unsigned long)task_stack_page(current));

bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);

if (kexec_should_crash(current))
Expand Down
1 change: 1 addition & 0 deletions arch/sparc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
show_regs(regs);
add_taint(TAINT_DIE);

__SAVE; __SAVE; __SAVE; __SAVE;
__SAVE; __SAVE; __SAVE; __SAVE;
Expand Down
1 change: 1 addition & 0 deletions arch/sparc64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,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);
if (regs->tstate & TSTATE_PRIV) {
struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);
Expand Down
1 change: 1 addition & 0 deletions arch/x86_64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
show_registers(regs);
add_taint(TAINT_DIE);
/* Executive summary in case the oops scrolled away */
printk(KERN_ALERT "RIP ");
printk_address(regs->rip);
Expand Down
1 change: 1 addition & 0 deletions arch/xtensa/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,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);
spin_unlock_irq(&die_lock);

if (in_interrupt())
Expand Down
1 change: 1 addition & 0 deletions include/linux/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ extern enum system_states {
#define TAINT_MACHINE_CHECK (1<<4)
#define TAINT_BAD_PAGE (1<<5)
#define TAINT_USER (1<<6)
#define TAINT_DIE (1<<7)

extern void dump_stack(void);

Expand Down
5 changes: 3 additions & 2 deletions kernel/panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,15 @@ const char *print_tainted(void)
{
static char buf[20];
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_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
tainted & TAINT_BAD_PAGE ? 'B' : ' ',
tainted & TAINT_USER ? 'U' : ' ');
tainted & TAINT_USER ? 'U' : ' ',
tainted & TAINT_DIE ? 'D' : ' ');
}
else
snprintf(buf, sizeof(buf), "Not tainted");
Expand Down

0 comments on commit bcdcd8e

Please sign in to comment.