Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge SA_IMMUTABLE-fixes-for-v5.16-rc2

I completed the first batch of signal changes for v5.17 against
v5.16-rc1 before the SA_IMMUTABLE fixes where completed. Which leaves
me with two lines of development that I want on my signal development
branch both rooted at v5.16-rc1. Especially as I am hoping
to reach the point of being able to remove SA_IMMUTABLE.

Linus merged my SA_IMUTABLE fixes as:
7af959b5d5c8 ("Merge branch 'SA_IMMUTABLE-fixes-for-v5.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace")

To avoid rebasing the development changes that are currently complete I am
merging the work I sent upstream to Linus to make my life simpler.

The SA_IMMUTABLE changes as they are described in Linus's merge commit.

Pull exit-vs-signal handling fixes from Eric Biederman:
"This is a small set of changes where debuggers were no longer able to
intercept synchronous SIGTRAP and SIGSEGV, introduced by the exit
cleanups.

This is essentially the change you suggested with all of i's dotted
and the t's crossed so that ptrace can intercept all of the cases it
has been able to intercept the past, and all of the cases that made it
to exit without giving ptrace a chance still don't give ptrace a
chance"

* 'SA_IMMUTABLE-fixes-for-v5.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
signal: Replace force_fatal_sig with force_exit_sig when in doubt
signal: Don't always set SA_IMMUTABLE for forced signals

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+42 -19
+1 -1
arch/m68k/kernel/traps.c
··· 1145 1145 */ 1146 1146 asmlinkage void fpsp040_die(void) 1147 1147 { 1148 - force_fatal_sig(SIGSEGV); 1148 + force_exit_sig(SIGSEGV); 1149 1149 } 1150 1150 1151 1151 #ifdef CONFIG_M68KFPU_EMU
+1 -1
arch/powerpc/kernel/signal_32.c
··· 1063 1063 * We kill the task with a SIGSEGV in this situation. 1064 1064 */ 1065 1065 if (do_setcontext(new_ctx, regs, 0)) { 1066 - force_fatal_sig(SIGSEGV); 1066 + force_exit_sig(SIGSEGV); 1067 1067 return -EFAULT; 1068 1068 } 1069 1069
+2 -2
arch/powerpc/kernel/signal_64.c
··· 704 704 */ 705 705 706 706 if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) { 707 - force_fatal_sig(SIGSEGV); 707 + force_exit_sig(SIGSEGV); 708 708 return -EFAULT; 709 709 } 710 710 set_current_blocked(&set); ··· 713 713 return -EFAULT; 714 714 if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) { 715 715 user_read_access_end(); 716 - force_fatal_sig(SIGSEGV); 716 + force_exit_sig(SIGSEGV); 717 717 return -EFAULT; 718 718 } 719 719 user_read_access_end();
+1 -1
arch/s390/kernel/traps.c
··· 84 84 { 85 85 if (user_mode(regs)) { 86 86 report_user_fault(regs, SIGSEGV, 0); 87 - force_fatal_sig(SIGSEGV); 87 + force_exit_sig(SIGSEGV); 88 88 } else 89 89 die(regs, "Unknown program exception"); 90 90 }
+2 -2
arch/sparc/kernel/signal_32.c
··· 244 244 get_sigframe(ksig, regs, sigframe_size); 245 245 246 246 if (invalid_frame_pointer(sf, sigframe_size)) { 247 - force_fatal_sig(SIGILL); 247 + force_exit_sig(SIGILL); 248 248 return -EINVAL; 249 249 } 250 250 ··· 336 336 sf = (struct rt_signal_frame __user *) 337 337 get_sigframe(ksig, regs, sigframe_size); 338 338 if (invalid_frame_pointer(sf, sigframe_size)) { 339 - force_fatal_sig(SIGILL); 339 + force_exit_sig(SIGILL); 340 340 return -EINVAL; 341 341 } 342 342
+1 -1
arch/sparc/kernel/windows.c
··· 122 122 if ((sp & 7) || 123 123 copy_to_user((char __user *) sp, &tp->reg_window[window], 124 124 sizeof(struct reg_window32))) { 125 - force_fatal_sig(SIGILL); 125 + force_exit_sig(SIGILL); 126 126 return; 127 127 } 128 128 }
+1 -1
arch/x86/entry/vsyscall/vsyscall_64.c
··· 226 226 if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { 227 227 warn_bad_vsyscall(KERN_DEBUG, regs, 228 228 "seccomp tried to change syscall nr or ip"); 229 - force_fatal_sig(SIGSYS); 229 + force_exit_sig(SIGSYS); 230 230 return true; 231 231 } 232 232 regs->orig_ax = -1;
+1 -1
arch/x86/kernel/vm86_32.c
··· 160 160 user_access_end(); 161 161 Efault: 162 162 pr_alert("could not access userspace vm86 info\n"); 163 - force_fatal_sig(SIGSEGV); 163 + force_exit_sig(SIGSEGV); 164 164 goto exit_vm86; 165 165 } 166 166
+1
include/linux/sched/signal.h
··· 353 353 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); 354 354 extern void force_sig(int); 355 355 extern void force_fatal_sig(int); 356 + extern void force_exit_sig(int); 356 357 extern int send_sig(int, struct task_struct *, int); 357 358 extern int zap_other_threads(struct task_struct *p); 358 359 extern struct sigqueue *sigqueue_alloc(void);
+2 -2
kernel/entry/syscall_user_dispatch.c
··· 48 48 * the selector is loaded by userspace. 49 49 */ 50 50 if (unlikely(__get_user(state, sd->selector))) { 51 - force_fatal_sig(SIGSEGV); 51 + force_exit_sig(SIGSEGV); 52 52 return true; 53 53 } 54 54 ··· 56 56 return false; 57 57 58 58 if (state != SYSCALL_DISPATCH_FILTER_BLOCK) { 59 - force_fatal_sig(SIGSYS); 59 + force_exit_sig(SIGSYS); 60 60 return true; 61 61 } 62 62 }
+29 -7
kernel/signal.c
··· 1301 1301 return ret; 1302 1302 } 1303 1303 1304 + enum sig_handler { 1305 + HANDLER_CURRENT, /* If reachable use the current handler */ 1306 + HANDLER_SIG_DFL, /* Always use SIG_DFL handler semantics */ 1307 + HANDLER_EXIT, /* Only visible as the process exit code */ 1308 + }; 1309 + 1304 1310 /* 1305 1311 * Force a signal that the process can't ignore: if necessary 1306 1312 * we unblock the signal and change any SIG_IGN to SIG_DFL. ··· 1319 1313 * that is why we also clear SIGNAL_UNKILLABLE. 1320 1314 */ 1321 1315 static int 1322 - force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl) 1316 + force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, 1317 + enum sig_handler handler) 1323 1318 { 1324 1319 unsigned long int flags; 1325 1320 int ret, blocked, ignored; ··· 1331 1324 action = &t->sighand->action[sig-1]; 1332 1325 ignored = action->sa.sa_handler == SIG_IGN; 1333 1326 blocked = sigismember(&t->blocked, sig); 1334 - if (blocked || ignored || sigdfl) { 1327 + if (blocked || ignored || (handler != HANDLER_CURRENT)) { 1335 1328 action->sa.sa_handler = SIG_DFL; 1336 - action->sa.sa_flags |= SA_IMMUTABLE; 1329 + if (handler == HANDLER_EXIT) 1330 + action->sa.sa_flags |= SA_IMMUTABLE; 1337 1331 if (blocked) { 1338 1332 sigdelset(&t->blocked, sig); 1339 1333 recalc_sigpending_and_wake(t); ··· 1354 1346 1355 1347 int force_sig_info(struct kernel_siginfo *info) 1356 1348 { 1357 - return force_sig_info_to_task(info, current, false); 1349 + return force_sig_info_to_task(info, current, HANDLER_CURRENT); 1358 1350 } 1359 1351 1360 1352 /* ··· 1671 1663 info.si_code = SI_KERNEL; 1672 1664 info.si_pid = 0; 1673 1665 info.si_uid = 0; 1674 - force_sig_info_to_task(&info, current, true); 1666 + force_sig_info_to_task(&info, current, HANDLER_SIG_DFL); 1667 + } 1668 + 1669 + void force_exit_sig(int sig) 1670 + { 1671 + struct kernel_siginfo info; 1672 + 1673 + clear_siginfo(&info); 1674 + info.si_signo = sig; 1675 + info.si_errno = 0; 1676 + info.si_code = SI_KERNEL; 1677 + info.si_pid = 0; 1678 + info.si_uid = 0; 1679 + force_sig_info_to_task(&info, current, HANDLER_EXIT); 1675 1680 } 1676 1681 1677 1682 /* ··· 1717 1696 info.si_flags = flags; 1718 1697 info.si_isr = isr; 1719 1698 #endif 1720 - return force_sig_info_to_task(&info, t, false); 1699 + return force_sig_info_to_task(&info, t, HANDLER_CURRENT); 1721 1700 } 1722 1701 1723 1702 int force_sig_fault(int sig, int code, void __user *addr ··· 1837 1816 info.si_errno = reason; 1838 1817 info.si_arch = syscall_get_arch(current); 1839 1818 info.si_syscall = syscall; 1840 - return force_sig_info_to_task(&info, current, force_coredump); 1819 + return force_sig_info_to_task(&info, current, 1820 + force_coredump ? HANDLER_EXIT : HANDLER_CURRENT); 1841 1821 } 1842 1822 1843 1823 /* For the crazy architectures that include trap information in