summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2021-08-30 05:42:27 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-09-22 11:48:09 +0200
commit07f2e0249db3f7bdf91633c4e04be6b11e5a8ed4 (patch)
tree5b1425e7908ff90817447994b95678621d1b1856 /ipc
parent0cc9af2dffee3ba20d17a91d22acbc9b6488e5af (diff)
downloadlinux-stable-07f2e0249db3f7bdf91633c4e04be6b11e5a8ed4.tar.gz
linux-stable-07f2e0249db3f7bdf91633c4e04be6b11e5a8ed4.tar.bz2
linux-stable-07f2e0249db3f7bdf91633c4e04be6b11e5a8ed4.zip
parisc: fix crash with signals and alloca
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>
Diffstat (limited to 'ipc')
0 files changed, 0 insertions, 0 deletions