Skip to content

Commit

Permalink
Merge branch 'exit-cleanups-for-v5.16' of git://git.kernel.org/pub/sc…
Browse files Browse the repository at this point in the history
…m/linux/kernel/git/ebiederm/user-namespace

Pull exit cleanups from Eric Biederman:
 "While looking at some issues related to the exit path in the kernel I
  found several instances where the code is not using the existing
  abstractions properly.

  This set of changes introduces force_fatal_sig a way of sending a
  signal and not allowing it to be caught, and corrects the misuse of
  the existing abstractions that I found.

  A lot of the misuse of the existing abstractions are silly things such
  as doing something after calling a no return function, rolling BUG by
  hand, doing more work than necessary to terminate a kernel thread, or
  calling do_exit(SIGKILL) instead of calling force_sig(SIGKILL).

  In the review a deficiency in force_fatal_sig and force_sig_seccomp
  where ptrace or sigaction could prevent the delivery of the signal was
  found. I have added a change that adds SA_IMMUTABLE to change that
  makes it impossible to interrupt the delivery of those signals, and
  allows backporting to fix force_sig_seccomp

  And Arnd found an issue where a function passed to kthread_run had the
  wrong prototype, and after my cleanup was failing to build."

* 'exit-cleanups-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (23 commits)
  soc: ti: fix wkup_m3_rproc_boot_thread return type
  signal: Add SA_IMMUTABLE to ensure forced siganls do not get changed
  signal: Replace force_sigsegv(SIGSEGV) with force_fatal_sig(SIGSEGV)
  exit/r8188eu: Replace the macro thread_exit with a simple return 0
  exit/rtl8712: Replace the macro thread_exit with a simple return 0
  exit/rtl8723bs: Replace the macro thread_exit with a simple return 0
  signal/x86: In emulate_vsyscall force a signal instead of calling do_exit
  signal/sparc32: In setup_rt_frame and setup_fram use force_fatal_sig
  signal/sparc32: Exit with a fatal signal when try_to_clear_window_buffer fails
  exit/syscall_user_dispatch: Send ordinary signals on failure
  signal: Implement force_fatal_sig
  exit/kthread: Have kernel threads return instead of calling do_exit
  signal/s390: Use force_sigsegv in default_trap_handler
  signal/vm86_32: Properly send SIGSEGV when the vm86 state cannot be saved.
  signal/vm86_32: Replace open coded BUG_ON with an actual BUG_ON
  signal/sparc: In setup_tsb_params convert open coded BUG into BUG
  signal/powerpc: On swapcontext failure force SIGSEGV
  signal/sh: Use force_sig(SIGKILL) instead of do_group_exit(SIGKILL)
  signal/mips: Update (_save|_restore)_fp_context to fail with -EFAULT
  signal/sparc32: Remove unreachable do_exit in do_sparc_fault
  ...
  • Loading branch information
torvalds committed Nov 11, 2021
2 parents a41b744 + f91140e commit 5147da9
Show file tree
Hide file tree
Showing 47 changed files with 97 additions and 96 deletions.
2 changes: 1 addition & 1 deletion arch/arc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hdr *x)
eflags = x->e_flags;
if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) {
pr_err("ABI mismatch - you need newer toolchain\n");
force_sigsegv(SIGSEGV);
force_fatal_sig(SIGSEGV);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/m68k/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long ssp)
*/
asmlinkage void fpsp040_die(void)
{
force_sigsegv(SIGSEGV);
force_fatal_sig(SIGSEGV);
}

#ifdef CONFIG_M68KFPU_EMU
Expand Down
4 changes: 2 additions & 2 deletions arch/mips/kernel/r2300_fpu.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#define EX2(a,b) \
9: a,##b; \
.section __ex_table,"a"; \
PTR 9b,bad_stack; \
PTR 9b+4,bad_stack; \
PTR 9b,fault; \
PTR 9b+4,fault; \
.previous

