]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 Sep 2021 13:00:44 +0000 (15:00 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 Sep 2021 13:00:44 +0000 (15:00 +0200)
added patches:
parisc-fix-crash-with-signals-and-alloca.patch

queue-4.4/parisc-fix-crash-with-signals-and-alloca.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/parisc-fix-crash-with-signals-and-alloca.patch b/queue-4.4/parisc-fix-crash-with-signals-and-alloca.patch
new file mode 100644 (file)
index 0000000..0f1e8d1
--- /dev/null
@@ -0,0 +1,84 @@
+From 030f653078316a9cc9ca6bd1b0234dcf858be35d Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 30 Aug 2021 05:42:27 -0400
+Subject: parisc: fix crash with signals and alloca
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 030f653078316a9cc9ca6bd1b0234dcf858be35d upstream.
+
+I was debugging some crashes on parisc and I found out that there is a
+crash possibility if a function using alloca is interrupted by a signal.
+The reason for the crash is that the gcc alloca implementation leaves
+garbage in the upper 32 bits of the sp register. This normally doesn't
+matter (the upper bits are ignored because the PSW W-bit is clear),
+however the signal delivery routine in the kernel uses full 64 bits of sp
+and it fails with -EFAULT if the upper 32 bits are not zero.
+
+I created this program that demonstrates the problem:
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <alloca.h>
+
+static __attribute__((noinline,noclone)) void aa(int *size)
+{
+       void * volatile p = alloca(-*size);
+       while (1) ;
+}
+
+static void handler(int sig)
+{
+       write(1, "signal delivered\n", 17);
+       _exit(0);
+}
+
+int main(void)
+{
+       int size = -0x100;
+       signal(SIGALRM, handler);
+       alarm(1);
+       aa(&size);
+}
+
+If you compile it with optimizations, it will crash.
+The "aa" function has this disassembly:
+
+000106a0 <aa>:
+   106a0:       08 03 02 41     copy r3,r1
+   106a4:       08 1e 02 43     copy sp,r3
+   106a8:       6f c1 00 80     stw,ma r1,40(sp)
+   106ac:       37 dc 3f c1     ldo -20(sp),ret0
+   106b0:       0c 7c 12 90     stw ret0,8(r3)
+   106b4:       0f 40 10 9c     ldw 0(r26),ret0                ; ret0 = 0x00000000FFFFFF00
+   106b8:       97 9c 00 7e     subi 3f,ret0,ret0      ; ret0 = 0xFFFFFFFF0000013F
+   106bc:       d7 80 1c 1a     depwi 0,31,6,ret0      ; ret0 = 0xFFFFFFFF00000100
+   106c0:       0b 9e 0a 1e     add,l sp,ret0,sp       ;   sp = 0xFFFFFFFFxxxxxxxx
+   106c4:       e8 1f 1f f7     b,l,n 106c4 <aa+0x24>,r0
+
+This patch fixes the bug by truncating the "usp" variable to 32 bits.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/parisc/kernel/signal.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/parisc/kernel/signal.c
++++ b/arch/parisc/kernel/signal.c
+@@ -239,6 +239,12 @@ setup_rt_frame(struct ksignal *ksig, sig
+ #endif
+       
+       usp = (regs->gr[30] & ~(0x01UL));
++#ifdef CONFIG_64BIT
++      if (is_compat_task()) {
++              /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
++              usp = (compat_uint_t)usp;
++      }
++#endif
+       /*FIXME: frame_size parameter is unused, remove it. */
+       frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
index c9ceb58ad5eabd8e6afb7a1f1845190b4db356ab..1e4db12639010ee0ac6764ecfe57d247ac421c05 100644 (file)
@@ -113,3 +113,4 @@ revert-usb-xhci-fix-u1-u2-handling-for-hardware-with.patch
 parport-remove-non-zero-check-on-count.patch
 ath9k-fix-oob-read-ar9300_eeprom_restore_internal.patch
 net-fix-null-pointer-reference-in-cipso_v4_doi_free.patch
+parisc-fix-crash-with-signals-and-alloca.patch