Skip to content

Commit 5147da9

Browse files
committed
Merge branch 'exit-cleanups-for-v5.16' of git://git.kernel.org/pub/scm/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 ...
2 parents a41b744 + f91140e commit 5147da9

File tree

47 files changed

+97
-96
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+97
-96
lines changed

arch/arc/kernel/process.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hdr *x)
294294
eflags = x->e_flags;
295295
if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) {
296296
pr_err("ABI mismatch - you need newer toolchain\n");
297-
force_sigsegv(SIGSEGV);
297+
force_fatal_sig(SIGSEGV);
298298
return 0;
299299
}
300300

arch/m68k/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long ssp)
11451145
*/
11461146
asmlinkage void fpsp040_die(void)
11471147
{
1148-
force_sigsegv(SIGSEGV);
1148+
force_fatal_sig(SIGSEGV);
11491149
}
11501150

11511151
#ifdef CONFIG_M68KFPU_EMU

arch/mips/kernel/r2300_fpu.S

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
#define EX2(a,b) \
3030
9: a,##b; \
3131
.section __ex_table,"a"; \
32-
PTR 9b,bad_stack; \
33-
PTR 9b+4,bad_stack; \
32+
PTR 9b,fault; \
33+
PTR 9b+4,fault; \
3434
.previous
3535

3636
.set mips1

arch/mips/kernel/syscall.c

-9
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,3 @@ SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
240240
{
241241
return -ENOSYS;
242242
}
243-
244-
/*
245-
* If we ever come here the user sp is bad. Zap the process right away.
246-
* Due to the bad stack signaling wouldn't work.
247-
*/
248-
asmlinkage void bad_stack(void)
249-
{
250-
do_exit(SIGSEGV);
251-
}

arch/nds32/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ DEFINE_SPINLOCK(die_lock);
118118
/*
119119
* This function is protected against re-entrancy.
120120
*/
121-
void die(const char *str, struct pt_regs *regs, int err)
121+
void __noreturn die(const char *str, struct pt_regs *regs, int err)
122122
{
123123
struct task_struct *tsk = current;
124124
static int die_counter;

arch/nds32/mm/fault.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#include <asm/tlbflush.h>
1515

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

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

300300
show_pte(mm, addr);
301301
die("Oops", regs, error_code);
302-
bust_spinlocks(0);
303-
do_exit(SIGKILL);
304-
305-
return;
306302

307303
/*
308304
* We ran out of memory, or some other thing happened to us that made

arch/openrisc/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ void nommu_dump_state(struct pt_regs *regs,
197197
}
198198

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

203203
console_verbose();

arch/openrisc/mm/fault.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ unsigned long pte_errors; /* updated by do_page_fault() */
3232
*/
3333
volatile pgd_t *current_pgd[NR_CPUS];
3434

35-
extern void die(char *, struct pt_regs *, long);
35+
extern void __noreturn die(char *, struct pt_regs *, long);
3636

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

249249
die("Oops", regs, write_acc);
250250

251-
do_exit(SIGKILL);
252-
253251
/*
254252
* We ran out of memory, or some other thing happened to us that made
255253
* us unable to handle the page fault gracefully.

arch/powerpc/kernel/signal_32.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
10621062
* or if another thread unmaps the region containing the context.
10631063
* We kill the task with a SIGSEGV in this situation.
10641064
*/
1065-
if (do_setcontext(new_ctx, regs, 0))
1066-
do_exit(SIGSEGV);
1065+
if (do_setcontext(new_ctx, regs, 0)) {
1066+
force_fatal_sig(SIGSEGV);
1067+
return -EFAULT;
1068+
}
10671069

10681070
set_thread_flag(TIF_RESTOREALL);
10691071
return 0;

arch/powerpc/kernel/signal_64.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
703703
* We kill the task with a SIGSEGV in this situation.
704704
*/
705705

706-
if (__get_user_sigset(&set, &new_ctx->uc_sigmask))
707-
do_exit(SIGSEGV);
706+
if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) {
707+
force_fatal_sig(SIGSEGV);
708+
return -EFAULT;
709+
}
708710
set_current_blocked(&set);
709711

710712
if (!user_read_access_begin(new_ctx, ctx_size))
711713
return -EFAULT;
712714
if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) {
713715
user_read_access_end();
714-
do_exit(SIGSEGV);
716+
force_fatal_sig(SIGSEGV);
717+
return -EFAULT;
715718
}
716719
user_read_access_end();
717720

arch/s390/include/asm/kdebug.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ enum die_val {
2323
DIE_NMI_IPI,
2424
};
2525