.set mips1
Expand Down
9 changes: 0 additions & 9 deletions arch/mips/kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,3 @@ SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
{
return -ENOSYS;
}

/*
* If we ever come here the user sp is bad. Zap the process right away.
* Due to the bad stack signaling wouldn't work.
*/
asmlinkage void bad_stack(void)
{
do_exit(SIGSEGV);
}
2 changes: 1 addition & 1 deletion arch/nds32/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ DEFINE_SPINLOCK(die_lock);
/*
* This function is protected against re-entrancy.
*/
void die(const char *str, struct pt_regs *regs, int err)
void __noreturn die(const char *str, struct pt_regs *regs, int err)
{
struct task_struct *tsk = current;
static int die_counter;
Expand Down
6 changes: 1 addition & 5 deletions arch/nds32/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include <asm/tlbflush.h>

extern void die(const char *str, struct pt_regs *regs, long err);
extern void __noreturn die(const char *str, struct pt_regs *regs, long err);

/*
* This is useful to dump out the page tables associated with
Expand Down Expand Up @@ -299,10 +299,6 @@ void do_page_fault(unsigned long entry, unsigned long addr,

show_pte(mm, addr);
die("Oops", regs, error_code);
bust_spinlocks(0);
do_exit(SIGKILL);

return;

/*
* We ran out of memory, or some other thing happened to us that made
Expand Down
2 changes: 1 addition & 1 deletion arch/openrisc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void nommu_dump_state(struct pt_regs *regs,
}

/* This is normally the 'Oops' routine */
void die(const char *str, struct pt_regs *regs, long err)
void __noreturn die(const char *str, struct pt_regs *regs, long err)
{

console_verbose();
Expand Down
4 changes: 1 addition & 3 deletions arch/openrisc/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ unsigned long pte_errors; /* updated by do_page_fault() */
*/
volatile pgd_t *current_pgd[NR_CPUS];

extern void die(char *, struct pt_regs *, long);
extern void __noreturn die(char *, struct pt_regs *, long);

/*
* This routine handles page faults. It determines the address,
Expand Down Expand Up @@ -248,8 +248,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,

die("Oops", regs, write_acc);

do_exit(SIGKILL);

/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
Expand Down
6 changes: 4 additions & 2 deletions arch/powerpc/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
* or if another thread unmaps the region containing the context.
* We kill the task with a SIGSEGV in this situation.
*/
if (do_setcontext(new_ctx, regs, 0))
do_exit(SIGSEGV);
if (do_setcontext(new_ctx, regs, 0)) {
force_fatal_sig(SIGSEGV);
return -EFAULT;
}

set_thread_flag(TIF_RESTOREALL);
return 0;
Expand Down
9 changes: 6 additions & 3 deletions arch/powerpc/kernel/signal_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
* We kill the task with a SIGSEGV in this situation.
*/

if (__get_user_sigset(&set, &new_ctx->uc_sigmask))
do_exit(SIGSEGV);
if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) {
force_fatal_sig(SIGSEGV);
return -EFAULT;
}
set_current_blocked(&set);

if (!user_read_access_begin(new_ctx, ctx_size))
return -EFAULT;
if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) {
user_read_access_end();
do_exit(SIGSEGV);
force_fatal_sig(SIGSEGV);
return -EFAULT;
}
user_read_access_end();

Expand Down
2 changes: 1 addition & 1 deletion arch/s390/include/asm/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ enum die_val {
DIE_NMI_IPI,
};

extern void die(struct pt_regs *, const char *);
extern void __noreturn die(struct pt_regs *, const char *);

#endif
2 changes: 1 addition & 1 deletion arch/s390/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ void show_regs(struct pt_regs *regs)

static DEFINE_SPINLOCK(die_lock);

void die(struct pt_regs *regs, const char *str)
void __noreturn die(struct pt_regs *regs, const char *str)
{
static int die_counter;

Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs)
{
if (user_mode(regs)) {
report_user_fault(regs, SIGSEGV, 0);
do_exit(SIGSEGV);
force_fatal_sig(SIGSEGV);
} else
die(regs, "Unknown program exception");
}
Expand Down
2 changes: 0 additions & 2 deletions arch/s390/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ static noinline void do_no_context(struct pt_regs *regs)
" in virtual user address space\n");
dump_fault_info(regs);
die(regs, "Oops");
do_exit(SIGKILL);
}

static noinline void do_low_address(struct pt_regs *regs)
Expand All @@ -270,7 +269,6 @@ static noinline void do_low_address(struct pt_regs *regs)
if (regs->psw.mask & PSW_MASK_PSTATE) {
/* Low-address protection hit in user mode 'cannot happen'. */
die (regs, "Low-address protection");
do_exit(SIGKILL);
}

do_no_context(regs);
Expand Down
10 changes: 6 additions & 4 deletions arch/sh/kernel/cpu/fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,20 @@ void fpu_state_restore(struct pt_regs *regs)
}

if (!tsk_used_math(tsk)) {
local_irq_enable();
int ret;
/*
* does a slab alloc which can sleep
*/
if (init_fpu(tsk)) {
local_irq_enable();
ret = init_fpu(tsk);
local_irq_disable();
if (ret) {
/*
* ran out of memory!
*/
do_group_exit(SIGKILL);
force_sig(SIGKILL);
return;
}
local_irq_disable();
}

grab_fpu(regs);
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

static DEFINE_SPINLOCK(die_lock);

void die(const char *str, struct pt_regs *regs, long err)
void __noreturn die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter;

Expand Down
2 changes: 0 additions & 2 deletions arch/sh/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
show_fault_oops(regs, address);

die("Oops", regs, error_code);
bust_spinlocks(0);
do_exit(SIGKILL);
}

static void
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs,
get_sigframe(ksig, regs, sigframe_size);

if (invalid_frame_pointer(sf, sigframe_size)) {
do_exit(SIGILL);
force_fatal_sig(SIGILL);
return -EINVAL;
}

Expand Down Expand Up @@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
sf = (struct rt_signal_frame __user *)
get_sigframe(ksig, regs, sigframe_size);
if (invalid_frame_pointer(sf, sigframe_size)) {
do_exit(SIGILL);
force_fatal_sig(SIGILL);
return -EINVAL;
}

Expand Down
6 changes: 4 additions & 2 deletions arch/sparc/kernel/windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)

if ((sp & 7) ||
copy_to_user((char __user *) sp, &tp->reg_window[window],
sizeof(struct reg_window32)))
do_exit(SIGILL);
sizeof(struct reg_window32))) {
force_fatal_sig(SIGILL);
return;
}
}
tp->w_saved = 0;
}
1 change: 0 additions & 1 deletion arch/sparc/mm/fault_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
}

unhandled_fault(address, tsk, regs);
do_exit(SIGKILL);

/*
* We ran out of memory, or some other thing happened to us that made
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/mm/tsb.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
default:
printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n",
current->comm, current->pid, tsb_bytes);
do_exit(SIGSEGV);
BUG();
}
tte |= pte_sz_bits(page_sz);

Expand Down
2 changes: 1 addition & 1 deletion arch/um/kernel/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)

void fatal_sigsegv(void)
{
force_sigsegv(SIGSEGV);
force_fatal_sig(SIGSEGV);
do_signal(&current->thread.regs);
/*
* This is to tell gcc that we're not returning - do_signal
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/entry/vsyscall/vsyscall_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ bool emulate_vsyscall(unsigned long error_code,
if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
warn_bad_vsyscall(KERN_DEBUG, regs,
"seccomp tried to change syscall nr or ip");
do_exit(SIGSYS);
force_fatal_sig(SIGSYS);
return true;
}
regs->orig_ax = -1;
if (tmp)
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/kernel/doublefault_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ asmlinkage noinstr void __noreturn doublefault_shim(void)
* some way to reconstruct CR3. We could make a credible guess based
* on cpu_tlbstate, but that would be racy and would not account for
* PTI.
*
* Instead, don't bother. We can return through
* rewind_stack_do_exit() instead.
*/
panic("cannot return from double fault\n");
}
Expand Down
10 changes: 5 additions & 5 deletions arch/x86/kernel/vm86_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,8 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
*/
local_irq_enable();

