]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Nov 2021 18:11:52 +0000 (19:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Nov 2021 18:11:52 +0000 (19:11 +0100)
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

12 files changed:
queue-5.15/exit-syscall_user_dispatch-send-ordinary-signals-on-failure.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/signal-don-t-always-set-sa_immutable-for-forced-signals.patch [new file with mode: 0644]
queue-5.15/signal-implement-force_fatal_sig.patch [new file with mode: 0644]
queue-5.15/signal-powerpc-on-swapcontext-failure-force-sigsegv.patch [new file with mode: 0644]
queue-5.15/signal-replace-force_fatal_sig-with-force_exit_sig-when-in-doubt.patch [new file with mode: 0644]
queue-5.15/signal-replace-force_sigsegv-sigsegv-with-force_fatal_sig-sigsegv.patch [new file with mode: 0644]
queue-5.15/signal-s390-use-force_sigsegv-in-default_trap_handler.patch [new file with mode: 0644]
queue-5.15/signal-sparc32-exit-with-a-fatal-signal-when-try_to_clear_window_buffer-fails.patch [new file with mode: 0644]
queue-5.15/signal-sparc32-in-setup_rt_frame-and-setup_fram-use-force_fatal_sig.patch [new file with mode: 0644]
queue-5.15/signal-vm86_32-properly-send-sigsegv-when-the-vm86-state-cannot-be-saved.patch [new file with mode: 0644]
queue-5.15/signal-x86-in-emulate_vsyscall-force-a-signal-instead-of-calling-do_exit.patch [new file with mode: 0644]

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 (file)
index 0000000..5a6df9e
--- /dev/null
@@ -0,0 +1,82 @@
+From 941edc5bf174b67f94db19817cbeab0a93e0c32a Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 20 Oct 2021 12:44:00 -0500
+Subject: exit/syscall_user_dispatch: Send ordinary signals on failure
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <krisman@collabora.com> 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 <krisman@collabora.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Andy Lutomirski <luto@kernel.org>
+[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 <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
index 86e39e95b5b58a25d90af12301a38e1f824a2255..68193af570a02c0c86770430175ecf0a88e91666 100644 (file)
@@ -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 (file)
index 0000000..38e7fc4
--- /dev/null
@@ -0,0 +1,114 @@
+From e349d945fac76bddc78ae1cb92a0145b427a87ce Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Thu, 18 Nov 2021 11:11:13 -0600
+Subject: signal: Don't always set SA_IMMUTABLE for forced signals
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <torvalds@linux-foundation.org>
+Reported-by: Kyle Huey <me@kylehuey.com>
+Reported-by: kernel test robot <oliver.sang@intel.com>
+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 <keescook@chromium.org>
+Tested-by: Kees Cook <keescook@chromium.org>
+Tested-by: Kyle Huey <khuey@kylehuey.com>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0bdbfb5
--- /dev/null
@@ -0,0 +1,87 @@
+From 26d5badbccddcc063dc5174a2baffd13a23322aa Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 20 Oct 2021 12:43:59 -0500
+Subject: signal: Implement force_fatal_sig
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..da8d95c
--- /dev/null
@@ -0,0 +1,70 @@
+From 83a1f27ad773b1d8f0460d3a676114c7651918cc Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 20 Oct 2021 12:43:53 -0500
+Subject: signal/powerpc: On swapcontext failure force SIGSEGV
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <mpe@ellerman.id.au>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Paul Mackerras <paulus@samba.org>
+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 <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..cac1263
--- /dev/null
@@ -0,0 +1,222 @@
+From fcb116bc43c8c37c052530ead79872f8b2615711 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <me@kylehuey.com>
+Reported-by: kernel test robot <oliver.sang@intel.com>
+[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 <keescook@chromium.org>
+Tested-by: Kees Cook <keescook@chromium.org>
+Tested-by: Kyle Huey <khuey@kylehuey.com>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..bf73d34
--- /dev/null
@@ -0,0 +1,130 @@
+From e21294a7aaae32c5d7154b187113a04db5852e37 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <geert@linux-m68k.org>
+Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
+Link: https://lkml.kernel.org/r/877de7jrev.fsf@disp2133
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(&current->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 (file)
index 0000000..88bd9d1
--- /dev/null
@@ -0,0 +1,48 @@
+From 9bc508cf0791c8e5a37696de1a046d746fcbd9d8 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 20 Oct 2021 12:43:57 -0500
+Subject: signal/s390: Use force_sigsegv in default_trap_handler
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <hca@linux.ibm.com>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Christian Borntraeger <borntraeger@de.ibm.com>
+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 <borntraeger@de.ibm.com>
+Link: https://lkml.kernel.org/r/20211020174406.17889-11-ebiederm@xmission.com
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..99cf741
--- /dev/null
@@ -0,0 +1,50 @@
+From c317d306d55079525c9610267fdaf3a8a6d2f08b Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <davem@davemloft.net>
+Cc: sparclinux@vger.kernel.org
+Link: https://lkml.kernel.org/r/20211020174406.17889-15-ebiederm@xmission.com
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..f8ec996
--- /dev/null
@@ -0,0 +1,48 @@
+From 086ec444f86660e103de8945d0dcae9b67132ac9 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <davem@davemloft.net>
+Cc: sparclinux@vger.kernel.org
+Link: https://lkml.kernel.org/r/20211020174406.17889-16-ebiederm@xmission.com
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..78b918c
--- /dev/null
@@ -0,0 +1,71 @@
+From 1fbd60df8a852d9c55de8cd3621899cf4c72a5b7 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <luto@kernel.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: x86@kernel.org
+Cc: H Peter Anvin <hpa@zytor.com>
+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 <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0a85d99
--- /dev/null
@@ -0,0 +1,39 @@
+From 695dd0d634df8903e5ead8aa08d326f63b23368a Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+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 <luto@kernel.org>
+Link: https://lkml.kernel.org/r/20211020174406.17889-17-ebiederm@xmission.com
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Thomas Backlund <tmb@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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)