uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap
authorOleg Nesterov <oleg@redhat.com>
Mon, 12 May 2014 16:24:45 +0000 (18:24 +0200)
committerOleg Nesterov <oleg@redhat.com>
Wed, 14 May 2014 11:57:28 +0000 (13:57 +0200)
commitb02ef20a9fba08948e643d3eec0efadf1da01a44
treed0db097668940dce698fec8b00d228cd29c1dee0
parent0eb14833d5b1ea1accfeffb71be5de5929f85da9
uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap

If the probed insn triggers a trap, ->si_addr = regs->ip is technically
correct, but this is not what the signal handler wants; we need to pass
the address of the probed insn, not the address of xol slot.

Add the new arch-agnostic helper, uprobe_get_trap_addr(), and change
fill_trap_info() and math_error() to use it. !CONFIG_UPROBES case in
uprobes.h uses a macro to avoid include hell and ensure that it can be
compiled even if an architecture doesn't define instruction_pointer().

Test-case:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

extern void probe_div(void);

void sigh(int sig, siginfo_t *info, void *c)
{
int passed = (info->si_addr == probe_div);
printf(passed ? "PASS\n" : "FAIL\n");
_exit(!passed);
}

int main(void)
{
struct sigaction sa = {
.sa_sigaction = sigh,
.sa_flags = SA_SIGINFO,
};

sigaction(SIGFPE, &sa, NULL);

asm (
"xor %ecx,%ecx\n"
".globl probe_div; probe_div:\n"
"idiv %ecx\n"
);

return 0;
}

it fails if probe_div() is probed.

Note: show_unhandled_signals users should probably use this helper too,
but we need to cleanup them first.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
arch/x86/kernel/traps.c
include/linux/uprobes.h
kernel/events/uprobes.c