26-
extern void die(struct pt_regs *, const char *);
26+
extern void __noreturn die(struct pt_regs *, const char *);
2727

2828
#endif

arch/s390/kernel/dumpstack.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void show_regs(struct pt_regs *regs)
192192

193193
static DEFINE_SPINLOCK(die_lock);
194194

195-
void die(struct pt_regs *regs, const char *str)
195+
void __noreturn die(struct pt_regs *regs, const char *str)
196196
{
197197
static int die_counter;
198198

arch/s390/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs)
8484
{
8585
if (user_mode(regs)) {
8686
report_user_fault(regs, SIGSEGV, 0);
87-
do_exit(SIGSEGV);
87+
force_fatal_sig(SIGSEGV);
8888
} else
8989
die(regs, "Unknown program exception");
9090
}

arch/s390/mm/fault.c

-2
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ static noinline void do_no_context(struct pt_regs *regs)
260260
" in virtual user address space\n");
261261
dump_fault_info(regs);
262262
die(regs, "Oops");
263-
do_exit(SIGKILL);
264263
}
265264

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

276274
do_no_context(regs);

arch/sh/kernel/cpu/fpu.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,20 @@ void fpu_state_restore(struct pt_regs *regs)
6262
}
6363

6464
if (!tsk_used_math(tsk)) {
65-
local_irq_enable();
65+
int ret;
6666
/*
6767
* does a slab alloc which can sleep
6868
*/
69-
if (init_fpu(tsk)) {
69+
local_irq_enable();
70+
ret = init_fpu(tsk);
71+
local_irq_disable();
72+
if (ret) {
7073
/*
7174
* ran out of memory!
7275
*/
73-
do_group_exit(SIGKILL);
76+
force_sig(SIGKILL);
7477
return;
7578
}
76-
local_irq_disable();
7779
}
7880

7981
grab_fpu(regs);

arch/sh/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
static DEFINE_SPINLOCK(die_lock);
2222

23-
void die(const char *str, struct pt_regs *regs, long err)
23+
void __noreturn die(const char *str, struct pt_regs *regs, long err)
2424
{
2525
static int die_counter;
2626

arch/sh/mm/fault.c

-2
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
238238
show_fault_oops(regs, address);
239239

240240
die("Oops", regs, error_code);
241-
bust_spinlocks(0);
242-
do_exit(SIGKILL);
243241
}
244242

245243
static void

arch/sparc/kernel/signal_32.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs,
244244
get_sigframe(ksig, regs, sigframe_size);
245245

246246
if (invalid_frame_pointer(sf, sigframe_size)) {
247-
do_exit(SIGILL);
247+
force_fatal_sig(SIGILL);
248248
return -EINVAL;
249249
}
250250

@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
336336
sf = (struct rt_signal_frame __user *)
337337
get_sigframe(ksig, regs, sigframe_size);
338338
if (invalid_frame_pointer(sf, sigframe_size)) {
339-
do_exit(SIGILL);
339+
force_fatal_sig(SIGILL);
340340
return -EINVAL;
341341
}
342342

arch/sparc/kernel/windows.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
121121

122122
if ((sp & 7) ||
123123
copy_to_user((char __user *) sp, &tp->reg_window[window],
124-
sizeof(struct reg_window32)))
125-
do_exit(SIGILL);
124+
sizeof(struct reg_window32))) {
125+
force_fatal_sig(SIGILL);
126+
return;
127+
}
126128
}
127129
tp->w_saved = 0;
128130
}

arch/sparc/mm/fault_32.c

-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
248248
}
249249

250250
unhandled_fault(address, tsk, regs);
251-
do_exit(SIGKILL);
252251

253252
/*
254253
* We ran out of memory, or some other thing happened to us that made

arch/sparc/mm/tsb.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
266266
default:
267267
printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n",
268268
current->comm, current->pid, tsb_bytes);
269-
do_exit(SIGSEGV);
269+
BUG();
270270
}
271271
tte |= pte_sz_bits(page_sz);
272272

arch/um/kernel/trap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
158158

159159
void fatal_sigsegv(void)
160160
{
161-
force_sigsegv(SIGSEGV);
161+
force_fatal_sig(SIGSEGV);
162162
do_signal(&current->thread.regs);
163163
/*
164164
* This is to tell gcc that we're not returning - do_signal

arch/x86/entry/vsyscall/vsyscall_64.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ bool emulate_vsyscall(unsigned long error_code,
226226
if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
227227
warn_bad_vsyscall(KERN_DEBUG, regs,
228228
"seccomp tried to change syscall nr or ip");
229-
do_exit(SIGSYS);
229+
force_fatal_sig(SIGSYS);
230+
return true;
230231
}
231232
regs->orig_ax = -1;
232233
if (tmp)

arch/x86/kernel/doublefault_32.c

-3
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,6 @@ asmlinkage noinstr void __noreturn doublefault_shim(void)
7777
* some way to reconstruct CR3. We could make a credible guess based
7878
* on cpu_tlbstate, but that would be racy and would not account for
7979
* PTI.
80-
*
81-
* Instead, don't bother. We can return through
82-
* rewind_stack_do_exit() instead.
8380
*/
8481
panic("cannot return from double fault\n");
8582
}

