exit: Add and use make_task_dead.

commit 0e25498f8cd43c1b5aa327f373dd094e9a006da7 upstream.

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>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Eric W. Biederman
2023-01-24 11:29:50 -08:00
committed by Greg Kroah-Hartman
parent 715a63588f
commit d9c740c765
38 changed files with 59 additions and 52 deletions

View File

@@ -192,7 +192,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
local_irq_enable(); local_irq_enable();
while (1); while (1);
} }
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
#ifndef CONFIG_MATHEMU #ifndef CONFIG_MATHEMU
@@ -577,7 +577,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n", printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
pc, va, opcode, reg); pc, va, opcode, reg);
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
got_exception: got_exception:
/* Ok, we caught the exception, but we don't want it. Is there /* Ok, we caught the exception, but we don't want it. Is there
@@ -632,7 +632,7 @@ got_exception:
local_irq_enable(); local_irq_enable();
while (1); while (1);
} }
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
/* /*

View File

@@ -204,7 +204,7 @@ retry:
printk(KERN_ALERT "Unable to handle kernel paging request at " printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address); "virtual address %016lx\n", address);
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16); 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 /* We ran out of memory, or some other thing happened to us that
made us unable to handle the page fault gracefully. */ made us unable to handle the page fault gracefully. */

View File

@@ -348,7 +348,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
if (signr) if (signr)
do_exit(signr); make_task_dead(signr);
} }
/* /*

View File

@@ -125,7 +125,7 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
show_pte(KERN_ALERT, mm, addr); show_pte(KERN_ALERT, mm, addr);
die("Oops", regs, fsr); die("Oops", regs, fsr);
bust_spinlocks(0); bust_spinlocks(0);
do_exit(SIGKILL); make_task_dead(SIGKILL);
} }
/* /*

View File

@@ -144,7 +144,7 @@ void die(const char *str, struct pt_regs *regs, int err)
raw_spin_unlock_irqrestore(&die_lock, flags); raw_spin_unlock_irqrestore(&die_lock, flags);
if (ret != NOTIFY_STOP) if (ret != NOTIFY_STOP)
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
static void arm64_show_signal(int signo, const char *str) static void arm64_show_signal(int signo, const char *str)

View File

@@ -293,7 +293,7 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
show_pte(addr); show_pte(addr);
die("Oops", regs, esr); die("Oops", regs, esr);
bust_spinlocks(0); bust_spinlocks(0);
do_exit(SIGKILL); make_task_dead(SIGKILL);
} }
static void __do_kernel_fault(unsigned long addr, unsigned int esr, static void __do_kernel_fault(unsigned long addr, unsigned int esr,

View File

@@ -294,7 +294,7 @@ bad_area:
__func__, opcode, rz, rx, imm, addr); __func__, opcode, rz, rx, imm, addr);
show_regs(regs); show_regs(regs);
bust_spinlocks(0); bust_spinlocks(0);
do_exit(SIGKILL); make_dead_task(SIGKILL);
} }
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr); force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);

View File

@@ -111,7 +111,7 @@ void die(struct pt_regs *regs, const char *str)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
if (ret != NOTIFY_STOP) 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) void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)

View File

@@ -110,7 +110,7 @@ void die(const char *str, struct pt_regs *fp, unsigned long err)
dump(fp); dump(fp);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
do_exit(SIGSEGV); make_dead_task(SIGSEGV);
} }
static int kstack_depth_to_print = 24; static int kstack_depth_to_print = 24;

View File

@@ -51,7 +51,7 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
printk(" at virtual address %08lx\n", address); printk(" at virtual address %08lx\n", address);
if (!user_mode(regs)) if (!user_mode(regs))
die("Oops", regs, error_code); die("Oops", regs, error_code);
do_exit(SIGKILL); make_dead_task(SIGKILL);
return 1; return 1;
} }

View File

@@ -218,7 +218,7 @@ int die(const char *str, struct pt_regs *regs, long err)
panic("Fatal exception"); panic("Fatal exception");
oops_exit(); oops_exit();
do_exit(err); make_dead_task(err);
return 0; return 0;
} }

View File

@@ -176,7 +176,7 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
spin_unlock(&mca_bh_lock); spin_unlock(&mca_bh_lock);
/* This process is about to be killed itself */ /* This process is about to be killed itself */
do_exit(SIGKILL); make_task_dead(SIGKILL);
} }
/** /**

View File

@@ -85,7 +85,7 @@ die (const char *str, struct pt_regs *regs, long err)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
return 0; return 0;
} }

View File

@@ -274,7 +274,7 @@ retry:
regs = NULL; regs = NULL;
bust_spinlocks(0); bust_spinlocks(0);
if (regs) if (regs)
do_exit(SIGKILL); make_task_dead(SIGKILL);
return; return;
out_of_memory: out_of_memory:

View File

@@ -1136,7 +1136,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
pr_crit("%s: %08x\n", str, nr); pr_crit("%s: %08x\n", str, nr);
show_registers(fp); show_registers(fp);
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
asmlinkage void set_esp0(unsigned long ssp) asmlinkage void set_esp0(unsigned long ssp)

View File

@@ -48,7 +48,7 @@ int send_fault_sig(struct pt_regs *regs)
pr_alert("Unable to handle kernel access"); pr_alert("Unable to handle kernel access");
pr_cont(" at virtual address %p\n", addr); pr_cont(" at virtual address %p\n", addr);
die_if_kernel("Oops", regs, 0 /*error_code*/); die_if_kernel("Oops", regs, 0 /*error_code*/);
do_exit(SIGKILL); make_task_dead(SIGKILL);
} }
return 1; return 1;

