when running strace tests, we noticed that si_addr appears to be wrong. the attached test shows the problem -- si_addr isn't set to the faulting address. i hacked arch/s390/mm/fault.c:do_sigsegv to load regs->psw.addr (sans mask), and it worked for insn based crashes. but obviously that doesn't work for data based ones. i'm not familiar with how regs->int_parm_long works though, so maybe it's supposed to be loaded indirectly. the use of __FAIL_ADDR_MASK blindly is most certainly incorrect ... whatever the fix, do_sigbus probably needs it too. on x86_64, both work: $ gcc test.c -O3 $ ./a.out data crash received signal 11 si_addr 0xa0 crasher 0xa0 PASS $ ./a.out asdf text crash received signal 11 si_addr 0xa0 crasher 0xa0 PASS on s390 both fail: $ gcc test.c -O3 $ ./a.out data crash received signal 11 si_addr (nil) crasher 0xa0 FAIL $ ./a.out asdf text crash received signal 11 si_addr (nil) crasher 0xa0 FAIL -mike
#include <inttypes.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> static bool text = true; union { void (*fn)(void); uintptr_t ptr; } crasher; static int *ptr; __attribute__((__noinline__)) void crashit(void) { if (text) { crasher.ptr = 0xA0; crasher.fn(); } else { ptr = (void *)0xA0; *ptr = 1; } } void sigcatcher(int signum, siginfo_t *siginfo, void *ucontext) { printf("received signal %i\n", signum); if (signum != SIGSEGV) { puts("FAIL (not SIGSEGV)"); exit(2); } printf("si_addr %p\n", siginfo->si_addr); bool passed; if (text) { printf("crasher %p\n", crasher.fn); passed = (crasher.ptr == (uintptr_t)siginfo->si_addr); } else { printf("crasher %p\n", ptr); passed = (ptr == siginfo->si_addr); } if (passed) { puts("PASS"); exit(0); } else { puts("FAIL"); exit(1); } } int main(int argc, char *argv[]) { struct sigaction sa; sa.sa_flags = SA_RESTART | SA_SIGINFO; sa.sa_sigaction = sigcatcher; sigaction(SIGSEGV, &sa, NULL); text = argc > 1 ? true : false; puts(text ? "text crash" : "data crash"); crashit(); return 10; }
Attachment:
signature.asc
Description: Digital signature