From: Greg Kroah-Hartman Date: Tue, 23 Nov 2021 18:11:52 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v5.15.5~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=53beba058f0ef2e043d915c9861924dbf2968949;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch signal-don-t-always-set-sa_immutable-for-forced-signals.patch signal-implement-force_fatal_sig.patch signal-powerpc-on-swapcontext-failure-force-sigsegv.patch signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch signal-s390-use-force_sigsegv-in-default_trap_handler.patch signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch --- diff --git a/queue-5.15/exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch b/queue-5.15/exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch new file mode 100644 index 00000000000..5a6df9ee4b8 --- /dev/null +++ b/queue-5.15/exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch @@ -0,0 +1,82 @@ +From 941edc5bf174b67f94db19817cbeab0a93e0c32a Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:44:00 -0500 +Subject: exit/syscall_user_dispatch: Send ordinary signals on failure + +From: Eric W. Biederman + +commit 941edc5bf174b67f94db19817cbeab0a93e0c32a upstream. + +Use force_fatal_sig instead of calling do_exit directly. This ensures +the ordinary signal handling path gets invoked, core dumps as +appropriate get created, and for multi-threaded processes all of the +threads are terminated not just a single thread. + +When asked Gabriel Krisman Bertazi said [1]: +> ebiederm@xmission.com (Eric W. Biederman) asked: +> +> > Why does do_syscal_user_dispatch call do_exit(SIGSEGV) and +> > do_exit(SIGSYS) instead of force_sig(SIGSEGV) and force_sig(SIGSYS)? +> > +> > Looking at the code these cases are not expected to happen, so I would +> > be surprised if userspace depends on any particular behaviour on the +> > failure path so I think we can change this. +> +> Hi Eric, +> +> There is not really a good reason, and the use case that originated the +> feature doesn't rely on it. +> +> Unless I'm missing yet another problem and others correct me, I think +> it makes sense to change it as you described. +> +> > Is using do_exit in this way something you copied from seccomp? +> +> I'm not sure, its been a while, but I think it might be just that. The +> first prototype of SUD was implemented as a seccomp mode. + +If at some point it becomes interesting we could relax +"force_fatal_sig(SIGSEGV)" to instead say +"force_sig_fault(SIGSEGV, SEGV_MAPERR, sd->selector)". + +I avoid doing that in this patch to avoid making it possible +to catch currently uncatchable signals. + +Cc: Gabriel Krisman Bertazi +Cc: Thomas Gleixner +Cc: Peter Zijlstra +Cc: Andy Lutomirski +[1] https://lkml.kernel.org/r/87mtr6gdvi.fsf@collabora.com +Link: https://lkml.kernel.org/r/20211020174406.17889-14-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + kernel/entry/syscall_user_dispatch.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/kernel/entry/syscall_user_dispatch.c ++++ b/kernel/entry/syscall_user_dispatch.c +@@ -47,14 +47,18 @@ bool syscall_user_dispatch(struct pt_reg + * access_ok() is performed once, at prctl time, when + * the selector is loaded by userspace. + */ +- if (unlikely(__get_user(state, sd->selector))) +- do_exit(SIGSEGV); ++ if (unlikely(__get_user(state, sd->selector))) { ++ force_fatal_sig(SIGSEGV); ++ return true; ++ } + + if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW)) + return false; + +- if (state != SYSCALL_DISPATCH_FILTER_BLOCK) +- do_exit(SIGSYS); ++ if (state != SYSCALL_DISPATCH_FILTER_BLOCK) { ++ force_fatal_sig(SIGSYS); ++ return true; ++ } + } + + sd->on_dispatch = true; diff --git a/queue-5.15/series b/queue-5.15/series index 86e39e95b5b..68193af570a 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -253,3 +253,14 @@ drm-i915-dp-ensure-max-link-params-are-always-valid.patch drm-i915-fix-type1-dvi-dp-dual-mode-adapter-heuristic-for-modern-platforms.patch drm-amdgpu-fix-set-scaling-mode-full-full-aspect-center-not-works-on-vga-and-dvi-connectors.patch drm-amd-pm-avoid-duplicate-powergate-ungate-setting.patch +signal-implement-force_fatal_sig.patch +exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch +signal-powerpc-on-swapcontext-failure-force-sigsegv.patch +signal-s390-use-force_sigsegv-in-default_trap_handler.patch +signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch +signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch +signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch +signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch +signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch +signal-don-t-always-set-sa_immutable-for-forced-signals.patch +signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch diff --git a/queue-5.15/signal-don-t-always-set-sa_immutable-for-forced-signals.patch b/queue-5.15/signal-don-t-always-set-sa_immutable-for-forced-signals.patch new file mode 100644 index 00000000000..38e7fc4f652 --- /dev/null +++ b/queue-5.15/signal-don-t-always-set-sa_immutable-for-forced-signals.patch @@ -0,0 +1,114 @@ +From e349d945fac76bddc78ae1cb92a0145b427a87ce Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 18 Nov 2021 11:11:13 -0600 +Subject: signal: Don't always set SA_IMMUTABLE for forced signals + +From: Eric W. Biederman + +commit e349d945fac76bddc78ae1cb92a0145b427a87ce upstream. + +Recently to prevent issues with SECCOMP_RET_KILL and similar signals +being changed before they are delivered SA_IMMUTABLE was added. + +Unfortunately this broke debuggers[1][2] which reasonably expect to be +able to trap synchronous SIGTRAP and SIGSEGV even when the target +process is not configured to handle those signals. + +Update force_sig_to_task to support both the case when we can allow +the debugger to intercept and possibly ignore the signal and the case +when it is not safe to let userspace know about the signal until the +process has exited. + +Suggested-by: Linus Torvalds +Reported-by: Kyle Huey +Reported-by: kernel test robot +Cc: stable@vger.kernel.org +[1] https://lkml.kernel.org/r/CAP045AoMY4xf8aC_4QU_-j7obuEPYgTcnQQP3Yxk=2X90jtpjw@mail.gmail.com +[2] https://lkml.kernel.org/r/20211117150258.GB5403@xsang-OptiPlex-9020 +Fixes: 00b06da29cf9 ("signal: Add SA_IMMUTABLE to ensure forced siganls do not get changed") +Link: https://lkml.kernel.org/r/877dd5qfw5.fsf_-_@email.froward.int.ebiederm.org +Reviewed-by: Kees Cook +Tested-by: Kees Cook +Tested-by: Kyle Huey +Signed-off-by: "Eric W. Biederman" +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + kernel/signal.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1298,6 +1298,12 @@ int do_send_sig_info(int sig, struct ker + return ret; + } + ++enum sig_handler { ++ HANDLER_CURRENT, /* If reachable use the current handler */ ++ HANDLER_SIG_DFL, /* Always use SIG_DFL handler semantics */ ++ HANDLER_EXIT, /* Only visible as the process exit code */ ++}; ++ + /* + * Force a signal that the process can't ignore: if necessary + * we unblock the signal and change any SIG_IGN to SIG_DFL. +@@ -1310,7 +1316,8 @@ int do_send_sig_info(int sig, struct ker + * that is why we also clear SIGNAL_UNKILLABLE. + */ + static int +-force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl) ++force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, ++ enum sig_handler handler) + { + unsigned long int flags; + int ret, blocked, ignored; +@@ -1321,9 +1328,10 @@ force_sig_info_to_task(struct kernel_sig + action = &t->sighand->action[sig-1]; + ignored = action->sa.sa_handler == SIG_IGN; + blocked = sigismember(&t->blocked, sig); +- if (blocked || ignored || sigdfl) { ++ if (blocked || ignored || (handler != HANDLER_CURRENT)) { + action->sa.sa_handler = SIG_DFL; +- action->sa.sa_flags |= SA_IMMUTABLE; ++ if (handler == HANDLER_EXIT) ++ action->sa.sa_flags |= SA_IMMUTABLE; + if (blocked) { + sigdelset(&t->blocked, sig); + recalc_sigpending_and_wake(t); +@@ -1343,7 +1351,7 @@ force_sig_info_to_task(struct kernel_sig + + int force_sig_info(struct kernel_siginfo *info) + { +- return force_sig_info_to_task(info, current, false); ++ return force_sig_info_to_task(info, current, HANDLER_CURRENT); + } + + /* +@@ -1660,7 +1668,7 @@ void force_fatal_sig(int sig) + info.si_code = SI_KERNEL; + info.si_pid = 0; + info.si_uid = 0; +- force_sig_info_to_task(&info, current, true); ++ force_sig_info_to_task(&info, current, HANDLER_SIG_DFL); + } + + /* +@@ -1693,7 +1701,7 @@ int force_sig_fault_to_task(int sig, int + info.si_flags = flags; + info.si_isr = isr; + #endif +- return force_sig_info_to_task(&info, t, false); ++ return force_sig_info_to_task(&info, t, HANDLER_CURRENT); + } + + int force_sig_fault(int sig, int code, void __user *addr +@@ -1813,7 +1821,8 @@ int force_sig_seccomp(int syscall, int r + info.si_errno = reason; + info.si_arch = syscall_get_arch(current); + info.si_syscall = syscall; +- return force_sig_info_to_task(&info, current, force_coredump); ++ return force_sig_info_to_task(&info, current, ++ force_coredump ? HANDLER_EXIT : HANDLER_CURRENT); + } + + /* For the crazy architectures that include trap information in diff --git a/queue-5.15/signal-implement-force_fatal_sig.patch b/queue-5.15/signal-implement-force_fatal_sig.patch new file mode 100644 index 00000000000..0bdbfb55b2e --- /dev/null +++ b/queue-5.15/signal-implement-force_fatal_sig.patch @@ -0,0 +1,87 @@ +From 26d5badbccddcc063dc5174a2baffd13a23322aa Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:43:59 -0500 +Subject: signal: Implement force_fatal_sig + +From: Eric W. Biederman + +commit 26d5badbccddcc063dc5174a2baffd13a23322aa upstream. + +Add a simple helper force_fatal_sig that causes a signal to be +delivered to a process as if the signal handler was set to SIG_DFL. + +Reimplement force_sigsegv based upon this new helper. This fixes +force_sigsegv so that when it forces the default signal handler +to be used the code now forces the signal to be unblocked as well. + +Reusing the tested logic in force_sig_info_to_task that was built for +force_sig_seccomp this makes the implementation trivial. + +This is interesting both because it makes force_sigsegv simpler and +because there are a couple of buggy places in the kernel that call +do_exit(SIGILL) or do_exit(SIGSYS) because there is no straight +forward way today for those places to simply force the exit of a +process with the chosen signal. Creating force_fatal_sig allows +those places to be implemented with normal signal exits. + +Link: https://lkml.kernel.org/r/20211020174406.17889-13-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/sched/signal.h | 1 + + kernel/signal.c | 26 +++++++++++++++++--------- + 2 files changed, 18 insertions(+), 9 deletions(-) + +--- a/include/linux/sched/signal.h ++++ b/include/linux/sched/signal.h +@@ -338,6 +338,7 @@ extern int kill_pid(struct pid *pid, int + extern __must_check bool do_notify_parent(struct task_struct *, int); + extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); + extern void force_sig(int); ++extern void force_fatal_sig(int); + extern int send_sig(int, struct task_struct *, int); + extern int zap_other_threads(struct task_struct *p); + extern struct sigqueue *sigqueue_alloc(void); +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1650,6 +1650,19 @@ void force_sig(int sig) + } + EXPORT_SYMBOL(force_sig); + ++void force_fatal_sig(int sig) ++{ ++ struct kernel_siginfo info; ++ ++ clear_siginfo(&info); ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = SI_KERNEL; ++ info.si_pid = 0; ++ info.si_uid = 0; ++ force_sig_info_to_task(&info, current, true); ++} ++ + /* + * When things go south during signal handling, we + * will force a SIGSEGV. And if the signal that caused +@@ -1658,15 +1671,10 @@ EXPORT_SYMBOL(force_sig); + */ + void force_sigsegv(int sig) + { +- struct task_struct *p = current; +- +- if (sig == SIGSEGV) { +- unsigned long flags; +- spin_lock_irqsave(&p->sighand->siglock, flags); +- p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; +- spin_unlock_irqrestore(&p->sighand->siglock, flags); +- } +- force_sig(SIGSEGV); ++ if (sig == SIGSEGV) ++ force_fatal_sig(SIGSEGV); ++ else ++ force_sig(SIGSEGV); + } + + int force_sig_fault_to_task(int sig, int code, void __user *addr diff --git a/queue-5.15/signal-powerpc-on-swapcontext-failure-force-sigsegv.patch b/queue-5.15/signal-powerpc-on-swapcontext-failure-force-sigsegv.patch new file mode 100644 index 00000000000..da8d95c7087 --- /dev/null +++ b/queue-5.15/signal-powerpc-on-swapcontext-failure-force-sigsegv.patch @@ -0,0 +1,70 @@ +From 83a1f27ad773b1d8f0460d3a676114c7651918cc Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:43:53 -0500 +Subject: signal/powerpc: On swapcontext failure force SIGSEGV + +From: Eric W. Biederman + +commit 83a1f27ad773b1d8f0460d3a676114c7651918cc upstream. + +If the register state may be partial and corrupted instead of calling +do_exit, call force_sigsegv(SIGSEGV). Which properly kills the +process with SIGSEGV and does not let any more userspace code execute, +instead of just killing one thread of the process and potentially +confusing everything. + +Cc: Michael Ellerman +Cc: Benjamin Herrenschmidt +Cc: Paul Mackerras +Cc: linuxppc-dev@lists.ozlabs.org +History-tree: git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git +Fixes: 756f1ae8a44e ("PPC32: Rework signal code and add a swapcontext system call.") +Fixes: 04879b04bf50 ("[PATCH] ppc64: VMX (Altivec) support & signal32 rework, from Ben Herrenschmidt") +Link: https://lkml.kernel.org/r/20211020174406.17889-7-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/signal_32.c | 6 ++++-- + arch/powerpc/kernel/signal_64.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 5 deletions(-) + +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + * 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_sigsegv(SIGSEGV); ++ return -EFAULT; ++ } + + set_thread_flag(TIF_RESTOREALL); + return 0; +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + * 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_sigsegv(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_sigsegv(SIGSEGV); ++ return -EFAULT; + } + user_read_access_end(); + diff --git a/queue-5.15/signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch b/queue-5.15/signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch new file mode 100644 index 00000000000..cac12635bba --- /dev/null +++ b/queue-5.15/signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch @@ -0,0 +1,222 @@ +From fcb116bc43c8c37c052530ead79872f8b2615711 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 18 Nov 2021 14:23:21 -0600 +Subject: signal: Replace force_fatal_sig with force_exit_sig when in doubt + +From: Eric W. Biederman + +commit fcb116bc43c8c37c052530ead79872f8b2615711 upstream. + +Recently to prevent issues with SECCOMP_RET_KILL and similar signals +being changed before they are delivered SA_IMMUTABLE was added. + +Unfortunately this broke debuggers[1][2] which reasonably expect +to be able to trap synchronous SIGTRAP and SIGSEGV even when +the target process is not configured to handle those signals. + +Add force_exit_sig and use it instead of force_fatal_sig where +historically the code has directly called do_exit. This has the +implementation benefits of going through the signal exit path +(including generating core dumps) without the danger of allowing +userspace to ignore or change these signals. + +This avoids userspace regressions as older kernels exited with do_exit +which debuggers also can not intercept. + +In the future is should be possible to improve the quality of +implementation of the kernel by changing some of these force_exit_sig +calls to force_fatal_sig. That can be done where it matters on +a case-by-case basis with careful analysis. + +Reported-by: Kyle Huey +Reported-by: kernel test robot +[1] https://lkml.kernel.org/r/CAP045AoMY4xf8aC_4QU_-j7obuEPYgTcnQQP3Yxk=2X90jtpjw@mail.gmail.com +[2] https://lkml.kernel.org/r/20211117150258.GB5403@xsang-OptiPlex-9020 +Fixes: 00b06da29cf9 ("signal: Add SA_IMMUTABLE to ensure forced siganls do not get changed") +Fixes: a3616a3c0272 ("signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die") +Fixes: 83a1f27ad773 ("signal/powerpc: On swapcontext failure force SIGSEGV") +Fixes: 9bc508cf0791 ("signal/s390: Use force_sigsegv in default_trap_handler") +Fixes: 086ec444f866 ("signal/sparc32: In setup_rt_frame and setup_fram use force_fatal_sig") +Fixes: c317d306d550 ("signal/sparc32: Exit with a fatal signal when try_to_clear_window_buffer fails") +Fixes: 695dd0d634df ("signal/x86: In emulate_vsyscall force a signal instead of calling do_exit") +Fixes: 1fbd60df8a85 ("signal/vm86_32: Properly send SIGSEGV when the vm86 state cannot be saved.") +Fixes: 941edc5bf174 ("exit/syscall_user_dispatch: Send ordinary signals on failure") +Link: https://lkml.kernel.org/r/871r3dqfv8.fsf_-_@email.froward.int.ebiederm.org +Reviewed-by: Kees Cook +Tested-by: Kees Cook +Tested-by: Kyle Huey +Signed-off-by: "Eric W. Biederman" +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/m68k/kernel/traps.c | 2 +- + arch/powerpc/kernel/signal_32.c | 2 +- + arch/powerpc/kernel/signal_64.c | 4 ++-- + arch/s390/kernel/traps.c | 2 +- + arch/sparc/kernel/signal_32.c | 4 ++-- + arch/sparc/kernel/windows.c | 2 +- + arch/x86/entry/vsyscall/vsyscall_64.c | 2 +- + arch/x86/kernel/vm86_32.c | 2 +- + include/linux/sched/signal.h | 1 + + kernel/entry/syscall_user_dispatch.c | 4 ++-- + kernel/signal.c | 13 +++++++++++++ + 11 files changed, 26 insertions(+), 12 deletions(-) + +--- a/arch/m68k/kernel/traps.c ++++ b/arch/m68k/kernel/traps.c +@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long s + */ + asmlinkage void fpsp040_die(void) + { +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + } + + #ifdef CONFIG_M68KFPU_EMU +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -1063,7 +1063,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + * We kill the task with a SIGSEGV in this situation. + */ + if (do_setcontext(new_ctx, regs, 0)) { +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + return -EFAULT; + } + +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -704,7 +704,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + */ + + if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) { +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + return -EFAULT; + } + set_current_blocked(&set); +@@ -713,7 +713,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + return -EFAULT; + if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) { + user_read_access_end(); +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + return -EFAULT; + } + user_read_access_end(); +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -84,7 +84,7 @@ static void default_trap_handler(struct + { + if (user_mode(regs)) { + report_user_fault(regs, SIGSEGV, 0); +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + } else + die(regs, "Unknown program exception"); + } +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *k + get_sigframe(ksig, regs, sigframe_size); + + if (invalid_frame_pointer(sf, sigframe_size)) { +- force_fatal_sig(SIGILL); ++ force_exit_sig(SIGILL); + return -EINVAL; + } + +@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal + sf = (struct rt_signal_frame __user *) + get_sigframe(ksig, regs, sigframe_size); + if (invalid_frame_pointer(sf, sigframe_size)) { +- force_fatal_sig(SIGILL); ++ force_exit_sig(SIGILL); + return -EINVAL; + } + +--- a/arch/sparc/kernel/windows.c ++++ b/arch/sparc/kernel/windows.c +@@ -122,7 +122,7 @@ void try_to_clear_window_buffer(struct p + if ((sp & 7) || + copy_to_user((char __user *) sp, &tp->reg_window[window], + sizeof(struct reg_window32))) { +- force_fatal_sig(SIGILL); ++ force_exit_sig(SIGILL); + return; + } + } +--- a/arch/x86/entry/vsyscall/vsyscall_64.c ++++ b/arch/x86/entry/vsyscall/vsyscall_64.c +@@ -226,7 +226,7 @@ bool emulate_vsyscall(unsigned long erro + if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + warn_bad_vsyscall(KERN_DEBUG, regs, + "seccomp tried to change syscall nr or ip"); +- force_fatal_sig(SIGSYS); ++ force_exit_sig(SIGSYS); + return true; + } + regs->orig_ax = -1; +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -162,7 +162,7 @@ Efault_end: + user_access_end(); + Efault: + pr_alert("could not access userspace vm86 info\n"); +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + goto exit_vm86; + } + +--- a/include/linux/sched/signal.h ++++ b/include/linux/sched/signal.h +@@ -339,6 +339,7 @@ extern __must_check bool do_notify_paren + extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); + extern void force_sig(int); + extern void force_fatal_sig(int); ++extern void force_exit_sig(int); + extern int send_sig(int, struct task_struct *, int); + extern int zap_other_threads(struct task_struct *p); + extern struct sigqueue *sigqueue_alloc(void); +--- a/kernel/entry/syscall_user_dispatch.c ++++ b/kernel/entry/syscall_user_dispatch.c +@@ -48,7 +48,7 @@ bool syscall_user_dispatch(struct pt_reg + * the selector is loaded by userspace. + */ + if (unlikely(__get_user(state, sd->selector))) { +- force_fatal_sig(SIGSEGV); ++ force_exit_sig(SIGSEGV); + return true; + } + +@@ -56,7 +56,7 @@ bool syscall_user_dispatch(struct pt_reg + return false; + + if (state != SYSCALL_DISPATCH_FILTER_BLOCK) { +- force_fatal_sig(SIGSYS); ++ force_exit_sig(SIGSYS); + return true; + } + } +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1671,6 +1671,19 @@ void force_fatal_sig(int sig) + force_sig_info_to_task(&info, current, HANDLER_SIG_DFL); + } + ++void force_exit_sig(int sig) ++{ ++ struct kernel_siginfo info; ++ ++ clear_siginfo(&info); ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = SI_KERNEL; ++ info.si_pid = 0; ++ info.si_uid = 0; ++ force_sig_info_to_task(&info, current, HANDLER_EXIT); ++} ++ + /* + * When things go south during signal handling, we + * will force a SIGSEGV. And if the signal that caused diff --git a/queue-5.15/signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch b/queue-5.15/signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch new file mode 100644 index 00000000000..bf73d349832 --- /dev/null +++ b/queue-5.15/signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch @@ -0,0 +1,130 @@ +From e21294a7aaae32c5d7154b187113a04db5852e37 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Mon, 25 Oct 2021 10:50:57 -0500 +Subject: signal: Replace force_sigsegv(SIGSEGV) with force_fatal_sig(SIGSEGV) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric W. Biederman + +commit e21294a7aaae32c5d7154b187113a04db5852e37 upstream. + +Now that force_fatal_sig exists it is unnecessary and a bit confusing +to use force_sigsegv in cases where the simpler force_fatal_sig is +wanted. So change every instance we can to make the code clearer. + +Acked-by: Geert Uytterhoeven +Reviewed-by: Philippe Mathieu-Daudé +Link: https://lkml.kernel.org/r/877de7jrev.fsf@disp2133 +Signed-off-by: "Eric W. Biederman" +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/arc/kernel/process.c | 2 +- + arch/m68k/kernel/traps.c | 2 +- + arch/powerpc/kernel/signal_32.c | 2 +- + arch/powerpc/kernel/signal_64.c | 4 ++-- + arch/s390/kernel/traps.c | 2 +- + arch/um/kernel/trap.c | 2 +- + arch/x86/kernel/vm86_32.c | 2 +- + fs/exec.c | 2 +- + 8 files changed, 9 insertions(+), 9 deletions(-) + +--- a/arch/arc/kernel/process.c ++++ b/arch/arc/kernel/process.c +@@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hd + 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; + } + +--- a/arch/m68k/kernel/traps.c ++++ b/arch/m68k/kernel/traps.c +@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long s + */ + asmlinkage void fpsp040_die(void) + { +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + } + + #ifdef CONFIG_M68KFPU_EMU +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -1063,7 +1063,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + * We kill the task with a SIGSEGV in this situation. + */ + if (do_setcontext(new_ctx, regs, 0)) { +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + return -EFAULT; + } + +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -704,7 +704,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + */ + + if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) { +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + return -EFAULT; + } + set_current_blocked(&set); +@@ -713,7 +713,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucon + return -EFAULT; + if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) { + user_read_access_end(); +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + return -EFAULT; + } + user_read_access_end(); +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -84,7 +84,7 @@ static void default_trap_handler(struct + { + if (user_mode(regs)) { + report_user_fault(regs, SIGSEGV, 0); +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + } else + die(regs, "Unknown program exception"); + } +--- a/arch/um/kernel/trap.c ++++ b/arch/um/kernel/trap.c +@@ -158,7 +158,7 @@ static void bad_segv(struct faultinfo fi + + void fatal_sigsegv(void) + { +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + do_signal(¤t->thread.regs); + /* + * This is to tell gcc that we're not returning - do_signal +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -162,7 +162,7 @@ Efault_end: + user_access_end(); + Efault: + pr_alert("could not access userspace vm86 info\n"); +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + goto exit_vm86; + } + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1852,7 +1852,7 @@ out: + * SIGSEGV. + */ + if (bprm->point_of_no_return && !fatal_signal_pending(current)) +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + + out_unmark: + current->fs->in_exec = 0; diff --git a/queue-5.15/signal-s390-use-force_sigsegv-in-default_trap_handler.patch b/queue-5.15/signal-s390-use-force_sigsegv-in-default_trap_handler.patch new file mode 100644 index 00000000000..88bd9d146d8 --- /dev/null +++ b/queue-5.15/signal-s390-use-force_sigsegv-in-default_trap_handler.patch @@ -0,0 +1,48 @@ +From 9bc508cf0791c8e5a37696de1a046d746fcbd9d8 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:43:57 -0500 +Subject: signal/s390: Use force_sigsegv in default_trap_handler + +From: Eric W. Biederman + +commit 9bc508cf0791c8e5a37696de1a046d746fcbd9d8 upstream. + +Reading the history it is unclear why default_trap_handler calls +do_exit. It is not even menthioned in the commit where the change +happened. My best guess is that because it is unknown why the +exception happened it was desired to guarantee the process never +returned to userspace. + +Using do_exit(SIGSEGV) has the problem that it will only terminate one +thread of a process, leaving the process in an undefined state. + +Use force_sigsegv(SIGSEGV) instead which effectively has the same +behavior except that is uses the ordinary signal mechanism and +terminates all threads of a process and is generally well defined. + +Cc: Heiko Carstens +Cc: Vasily Gorbik +Cc: Christian Borntraeger +Cc: linux-s390@vger.kernel.org +Fixes: ca2ab03237ec ("[PATCH] s390: core changes") +History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git +Reviewed-by: Christian Borntraeger +Link: https://lkml.kernel.org/r/20211020174406.17889-11-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/kernel/traps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -84,7 +84,7 @@ static void default_trap_handler(struct + { + if (user_mode(regs)) { + report_user_fault(regs, SIGSEGV, 0); +- do_exit(SIGSEGV); ++ force_sigsegv(SIGSEGV); + } else + die(regs, "Unknown program exception"); + } diff --git a/queue-5.15/signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch b/queue-5.15/signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch new file mode 100644 index 00000000000..99cf741b82e --- /dev/null +++ b/queue-5.15/signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch @@ -0,0 +1,50 @@ +From c317d306d55079525c9610267fdaf3a8a6d2f08b Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:44:01 -0500 +Subject: signal/sparc32: Exit with a fatal signal when try_to_clear_window_buffer fails + +From: Eric W. Biederman + +commit c317d306d55079525c9610267fdaf3a8a6d2f08b upstream. + +The function try_to_clear_window_buffer is only called from +rtrap_32.c. After it is called the signal pending state is retested, +and signals are handled if TIF_SIGPENDING is set. This allows +try_to_clear_window_buffer to call force_fatal_signal and then rely on +the signal being delivered to kill the process, without any danger of +returning to userspace, or otherwise using possible corrupt state on +failure. + +The functional difference between force_fatal_sig and do_exit is that +do_exit will only terminate a single thread, and will never trigger a +core-dump. A multi-threaded program for which a single thread +terminates unexpectedly is hard to reason about. Calling force_fatal_sig +does not give userspace a chance to catch the signal, but otherwise +is an ordinary fatal signal exit, and it will trigger a coredump +of the offending process if core dumps are enabled. + +Cc: David Miller +Cc: sparclinux@vger.kernel.org +Link: https://lkml.kernel.org/r/20211020174406.17889-15-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/windows.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/windows.c ++++ b/arch/sparc/kernel/windows.c +@@ -121,8 +121,10 @@ void try_to_clear_window_buffer(struct p + + 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; + } diff --git a/queue-5.15/signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch b/queue-5.15/signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch new file mode 100644 index 00000000000..f8ec996a3b6 --- /dev/null +++ b/queue-5.15/signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch @@ -0,0 +1,48 @@ +From 086ec444f86660e103de8945d0dcae9b67132ac9 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:44:02 -0500 +Subject: signal/sparc32: In setup_rt_frame and setup_fram use force_fatal_sig + +From: Eric W. Biederman + +commit 086ec444f86660e103de8945d0dcae9b67132ac9 upstream. + +Modify the 32bit version of setup_rt_frame and setup_frame to act +similar to the 64bit version of setup_rt_frame and fail with a signal +instead of calling do_exit. + +Replacing do_exit(SIGILL) with force_fatal_signal(SIGILL) ensures that +the process will be terminated cleanly when the stack frame is +invalid, instead of just killing off a single thread and leaving the +process is a weird state. + +Cc: David Miller +Cc: sparclinux@vger.kernel.org +Link: https://lkml.kernel.org/r/20211020174406.17889-16-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/signal_32.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *k + get_sigframe(ksig, regs, sigframe_size); + + if (invalid_frame_pointer(sf, sigframe_size)) { +- do_exit(SIGILL); ++ force_fatal_sig(SIGILL); + return -EINVAL; + } + +@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal + 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; + } + diff --git a/queue-5.15/signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch b/queue-5.15/signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch new file mode 100644 index 00000000000..78b918c1754 --- /dev/null +++ b/queue-5.15/signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch @@ -0,0 +1,71 @@ +From 1fbd60df8a852d9c55de8cd3621899cf4c72a5b7 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:43:56 -0500 +Subject: signal/vm86_32: Properly send SIGSEGV when the vm86 state cannot be saved. + +From: Eric W. Biederman + +commit 1fbd60df8a852d9c55de8cd3621899cf4c72a5b7 upstream. + +Update save_v86_state to always complete all of it's work except +possibly some of the copies to userspace even if save_v86_state takes +a fault. This ensures that the kernel is always in a sane state, even +if userspace has done something silly. + +When save_v86_state takes a fault update it to force userspace to take +a SIGSEGV and terminate the userspace application. + +As Andy pointed out in review of the first version of this change +there are races between sigaction and the application terinating. Now +that the code has been modified to always perform all save_v86_state's +work (except possibly copying to userspace) those races do not matter +from a kernel perspective. + +Forcing the userspace application to terminate (by resetting it's +handler to SIGDFL) is there to keep everything as close to the current +behavior as possible while removing the unique (and difficult to +maintain) use of do_exit. + +If this new SIGSEGV happens during handle_signal the next time around +the exit_to_user_mode_loop, SIGSEGV will be delivered to userspace. + +All of the callers of handle_vm86_trap and handle_vm86_fault run the +exit_to_user_mode_loop before they return to userspace any signal sent +to the current task during their execution will be delivered to the +current task before that tasks exits to usermode. + +Cc: Andy Lutomirski +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: x86@kernel.org +Cc: H Peter Anvin +v1: https://lkml.kernel.org/r/20211020174406.17889-10-ebiederm@xmission.com +Link: https://lkml.kernel.org/r/877de1xcr6.fsf_-_@disp2133 +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/vm86_32.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -142,6 +142,7 @@ void save_v86_state(struct kernel_vm86_r + + user_access_end(); + ++exit_vm86: + preempt_disable(); + tsk->thread.sp0 = vm86->saved_sp0; + tsk->thread.sysenter_cs = __KERNEL_CS; +@@ -161,7 +162,8 @@ Efault_end: + user_access_end(); + Efault: + pr_alert("could not access userspace vm86 info\n"); +- do_exit(SIGSEGV); ++ force_sigsegv(SIGSEGV); ++ goto exit_vm86; + } + + static int do_vm86_irq_handling(int subfunction, int irqnumber); diff --git a/queue-5.15/signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch b/queue-5.15/signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch new file mode 100644 index 00000000000..0a85d995e54 --- /dev/null +++ b/queue-5.15/signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch @@ -0,0 +1,39 @@ +From 695dd0d634df8903e5ead8aa08d326f63b23368a Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 20 Oct 2021 12:44:03 -0500 +Subject: signal/x86: In emulate_vsyscall force a signal instead of calling do_exit + +From: Eric W. Biederman + +commit 695dd0d634df8903e5ead8aa08d326f63b23368a upstream. + +Directly calling do_exit with a signal number has the problem that +all of the side effects of the signal don't happen, such as +killing all of the threads of a process instead of just the +calling thread. + +So replace do_exit(SIGSYS) with force_fatal_sig(SIGSYS) which +causes the signal handling to take it's normal path and work +as expected. + +Cc: Andy Lutomirski +Link: https://lkml.kernel.org/r/20211020174406.17889-17-ebiederm@xmission.com +Signed-off-by: Eric W. Biederman +Cc: Thomas Backlund +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/entry/vsyscall/vsyscall_64.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/entry/vsyscall/vsyscall_64.c ++++ b/arch/x86/entry/vsyscall/vsyscall_64.c +@@ -226,7 +226,8 @@ bool emulate_vsyscall(unsigned long erro + 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)