View File

@@ -44,10 +44,10 @@ void die(const char *str, struct pt_regs *fp, long err)
pr_warn("Oops: %s, sig: %ld\n", str, err); pr_warn("Oops: %s, sig: %ld\n", str, err);
show_regs(fp); show_regs(fp);
spin_unlock_irq(&die_lock); 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 * context so we don't handle it here
*/ */
do_exit(err); make_task_dead(err);
} }
/* for user application debugging */ /* for user application debugging */

View File

@@ -413,7 +413,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
if (regs && kexec_should_crash(current)) if (regs && kexec_should_crash(current))
crash_kexec(regs); crash_kexec(regs);
do_exit(sig); make_task_dead(sig);
} }
extern struct exception_table_entry __start___dbe_table[]; extern struct exception_table_entry __start___dbe_table[];

View File

@@ -223,7 +223,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
} }
} else if (fpcsr & FPCSR_mskRIT) { } else if (fpcsr & FPCSR_mskRIT) {
if (!user_mode(regs)) if (!user_mode(regs))
do_exit(SIGILL); make_task_dead(SIGILL);
si_signo = SIGILL; si_signo = SIGILL;
} }

View File

@@ -185,7 +185,7 @@ void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(0); bust_spinlocks(0);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
EXPORT_SYMBOL(die); EXPORT_SYMBOL(die);
@@ -289,7 +289,7 @@ void unhandled_interruption(struct pt_regs *regs)
pr_emerg("unhandled_interruption\n"); pr_emerg("unhandled_interruption\n");
show_regs(regs); show_regs(regs);
if (!user_mode(regs)) if (!user_mode(regs))
do_exit(SIGKILL); make_task_dead(SIGKILL);
force_sig(SIGKILL); force_sig(SIGKILL);
} }
@@ -300,7 +300,7 @@ void unhandled_exceptions(unsigned long entry, unsigned long addr,
addr, type); addr, type);
show_regs(regs); show_regs(regs);
if (!user_mode(regs)) if (!user_mode(regs))
do_exit(SIGKILL); make_task_dead(SIGKILL);
force_sig(SIGKILL); force_sig(SIGKILL);
} }
@@ -327,7 +327,7 @@ void do_revinsn(struct pt_regs *regs)
pr_emerg("Reserved Instruction\n"); pr_emerg("Reserved Instruction\n");
show_regs(regs); show_regs(regs);
if (!user_mode(regs)) if (!user_mode(regs))
do_exit(SIGILL); make_task_dead(SIGILL);
force_sig(SIGILL); force_sig(SIGILL);
} }

View File

@@ -37,10 +37,10 @@ void die(const char *str, struct pt_regs *regs, long err)
show_regs(regs); show_regs(regs);
spin_unlock_irq(&die_lock); 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 * 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) void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)

View File

@@ -212,7 +212,7 @@ void die(const char *str, struct pt_regs *regs, long err)
__asm__ __volatile__("l.nop 1"); __asm__ __volatile__("l.nop 1");
do {} while (1); do {} while (1);
#endif #endif
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
/* This is normally the 'Oops' routine */ /* This is normally the 'Oops' routine */

View File

@@ -268,7 +268,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
panic("Fatal exception"); panic("Fatal exception");
oops_exit(); oops_exit();
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
/* gdb uses break 4,8 */ /* gdb uses break 4,8 */

View File

@@ -245,7 +245,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs,
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
do_exit(signr); make_task_dead(signr);
} }
NOKPROBE_SYMBOL(oops_end); NOKPROBE_SYMBOL(oops_end);

View File

@@ -57,7 +57,7 @@ void die(struct pt_regs *regs, const char *str)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
if (ret != NOTIFY_STOP) 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) void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)

View File

@@ -34,7 +34,7 @@ static inline void no_context(struct pt_regs *regs, unsigned long addr)
(addr < PAGE_SIZE) ? "NULL pointer dereference" : (addr < PAGE_SIZE) ? "NULL pointer dereference" :
"paging request", addr); "paging request", addr);
die(regs, "Oops"); 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) static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_fault_t fault)

View File

@@ -214,5 +214,5 @@ void die(struct pt_regs *regs, const char *str)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception: panic_on_oops"); panic("Fatal exception: panic_on_oops");
oops_exit(); oops_exit();
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }

View File

@@ -178,7 +178,7 @@ void s390_handle_mcck(void)
"malfunction (code 0x%016lx).\n", mcck.mcck_code); "malfunction (code 0x%016lx).\n", mcck.mcck_code);
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n", printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
current->comm, current->pid); current->comm, current->pid);
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
} }
EXPORT_SYMBOL_GPL(s390_handle_mcck); EXPORT_SYMBOL_GPL(s390_handle_mcck);

View File

@@ -57,7 +57,7 @@ void die(const char *str, struct pt_regs *regs, long err)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
do_exit(SIGSEGV); make_task_dead(SIGSEGV);
} }
void die_if_kernel(const char *str, struct pt_regs *regs, long err) void die_if_kernel(const char *str, struct pt_regs *regs, long err)

View File

@@ -86,9 +86,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
} }
printk("Instruction DUMP:"); printk("Instruction DUMP:");
instruction_dump ((unsigned long *) regs->pc); instruction_dump ((unsigned long *) regs->pc);
if(regs->psr & PSR_PS) make_task_dead((regs->psr & PSR_PS) ? SIGKILL : SIGSEGV);
do_exit(SIGKILL);
do_exit(SIGSEGV);
} }
void do_hw_interrupt(struct pt_regs *regs, unsigned long type) void do_hw_interrupt(struct pt_regs *regs, unsigned long type)

View File

@@ -2564,9 +2564,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
} }
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
if (regs->tstate & TSTATE_PRIV) make_task_dead((regs->tstate & TSTATE_PRIV)? SIGKILL : SIGSEGV);
do_exit(SIGKILL);
do_exit(SIGSEGV);
} }
EXPORT_SYMBOL(die_if_kernel); EXPORT_SYMBOL(die_if_kernel);

