exit: Add and use make_task_dead.
There are two big uses of do_exit. The first is it's design use to be the guts of the exit(2) system call. The second use is to terminate a task after something catastrophic has happened like a NULL pointer in kernel code. Add a function make_task_dead that is initialy exactly the same as do_exit to cover the cases where do_exit is called to handle catastrophic failure. In time this can probably be reduced to just a light wrapper around do_task_dead. For now keep it exactly the same so that there will be no behavioral differences introducing this new concept. Replace all of the uses of do_exit that use it for catastraphic task cleanup with make_task_dead to make it clear what the code is doing. As part of this rename rewind_stack_do_exit rewind_stack_and_make_dead. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
parent
5e354747b2
commit
0e25498f8c
|
@ -190,7 +190,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
|
|||
local_irq_enable();
|
||||
while (1);
|
||||
}
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MATHEMU
|
||||
|
@ -575,7 +575,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
|
|||
|
||||
printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
|
||||
pc, va, opcode, reg);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
|
||||
got_exception:
|
||||
/* Ok, we caught the exception, but we don't want it. Is there
|
||||
|
@ -630,7 +630,7 @@ got_exception:
|
|||
local_irq_enable();
|
||||
while (1);
|
||||
}
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -204,7 +204,7 @@ retry:
|
|||
printk(KERN_ALERT "Unable to handle kernel paging request at "
|
||||
"virtual address %016lx\n", address);
|
||||
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
|
||||
/* We ran out of memory, or some other thing happened to us that
|
||||
made us unable to handle the page fault gracefully. */
|
||||
|
|
|
@ -333,7 +333,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
if (signr)
|
||||
do_exit(signr);
|
||||
make_task_dead(signr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -111,7 +111,7 @@ static void die_kernel_fault(const char *msg, struct mm_struct *mm,
|
|||
show_pte(KERN_ALERT, mm, addr);
|
||||
die("Oops", regs, fsr);
|
||||
bust_spinlocks(0);
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -235,7 +235,7 @@ void die(const char *str, struct pt_regs *regs, int err)
|
|||
raw_spin_unlock_irqrestore(&die_lock, flags);
|
||||
|
||||
if (ret != NOTIFY_STOP)
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
static void arm64_show_signal(int signo, const char *str)
|
||||
|
|
|
@ -302,7 +302,7 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
|
|||
show_pte(addr);
|
||||
die("Oops", regs, esr);
|
||||
bust_spinlocks(0);
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KASAN_HW_TAGS
|
||||
|
|
|
@ -294,7 +294,7 @@ bad_area:
|
|||
__func__, opcode, rz, rx, imm, addr);
|
||||
show_regs(regs);
|
||||
bust_spinlocks(0);
|
||||
do_exit(SIGKILL);
|
||||
make_dead_task(SIGKILL);
|
||||
}
|
||||
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
|
||||
|
|
|
@ -109,7 +109,7 @@ void die(struct pt_regs *regs, const char *str)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
if (ret != NOTIFY_STOP)
|
||||
do_exit(SIGSEGV);
|
||||
make_dead_task(SIGSEGV);
|
||||
}
|
||||
|
||||
void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
|
||||
|
|
|
@ -67,7 +67,7 @@ static inline void no_context(struct pt_regs *regs, unsigned long addr)
|
|||
pr_alert("Unable to handle kernel paging request at virtual "
|
||||
"addr 0x%08lx, pc: 0x%08lx\n", addr, regs->pc);
|
||||
die(regs, "Oops");
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_fault_t fault)
|
||||
|
|
|
@ -106,7 +106,7 @@ void die(const char *str, struct pt_regs *fp, unsigned long err)
|
|||
dump(fp);
|
||||
|
||||
spin_unlock_irq(&die_lock);
|
||||
do_exit(SIGSEGV);
|
||||
make_dead_task(SIGSEGV);
|
||||
}
|
||||
|
||||
static int kstack_depth_to_print = 24;
|
||||
|
|
|
@ -51,7 +51,7 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
printk(" at virtual address %08lx\n", address);
|
||||
if (!user_mode(regs))
|
||||
die("Oops", regs, error_code);
|
||||
do_exit(SIGKILL);
|
||||
make_dead_task(SIGKILL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ int die(const char *str, struct pt_regs *regs, long err)
|
|||
panic("Fatal exception");
|
||||
|
||||
oops_exit();
|
||||
do_exit(err);
|
||||
make_dead_task(err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
|
|||
spin_unlock(&mca_bh_lock);
|
||||
|
||||
/* This process is about to be killed itself */
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -85,7 +85,7 @@ die (const char *str, struct pt_regs *regs, long err)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ retry:
|
|||
regs = NULL;
|
||||
bust_spinlocks(0);
|
||||
if (regs)
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
return;
|
||||
|
||||
out_of_memory:
|
||||
|
|
|
@ -1131,7 +1131,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
|
|||
pr_crit("%s: %08x\n", str, nr);
|
||||
show_registers(fp);
|
||||
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
asmlinkage void set_esp0(unsigned long ssp)
|
||||
|
|
|
@ -48,7 +48,7 @@ int send_fault_sig(struct pt_regs *regs)
|
|||
pr_alert("Unable to handle kernel access");
|
||||
pr_cont(" at virtual address %p\n", addr);
|
||||
die_if_kernel("Oops", regs, 0 /*error_code*/);
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -44,10 +44,10 @@ void die(const char *str, struct pt_regs *fp, long err)
|
|||
pr_warn("Oops: %s, sig: %ld\n", str, err);
|
||||
show_regs(fp);
|
||||
spin_unlock_irq(&die_lock);
|
||||
/* do_exit() should take care of panic'ing from an interrupt
|
||||
/* make_task_dead() should take care of panic'ing from an interrupt
|
||||
* context so we don't handle it here
|
||||
*/
|
||||
do_exit(err);
|
||||
make_task_dead(err);
|
||||
}
|
||||
|
||||
/* for user application debugging */
|
||||
|
|
|
@ -422,7 +422,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
|
|||
if (regs && kexec_should_crash(current))
|
||||
crash_kexec(regs);
|
||||
|
||||
do_exit(sig);
|
||||
make_task_dead(sig);
|
||||
}
|
||||
|
||||
extern struct exception_table_entry __start___dbe_table[];
|
||||
|
|
|
@ -223,7 +223,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
|
|||
}
|
||||
} else if (fpcsr & FPCSR_mskRIT) {
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGILL);
|
||||
make_task_dead(SIGILL);
|
||||
si_signo = SIGILL;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ void __noreturn die(const char *str, struct pt_regs *regs, int err)
|
|||
|
||||
bust_spinlocks(0);
|
||||
spin_unlock_irq(&die_lock);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(die);
|
||||
|
@ -240,7 +240,7 @@ void unhandled_interruption(struct pt_regs *regs)
|
|||
pr_emerg("unhandled_interruption\n");
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
force_sig(SIGKILL);
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ void unhandled_exceptions(unsigned long entry, unsigned long addr,
|
|||
addr, type);
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
force_sig(SIGKILL);
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ void do_revinsn(struct pt_regs *regs)
|
|||
pr_emerg("Reserved Instruction\n");
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGILL);
|
||||
make_task_dead(SIGILL);
|
||||
force_sig(SIGILL);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ void die(const char *str, struct pt_regs *regs, long err)
|
|||
show_regs(regs);
|
||||
spin_unlock_irq(&die_lock);
|
||||
/*
|
||||
* do_exit() should take care of panic'ing from an interrupt
|
||||
* make_task_dead() should take care of panic'ing from an interrupt
|
||||
* context so we don't handle it here
|
||||
*/
|
||||
do_exit(err);
|
||||
make_task_dead(err);
|
||||
}
|
||||
|
||||
void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
|
||||
|
|
|
@ -212,7 +212,7 @@ void __noreturn die(const char *str, struct pt_regs *regs, long err)
|
|||
__asm__ __volatile__("l.nop 1");
|
||||
do {} while (1);
|
||||
#endif
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
/* This is normally the 'Oops' routine */
|
||||
|
|
|
@ -269,7 +269,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
|
|||
panic("Fatal exception");
|
||||
|
||||
oops_exit();
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
/* gdb uses break 4,8 */
|
||||
|
|
|
@ -245,7 +245,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs,
|
|||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
do_exit(signr);
|
||||
make_task_dead(signr);
|
||||
}
|
||||
NOKPROBE_SYMBOL(oops_end);
|
||||
|
||||
|
@ -792,9 +792,9 @@ int machine_check_generic(struct pt_regs *regs)
|
|||
void die_mce(const char *str, struct pt_regs *regs, long err)
|
||||
{
|
||||
/*
|
||||
* The machine check wants to kill the interrupted context, but
|
||||
* do_exit() checks for in_interrupt() and panics in that case, so
|
||||
* exit the irq/nmi before calling die.
|
||||
* The machine check wants to kill the interrupted context,
|
||||
* but make_task_dead() checks for in_interrupt() and panics
|
||||
* in that case, so exit the irq/nmi before calling die.
|
||||
*/
|
||||
if (in_nmi())
|
||||
nmi_exit();
|
||||
|
|
|
@ -54,7 +54,7 @@ void die(struct pt_regs *regs, const char *str)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
if (ret != NOTIFY_STOP)
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
|
||||
|
|
|
@ -31,7 +31,7 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
|
|||
|
||||
bust_spinlocks(0);
|
||||
die(regs, "Oops");
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
static inline void no_context(struct pt_regs *regs, unsigned long addr)
|
||||
|
|
|
@ -224,5 +224,5 @@ void __noreturn die(struct pt_regs *regs, const char *str)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception: panic_on_oops");
|
||||
oops_exit();
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ void __s390_handle_mcck(void)
|
|||
"malfunction (code 0x%016lx).\n", mcck.mcck_code);
|
||||
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
|
||||
current->comm, current->pid);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void __noreturn die(const char *str, struct pt_regs *regs, long err)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
void die_if_kernel(const char *str, struct pt_regs *regs, long err)
|
||||
|
|
|
@ -86,9 +86,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
|
|||
}
|
||||
printk("Instruction DUMP:");
|
||||
instruction_dump ((unsigned long *) regs->pc);
|
||||
if(regs->psr & PSR_PS)
|
||||
do_exit(SIGKILL);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead((regs->psr & PSR_PS) ? SIGKILL : SIGSEGV);
|
||||
}
|
||||
|
||||
void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
|
||||
|
|
|
@ -2559,9 +2559,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
|
|||
}
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
if (regs->tstate & TSTATE_PRIV)
|
||||
do_exit(SIGKILL);
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead((regs->tstate & TSTATE_PRIV)? SIGKILL : SIGSEGV);
|
||||
}
|
||||
EXPORT_SYMBOL(die_if_kernel);
|
||||
|
||||
|
|
|
@ -1248,14 +1248,14 @@ SYM_CODE_START(asm_exc_nmi)
|
|||
SYM_CODE_END(asm_exc_nmi)
|
||||
|
||||
.pushsection .text, "ax"
|
||||
SYM_CODE_START(rewind_stack_do_exit)
|
||||
SYM_CODE_START(rewind_stack_and_make_dead)
|
||||
/* Prevent any naive code from trying to unwind to our caller. */
|
||||
xorl %ebp, %ebp
|
||||
|
||||
movl PER_CPU_VAR(cpu_current_top_of_stack), %esi
|
||||
leal -TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp
|
||||
|
||||
call do_exit
|
||||
call make_task_dead
|
||||
1: jmp 1b
|
||||
SYM_CODE_END(rewind_stack_do_exit)
|
||||
SYM_CODE_END(rewind_stack_and_make_dead)
|
||||
.popsection
|
||||
|
|
|
@ -1429,7 +1429,7 @@ SYM_CODE_END(ignore_sysret)
|
|||
#endif
|
||||
|
||||
.pushsection .text, "ax"
|
||||
SYM_CODE_START(rewind_stack_do_exit)
|
||||
SYM_CODE_START(rewind_stack_and_make_dead)
|
||||
UNWIND_HINT_FUNC
|
||||
/* Prevent any naive code from trying to unwind to our caller. */
|
||||
xorl %ebp, %ebp
|
||||
|
@ -1438,6 +1438,6 @@ SYM_CODE_START(rewind_stack_do_exit)
|
|||
leaq -PTREGS_SIZE(%rax), %rsp
|
||||
UNWIND_HINT_REGS
|
||||
|
||||
call do_exit
|
||||
SYM_CODE_END(rewind_stack_do_exit)
|
||||
call make_task_dead
|
||||
SYM_CODE_END(rewind_stack_and_make_dead)
|
||||
.popsection
|
||||
|
|
|
@ -351,7 +351,7 @@ unsigned long oops_begin(void)
|
|||
}
|
||||
NOKPROBE_SYMBOL(oops_begin);
|
||||
|
||||
void __noreturn rewind_stack_do_exit(int signr);
|
||||
void __noreturn rewind_stack_and_make_dead(int signr);
|
||||
|
||||
void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
||||
{
|
||||
|
@ -386,7 +386,7 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
|||
* reuse the task stack and that existing poisons are invalid.
|
||||
*/
|
||||
kasan_unpoison_task_stack(current);
|
||||
rewind_stack_do_exit(signr);
|
||||
rewind_stack_and_make_dead(signr);
|
||||
}
|
||||
NOKPROBE_SYMBOL(oops_end);
|
||||
|
||||
|
|
|
@ -552,5 +552,5 @@ void __noreturn die(const char * str, struct pt_regs * regs, long err)
|
|||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(err);
|
||||
make_task_dead(err);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ extern void sched_post_fork(struct task_struct *p,
|
|||
extern void sched_dead(struct task_struct *p);
|
||||
|
||||
void __noreturn do_task_dead(void);
|
||||
void __noreturn make_task_dead(int signr);
|
||||
|
||||
extern void proc_caches_init(void);
|
||||
|
||||
|
|
|
@ -884,6 +884,15 @@ void __noreturn do_exit(long code)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(do_exit);
|
||||
|
||||
void __noreturn make_task_dead(int signr)
|
||||
{
|
||||
/*
|
||||
* Take the task off the cpu after something catastrophic has
|
||||
* happened.
|
||||
*/
|
||||
do_exit(signr);
|
||||
}
|
||||
|
||||
void complete_and_exit(struct completion *comp, long code)
|
||||
{
|
||||
if (comp)
|
||||
|
|
|
@ -168,6 +168,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
|
|||
"panic",
|
||||
"do_exit",
|
||||
"do_task_dead",
|
||||
"make_task_dead",
|
||||
"__module_put_and_exit",
|
||||
"complete_and_exit",
|
||||
"__reiserfs_panic",
|
||||
|
@ -175,7 +176,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
|
|||
"fortify_panic",
|
||||
"usercopy_abort",
|
||||
"machine_real_restart",
|
||||
"rewind_stack_do_exit",
|
||||
"rewind_stack_and_make_dead"
|
||||
"kunit_try_catch_throw",
|
||||
"xen_start_kernel",
|
||||
"cpu_bringup_and_idle",
|
||||
|
|
Loading…
Reference in New Issue