sigsegv/sigbus not setting si_addr correctly for insn faults

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Kernel Development]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Info]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Linux Media]     [Device Mapper]

  Powered by Linux