mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
		
							parent
							
								
									c852680959
								
							
						
					
					
						commit
						05e792e30e
					
				
					 4 changed files with 30 additions and 71 deletions
				
			
		| 
						 | 
					@ -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)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
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(¤t->mm->mmap_sem);
 | 
						down_read(¤t->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(¤t->mm->mmap_sem);
 | 
						up_read(¤t->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)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
				
			||||||
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)
 | 
				
			||||||
		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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#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)
 | 
				
			||||||
#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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#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
 | 
				
			||||||
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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#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
 | 
				
			||||||
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)
 | 
				
			||||||
		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
 | 
				
			||||||
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)
 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue