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:
parent
2f87e25512
commit
9a18c9c833
@ -192,7 +192,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
|
||||
@ -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",
|
||||
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
|
||||
@ -632,7 +632,7 @@ got_exception:
|
||||
local_irq_enable();
|
||||
while (1);
|
||||
}
|
||||
do_exit(SIGSEGV);
|
||||
make_task_dead(SIGSEGV);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -206,7 +206,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. */
|
||||
|
@ -341,7 +341,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -124,7 +124,7 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
|
||||
show_pte(KERN_ALERT, mm, addr);
|
||||
die("Oops", regs, fsr);
|
||||
bust_spinlocks(0);
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -202,7 +202,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)
|
||||
|
@ -296,7 +296,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);
|
||||
}
|
||||
|
||||
static void __do_kernel_fault(unsigned long addr, unsigned int esr,
|
||||
|
@ -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);
|
||||
|
@ -85,7 +85,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, int nr)
|
||||
pr_err("%s: %08x\n", str, nr);
|
||||
show_regs(regs);
|
||||
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
|
||||
do_exit(SIGSEGV);
|
||||
make_dead_task(SIGSEGV);
|
||||
}
|
||||
|
||||
void buserr(struct pt_regs *regs)
|
||||
|
@ -110,7 +110,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;
|
||||
|
@ -52,7 +52,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;
|
||||
}
|
||||
|
@ -221,7 +221,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;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kallsyms.h>
|
||||
@ -176,7 +177,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;
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ retry:
|
||||
regs = NULL;
|
||||
bust_spinlocks(0);
|
||||
if (regs)
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
return;
|
||||
|
||||
out_of_memory:
|
||||
|
@ -1139,7 +1139,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 */
|
||||
|
@ -415,7 +415,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;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ void 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);
|
||||
@ -288,7 +288,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);
|
||||
}
|
||||
|
||||
@ -299,7 +299,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);
|
||||
}
|
||||
|
||||
@ -326,7 +326,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)
|
||||
|
@ -218,7 +218,7 @@ void 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 */
|
||||
|
@ -268,7 +268,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 */
|
||||
|
@ -246,7 +246,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);
|
||||
|
||||
|
@ -57,7 +57,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)
|
||||
|
@ -189,7 +189,7 @@ no_context:
|
||||
(addr < PAGE_SIZE) ? "NULL pointer dereference" :
|
||||
"paging request", addr);
|
||||
die(regs, "Oops");
|
||||
do_exit(SIGKILL);
|
||||
make_task_dead(SIGKILL);
|
||||
|
||||
/*
|
||||
* We ran out of memory, call the OOM killer, and return the userspace
|
||||
|
@ -210,5 +210,5 @@ void 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);
|
||||
}
|
||||
|
@ -179,7 +179,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);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(s390_handle_mcck);
|
||||
|
@ -57,7 +57,7 @@ void 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)
|
||||
|
@ -2564,9 +2564,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);
|
||||
|
||||
|
@ -1659,13 +1659,13 @@ ENTRY(async_page_fault)
|
||||
END(async_page_fault)
|
||||
#endif
|
||||
|
||||
ENTRY(rewind_stack_do_exit)
|
||||
ENTRY(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
|
||||
END(rewind_stack_do_exit)
|
||||
END(rewind_stack_and_make_dead)
|
||||
|
@ -1757,7 +1757,7 @@ ENTRY(ignore_sysret)
|
||||
END(ignore_sysret)
|
||||
#endif
|
||||
|
||||
ENTRY(rewind_stack_do_exit)
|
||||
ENTRY(rewind_stack_and_make_dead)
|
||||
UNWIND_HINT_FUNC
|
||||
/* Prevent any naive code from trying to unwind to our caller. */
|
||||
xorl %ebp, %ebp
|
||||
@ -1766,5 +1766,5 @@ ENTRY(rewind_stack_do_exit)
|
||||
leaq -PTREGS_SIZE(%rax), %rsp
|
||||
UNWIND_HINT_REGS
|
||||
|
||||
call do_exit
|
||||
END(rewind_stack_do_exit)
|
||||
call make_task_dead
|
||||
END(rewind_stack_and_make_dead)
|
||||
|
@ -326,7 +326,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)
|
||||
{
|
||||
@ -361,7 +361,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);
|
||||
|
||||
|
@ -543,5 +543,5 @@ void die(const char * str, struct pt_regs * regs, long err)
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(err);
|
||||
make_task_dead(err);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ extern int sched_fork(unsigned long clone_flags, 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);
|
||||
|
||||
|
@ -864,6 +864,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)
|
||||
|
@ -136,6 +136,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",
|
||||
@ -143,7 +144,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"
|
||||
"cpu_bringup_and_idle",
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user