View File

@@ -1333,14 +1333,14 @@ SYM_CODE_START(asm_exc_nmi)
SYM_CODE_END(asm_exc_nmi) SYM_CODE_END(asm_exc_nmi)
.pushsection .text, "ax" .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. */ /* Prevent any naive code from trying to unwind to our caller. */
xorl %ebp, %ebp xorl %ebp, %ebp
movl PER_CPU_VAR(cpu_current_top_of_stack), %esi movl PER_CPU_VAR(cpu_current_top_of_stack), %esi
leal -TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp leal -TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp
call do_exit call make_task_dead
1: jmp 1b 1: jmp 1b
SYM_CODE_END(rewind_stack_do_exit) SYM_CODE_END(rewind_stack_and_make_dead)
.popsection .popsection

View File

@@ -1509,7 +1509,7 @@ SYM_CODE_END(ignore_sysret)
#endif #endif
.pushsection .text, "ax" .pushsection .text, "ax"
SYM_CODE_START(rewind_stack_do_exit) SYM_CODE_START(rewind_stack_and_make_dead)
UNWIND_HINT_FUNC UNWIND_HINT_FUNC
/* Prevent any naive code from trying to unwind to our caller. */ /* Prevent any naive code from trying to unwind to our caller. */
xorl %ebp, %ebp xorl %ebp, %ebp
@@ -1518,6 +1518,6 @@ SYM_CODE_START(rewind_stack_do_exit)
leaq -PTREGS_SIZE(%rax), %rsp leaq -PTREGS_SIZE(%rax), %rsp
UNWIND_HINT_REGS UNWIND_HINT_REGS
call do_exit call make_task_dead
SYM_CODE_END(rewind_stack_do_exit) SYM_CODE_END(rewind_stack_and_make_dead)
.popsection .popsection

View File

@@ -351,7 +351,7 @@ unsigned long oops_begin(void)
} }
NOKPROBE_SYMBOL(oops_begin); 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) 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. * reuse the task stack and that existing poisons are invalid.
*/ */
kasan_unpoison_task_stack(current); kasan_unpoison_task_stack(current);
rewind_stack_do_exit(signr); rewind_stack_and_make_dead(signr);
} }
NOKPROBE_SYMBOL(oops_end); NOKPROBE_SYMBOL(oops_end);

View File

@@ -545,5 +545,5 @@ void die(const char * str, struct pt_regs * regs, long err)
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
do_exit(err); make_task_dead(err);
} }

View File

@@ -61,6 +61,7 @@ extern void sched_post_fork(struct task_struct *p,
extern void sched_dead(struct task_struct *p); extern void sched_dead(struct task_struct *p);
void __noreturn do_task_dead(void); void __noreturn do_task_dead(void);
void __noreturn make_task_dead(int signr);
extern void proc_caches_init(void); extern void proc_caches_init(void);

View File

@@ -863,6 +863,15 @@ void __noreturn do_exit(long code)
} }
EXPORT_SYMBOL_GPL(do_exit); 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) void complete_and_exit(struct completion *comp, long code)
{ {
if (comp) if (comp)

View File

@@ -168,6 +168,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
"panic", "panic",
"do_exit", "do_exit",
"do_task_dead", "do_task_dead",
"make_task_dead",
"__module_put_and_exit", "__module_put_and_exit",
"complete_and_exit", "complete_and_exit",
"__reiserfs_panic", "__reiserfs_panic",
@@ -175,7 +176,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
"fortify_panic", "fortify_panic",
"usercopy_abort", "usercopy_abort",
"machine_real_restart", "machine_real_restart",
"rewind_stack_do_exit", "rewind_stack_and_make_dead"
"kunit_try_catch_throw", "kunit_try_catch_throw",
"xen_start_kernel", "xen_start_kernel",
"cpu_bringup_and_idle", "cpu_bringup_and_idle",