arch/x86/kernel/vm86_32.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,8 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
106106
*/
107107
local_irq_enable();
108108

109-
if (!vm86 || !vm86->user_vm86) {
110-
pr_alert("no user_vm86: BAD\n");
111-
do_exit(SIGSEGV);
112-
}
109+
BUG_ON(!vm86 || !vm86->user_vm86);
110+
113111
set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | vm86->veflags_mask);
114112
user = vm86->user_vm86;
115113

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

143141
user_access_end();
144142

143+
exit_vm86:
145144
preempt_disable();
146145
tsk->thread.sp0 = vm86->saved_sp0;
147146
tsk->thread.sysenter_cs = __KERNEL_CS;
@@ -161,7 +160,8 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
161160
user_access_end();
162161
Efault:
163162
pr_alert("could not access userspace vm86 info\n");
164-
do_exit(SIGSEGV);
163+
force_fatal_sig(SIGSEGV);
164+
goto exit_vm86;
165165
}
166166

167167
static int do_vm86_irq_handling(int subfunction, int irqnumber);

arch/xtensa/kernel/traps.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
527527

528528
DEFINE_SPINLOCK(die_lock);
529529

530-
void die(const char * str, struct pt_regs * regs, long err)
530+
void __noreturn die(const char * str, struct pt_regs * regs, long err)
531531
{
532532
static int die_counter;
533533
const char *pr = "";

arch/xtensa/mm/fault.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void do_page_fault(struct pt_regs *regs)
238238
void
239239
bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
240240
{
241-
extern void die(const char*, struct pt_regs*, long);
241+
extern void __noreturn die(const char*, struct pt_regs*, long);
242242
const struct exception_table_entry *entry;
243243

244244
/* Are we prepared to handle this kernel fault? */
@@ -257,5 +257,4 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
257257
"address %08lx\n pc = %08lx, ra = %08lx\n",
258258
address, regs->pc, regs->areg[0]);
259259
die("Oops", regs, sig);
260-
do_exit(sig);
261260
}

drivers/firmware/stratix10-svc.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ static int svc_normal_to_secure_thread(void *data)
520520
* physical address of memory block reserved by secure monitor software at
521521
* secure world.
522522
*
523-
* svc_normal_to_secure_shm_thread() calls do_exit() directly since it is a
523+
* svc_normal_to_secure_shm_thread() terminates directly since it is a
524524
* standlone thread for which no one will call kthread_stop() or return when
525525
* 'kthread_should_stop()' is true.
526526
*/
@@ -544,7 +544,7 @@ static int svc_normal_to_secure_shm_thread(void *data)
544544
}
545545

546546
complete(&sh_mem->sync_complete);
547-
do_exit(0);
547+
return 0;
548548
}
549549

550550
/**

drivers/soc/ti/wkup_m3_ipc.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,9 @@ void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc)
413413
}
414414
EXPORT_SYMBOL_GPL(wkup_m3_ipc_put);
415415

416-
static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
416+
static int wkup_m3_rproc_boot_thread(void *arg)
417417
{
418+
struct wkup_m3_ipc *m3_ipc = arg;
418419
struct device *dev = m3_ipc->dev;
419420
int ret;
420421

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

429-
do_exit(0);
430+
return 0;
430431
}
431432

432433
static int wkup_m3_ipc_probe(struct platform_device *pdev)
@@ -500,7 +501,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
500501
* can boot the wkup_m3 as soon as it's ready without holding
501502
* up kernel boot
502503
*/
503-
task = kthread_run((void *)wkup_m3_rproc_boot_thread, m3_ipc,
504+
task = kthread_run(wkup_m3_rproc_boot_thread, m3_ipc,
504505
"wkup_m3_rproc_loader");
505506

506507
if (IS_ERR(task)) {

0 commit comments

Comments
 (0)