if (!vm86 || !vm86->user_vm86) {
pr_alert("no user_vm86: BAD\n");
do_exit(SIGSEGV);
}
BUG_ON(!vm86 || !vm86->user_vm86);

set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | vm86->veflags_mask);
user = vm86->user_vm86;

Expand Down Expand Up @@ -142,6 +140,7 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)

user_access_end();

exit_vm86:
preempt_disable();
tsk->thread.sp0 = vm86->saved_sp0;
tsk->thread.sysenter_cs = __KERNEL_CS;
Expand All @@ -161,7 +160,8 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
user_access_end();
Efault:
pr_alert("could not access userspace vm86 info\n");
do_exit(SIGSEGV);
force_fatal_sig(SIGSEGV);
goto exit_vm86;
}

static int do_vm86_irq_handling(int subfunction, int irqnumber);
Expand Down
2 changes: 1 addition & 1 deletion arch/xtensa/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)

DEFINE_SPINLOCK(die_lock);

void die(const char * str, struct pt_regs * regs, long err)
void __noreturn die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
const char *pr = "";
Expand Down
3 changes: 1 addition & 2 deletions arch/xtensa/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void do_page_fault(struct pt_regs *regs)
void
bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
{
extern void die(const char*, struct pt_regs*, long);
extern void __noreturn die(const char*, struct pt_regs*, long);
const struct exception_table_entry *entry;

/* Are we prepared to handle this kernel fault? */
Expand All @@ -257,5 +257,4 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
"address %08lx\n pc = %08lx, ra = %08lx\n",
address, regs->pc, regs->areg[0]);
die("Oops", regs, sig);
do_exit(sig);
}
4 changes: 2 additions & 2 deletions drivers/firmware/stratix10-svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ static int svc_normal_to_secure_thread(void *data)
* physical address of memory block reserved by secure monitor software at
* secure world.
*
* svc_normal_to_secure_shm_thread() calls do_exit() directly since it is a
* svc_normal_to_secure_shm_thread() terminates directly since it is a
* standlone thread for which no one will call kthread_stop() or return when
* 'kthread_should_stop()' is true.
*/
Expand All @@ -544,7 +544,7 @@ static int svc_normal_to_secure_shm_thread(void *data)
}

complete(&sh_mem->sync_complete);
do_exit(0);
return 0;
}

/**
Expand Down
7 changes: 4 additions & 3 deletions drivers/soc/ti/wkup_m3_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,9 @@ void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc)
}
EXPORT_SYMBOL_GPL(wkup_m3_ipc_put);

static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
static int wkup_m3_rproc_boot_thread(void *arg)
{
struct wkup_m3_ipc *m3_ipc = arg;
struct device *dev = m3_ipc->dev;
int ret;

Expand All @@ -426,7 +427,7 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
else
m3_ipc_state = m3_ipc;

do_exit(0);
return 0;
}

static int wkup_m3_ipc_probe(struct platform_device *pdev)
Expand Down Expand Up @@ -500,7 +501,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
* can boot the wkup_m3 as soon as it's ready without holding
* up kernel boot
*/
task = kthread_run((void *)wkup_m3_rproc_boot_thread, m3_ipc,
task = kthread_run(wkup_m3_rproc_boot_thread, m3_ipc,
"wkup_m3_rproc_loader");

if (IS_ERR(task)) {
Expand Down
Loading

0 comments on commit 5147da9

Please sign in to comment.