From 1ad10a27cff05a30a3956f54fbca24833f833b2d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 16 Sep 2021 15:00:44 +0200 Subject: [PATCH] 4.4-stable patches added patches: parisc-fix-crash-with-signals-and-alloca.patch --- ...sc-fix-crash-with-signals-and-alloca.patch | 84 +++++++++++++++++++ queue-4.4/series | 1 + 2 files changed, 85 insertions(+) create mode 100644 queue-4.4/parisc-fix-crash-with-signals-and-alloca.patch 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 index 00000000000..0f1e8d1e213 --- /dev/null +++ b/queue-4.4/parisc-fix-crash-with-signals-and-alloca.patch @@ -0,0 +1,84 @@ +From 030f653078316a9cc9ca6bd1b0234dcf858be35d Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Mon, 30 Aug 2021 05:42:27 -0400 +Subject: parisc: fix crash with signals and alloca + +From: Mikulas Patocka + +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 +#include +#include +#include + +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 : + 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 ,r0 + +This patch fixes the bug by truncating the "usp" variable to 32 bits. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + 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)); + diff --git a/queue-4.4/series b/queue-4.4/series index c9ceb58ad5e..1e4db126390 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -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 -- 2.47.2