Commit 05e792e3 authored by Eric W. Biederman's avatar Eric W. Biederman

signal/arm: Push siginfo generation into arm_notify_die

In arm_notify_die call force_sig_fault to let the generic
code handle siginfo generation.

This removes some boiler plate making the code easier to
maintain in the long run.
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent c8526809
...@@ -62,8 +62,8 @@ do { \ ...@@ -62,8 +62,8 @@ do { \
struct pt_regs; struct pt_regs;
void die(const char *msg, struct pt_regs *regs, int err); void die(const char *msg, struct pt_regs *regs, int err);
struct siginfo; void arm_notify_die(const char *str, struct pt_regs *regs,
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, int signo, int si_code, void __user *addr,
unsigned long err, unsigned long trap); unsigned long err, unsigned long trap);
#ifdef CONFIG_ARM_LPAE #ifdef CONFIG_ARM_LPAE
......
...@@ -98,22 +98,20 @@ static int proc_status_show(struct seq_file *m, void *v) ...@@ -98,22 +98,20 @@ static int proc_status_show(struct seq_file *m, void *v)
*/ */
static void set_segfault(struct pt_regs *regs, unsigned long addr) static void set_segfault(struct pt_regs *regs, unsigned long addr)
{ {
siginfo_t info; int si_code;
clear_siginfo(&info);
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
if (find_vma(current->mm, addr) == NULL) if (find_vma(current->mm, addr) == NULL)
info.si_code = SEGV_MAPERR; si_code = SEGV_MAPERR;
else else
info.si_code = SEGV_ACCERR; si_code = SEGV_ACCERR;
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_addr = (void *) instruction_pointer(regs);
pr_debug("SWP{B} emulation: access caused memory abort!\n"); pr_debug("SWP{B} emulation: access caused memory abort!\n");
arm_notify_die("Illegal memory access", regs, &info, 0, 0); arm_notify_die("Illegal memory access", regs,
SIGSEGV, si_code,
(void __user *)instruction_pointer(regs),
0, 0);
abtcounter++; abtcounter++;
} }
......
...@@ -365,13 +365,14 @@ void die(const char *str, struct pt_regs *regs, int err) ...@@ -365,13 +365,14 @@ void die(const char *str, struct pt_regs *regs, int err)
} }
void arm_notify_die(const char *str, struct pt_regs *regs, void arm_notify_die(const char *str, struct pt_regs *regs,
struct siginfo *info, unsigned long err, unsigned long trap) int signo, int si_code, void __user *addr,
unsigned long err, unsigned long trap)
{ {
if (user_mode(regs)) { if (user_mode(regs)) {
current->thread.error_code = err; current->thread.error_code = err;
current->thread.trap_no = trap; current->thread.trap_no = trap;
force_sig_info(info->si_signo, info, current); force_sig_fault(signo, si_code, addr, current);
} else { } else {
die(str, regs, err); die(str, regs, err);
} }
...@@ -438,10 +439,8 @@ int call_undef_hook(struct pt_regs *regs, unsigned int instr) ...@@ -438,10 +439,8 @@ int call_undef_hook(struct pt_regs *regs, unsigned int instr)
asmlinkage void do_undefinstr(struct pt_regs *regs) asmlinkage void do_undefinstr(struct pt_regs *regs)
{ {
unsigned int instr; unsigned int instr;
siginfo_t info;
void __user *pc; void __user *pc;
clear_siginfo(&info);
pc = (void __user *)instruction_pointer(regs); pc = (void __user *)instruction_pointer(regs);
if (processor_mode(regs) == SVC_MODE) { if (processor_mode(regs) == SVC_MODE) {
...@@ -485,13 +484,8 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) ...@@ -485,13 +484,8 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
dump_instr(KERN_INFO, regs); dump_instr(KERN_INFO, regs);
} }
#endif #endif
arm_notify_die("Oops - undefined instruction", regs,
info.si_signo = SIGILL; SIGILL, ILL_ILLOPC, pc, 0, 6);
info.si_errno = 0;
info.si_code = ILL_ILLOPC;
info.si_addr = pc;
arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
} }
NOKPROBE_SYMBOL(do_undefinstr) NOKPROBE_SYMBOL(do_undefinstr)
...@@ -539,9 +533,6 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) ...@@ -539,9 +533,6 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason)
static int bad_syscall(int n, struct pt_regs *regs) static int bad_syscall(int n, struct pt_regs *regs)
{ {
siginfo_t info;
clear_siginfo(&info);
if ((current->personality & PER_MASK) != PER_LINUX) { if ((current->personality & PER_MASK) != PER_LINUX) {
send_sig(SIGSEGV, current, 1); send_sig(SIGSEGV, current, 1);
return regs->ARM_r0; return regs->ARM_r0;
...@@ -555,13 +546,10 @@ static int bad_syscall(int n, struct pt_regs *regs) ...@@ -555,13 +546,10 @@ static int bad_syscall(int n, struct pt_regs *regs)
} }
#endif #endif
info.si_signo = SIGILL; arm_notify_die("Oops - bad syscall", regs, SIGILL, ILL_ILLTRP,
info.si_errno = 0; (void __user *)instruction_pointer(regs) -
info.si_code = ILL_ILLTRP; (thumb_mode(regs) ? 2 : 4),
info.si_addr = (void __user *)instruction_pointer(regs) - n, 0);
(thumb_mode(regs) ? 2 : 4);
arm_notify_die("Oops - bad syscall", regs, &info, n, 0);
return regs->ARM_r0; return regs->ARM_r0;
} }
...@@ -607,20 +595,13 @@ do_cache_op(unsigned long start, unsigned long end, int flags) ...@@ -607,20 +595,13 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
#define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE)
asmlinkage int arm_syscall(int no, struct pt_regs *regs) asmlinkage int arm_syscall(int no, struct pt_regs *regs)
{ {
siginfo_t info;
clear_siginfo(&info);
if ((no >> 16) != (__ARM_NR_BASE>> 16)) if ((no >> 16) != (__ARM_NR_BASE>> 16))
return bad_syscall(no, regs); return bad_syscall(no, regs);
switch (no & 0xffff) { switch (no & 0xffff) {
case 0: /* branch through 0 */ case 0: /* branch through 0 */
info.si_signo = SIGSEGV; arm_notify_die("branch through zero", regs,
info.si_errno = 0; SIGSEGV, SEGV_MAPERR, NULL, 0, 0);
info.si_code = SEGV_MAPERR;
info.si_addr = NULL;
arm_notify_die("branch through zero", regs, &info, 0, 0);
return 0; return 0;
case NR(breakpoint): /* SWI BREAK_POINT */ case NR(breakpoint): /* SWI BREAK_POINT */
...@@ -688,13 +669,10 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) ...@@ -688,13 +669,10 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
} }
} }
#endif #endif
info.si_signo = SIGILL; arm_notify_die("Oops - bad syscall(2)", regs, SIGILL, ILL_ILLTRP,
info.si_errno = 0; (void __user *)instruction_pointer(regs) -
info.si_code = ILL_ILLTRP; (thumb_mode(regs) ? 2 : 4),
info.si_addr = (void __user *)instruction_pointer(regs) - no, 0);
(thumb_mode(regs) ? 2 : 4);
arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
return 0; return 0;
} }
...@@ -744,9 +722,6 @@ asmlinkage void ...@@ -744,9 +722,6 @@ asmlinkage void
baddataabort(int code, unsigned long instr, struct pt_regs *regs) baddataabort(int code, unsigned long instr, struct pt_regs *regs)
{ {
unsigned long addr = instruction_pointer(regs); unsigned long addr = instruction_pointer(regs);
siginfo_t info;
clear_siginfo(&info);
#ifdef CONFIG_DEBUG_USER #ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_BADABORT) { if (user_debug & UDBG_BADABORT) {
...@@ -757,12 +732,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) ...@@ -757,12 +732,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
} }
#endif #endif
info.si_signo = SIGILL; arm_notify_die("unknown data abort code", regs,
info.si_errno = 0; SIGILL, ILL_ILLOPC, (void __user *)addr, instr, 0);
info.si_code = ILL_ILLOPC;
info.si_addr = (void __user *)addr;
arm_notify_die("unknown data abort code", regs, &info, instr, 0);
} }
void __readwrite_bug(const char *fn) void __readwrite_bug(const char *fn)
......
...@@ -554,7 +554,6 @@ asmlinkage void ...@@ -554,7 +554,6 @@ asmlinkage void
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{ {
const struct fsr_info *inf = fsr_info + fsr_fs(fsr); const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
struct siginfo info;
if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
return; return;
...@@ -563,12 +562,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -563,12 +562,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
inf->name, fsr, addr); inf->name, fsr, addr);
show_pte(current->mm, addr); show_pte(current->mm, addr);
clear_siginfo(&info); arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
info.si_signo = inf->sig; fsr, 0);
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
arm_notify_die("", regs, &info, fsr, 0);
} }
void __init void __init
...@@ -588,7 +583,6 @@ asmlinkage void ...@@ -588,7 +583,6 @@ asmlinkage void
do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
{ {
const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
struct siginfo info;
if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
return; return;
...@@ -596,12 +590,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) ...@@ -596,12 +590,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
inf->name, ifsr, addr); inf->name, ifsr, addr);
clear_siginfo(&info); arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
info.si_signo = inf->sig; ifsr, 0);
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
arm_notify_die("", regs, &info, ifsr, 0);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment