From be5c2ff06c2a30fb694d54b0a100ef4f55e1de3a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 17 Apr 2018 15:21:58 -0500 Subject: signal/nds32: Use force_sig in unhandled_interruption and unhandled_exceptions Neither unhandled_interrupt nor unhandled_exceptions fills in any of the siginfo fields whend sending SIGKILL. Further because it is SIGKILL even if all of the fields were filled out appropriately it would be impossible for the process to read any of the siginfo fields. So simplfy things and just use force_sig instead of force_sig_info. Fixes: 2923f5ea7738 ("nds32: Exception handling") Cc: Vincent Chen Cc: Greentime Hu Cc: Arnd Bergmann Acked-by: Vincent Chen Signed-off-by: "Eric W. Biederman" --- arch/nds32/kernel/traps.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'arch/nds32') diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c index 6e34eb9..65961bf 100644 --- a/arch/nds32/kernel/traps.c +++ b/arch/nds32/kernel/traps.c @@ -318,29 +318,22 @@ void do_debug_trap(unsigned long entry, unsigned long addr, void unhandled_interruption(struct pt_regs *regs) { - siginfo_t si; pr_emerg("unhandled_interruption\n"); show_regs(regs); if (!user_mode(regs)) do_exit(SIGKILL); - si.si_signo = SIGKILL; - si.si_errno = 0; - force_sig_info(SIGKILL, &si, current); + force_sig(SIGKILL, current); } void unhandled_exceptions(unsigned long entry, unsigned long addr, unsigned long type, struct pt_regs *regs) { - siginfo_t si; pr_emerg("Unhandled Exception: entry: %lx addr:%lx itype:%lx\n", entry, addr, type); show_regs(regs); if (!user_mode(regs)) do_exit(SIGKILL); - si.si_signo = SIGKILL; - si.si_errno = 0; - si.si_addr = (void *)addr; - force_sig_info(SIGKILL, &si, current); + force_sig(SIGKILL, current); } extern int do_page_fault(unsigned long entry, unsigned long addr, -- cgit v1.1 From f6ed1ecad56fec7ab5c6bf741064b95801e9688f Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 17 Apr 2018 15:23:48 -0500 Subject: signal/nds32: Use force_sig(SIGILL) in do_revisn As originally committed do_revisn would deliver a siginfo for SIGILL with an si_code composed of random stack contents. That makes no sense and is not something userspace can depend on. So simplify the code and just use "force_sig(SIG_ILL, current)" instead. Fixes: 2923f5ea7738 ("nds32: Exception handling") Cc: Vincent Chen Cc: Greentime Hu Cc: Arnd Bergmann Signed-off-by: "Eric W. Biederman" --- arch/nds32/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/nds32') diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c index 65961bf..8e9a5b1 100644 --- a/arch/nds32/kernel/traps.c +++ b/arch/nds32/kernel/traps.c @@ -356,14 +356,11 @@ void do_dispatch_tlb_misc(unsigned long entry, unsigned long addr, void do_revinsn(struct pt_regs *regs) { - siginfo_t si; pr_emerg("Reserved Instruction\n"); show_regs(regs); if (!user_mode(regs)) do_exit(SIGILL); - si.si_signo = SIGILL; - si.si_errno = 0; - force_sig_info(SIGILL, &si, current); + force_sig(SIGILL, current); } #ifdef CONFIG_ALIGNMENT_TRAP -- cgit v1.1 From 3eb0f5193b497083391aa05d35210d5645211eef Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 17 Apr 2018 15:26:37 -0500 Subject: signal: Ensure every siginfo we send has all bits initialized Call clear_siginfo to ensure every stack allocated siginfo is properly initialized before being passed to the signal sending functions. Note: It is not safe to depend on C initializers to initialize struct siginfo on the stack because C is allowed to skip holes when initializing a structure. The initialization of struct siginfo in tracehook_report_syscall_exit was moved from the helper user_single_step_siginfo into tracehook_report_syscall_exit itself, to make it clear that the local variable siginfo gets fully initialized. In a few cases the scope of struct siginfo has been reduced to make it clear that siginfo siginfo is not used on other paths in the function in which it is declared. Instances of using memset to initialize siginfo have been replaced with calls clear_siginfo for clarity. Signed-off-by: "Eric W. Biederman" --- arch/nds32/kernel/traps.c | 3 ++- arch/nds32/mm/fault.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/nds32') diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c index 8e9a5b1..4691176 100644 --- a/arch/nds32/kernel/traps.c +++ b/arch/nds32/kernel/traps.c @@ -229,6 +229,7 @@ int bad_syscall(int n, struct pt_regs *regs) return regs->uregs[0]; } + clear_siginfo(&info); info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLTRP; @@ -292,7 +293,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, tsk->thread.trap_no = ENTRY_DEBUG_RELATED; tsk->thread.error_code = error_code; - memset(&info, 0, sizeof(info)); + clear_siginfo(&info); info.si_signo = SIGTRAP; info.si_code = si_code; info.si_addr = (void __user *)instruction_pointer(regs); diff --git a/arch/nds32/mm/fault.c b/arch/nds32/mm/fault.c index 3a246fb..876ee01 100644 --- a/arch/nds32/mm/fault.c +++ b/arch/nds32/mm/fault.c @@ -77,6 +77,7 @@ void do_page_fault(unsigned long entry, unsigned long addr, unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + clear_siginfo(&info); error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE); tsk = current; mm = tsk->mm; -- cgit v1.1 From d808e918ed1533132c3124be52dfcfcda16a0bf0 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 16 Apr 2018 14:58:34 -0500 Subject: signal/nds32: Use force_sig_fault where appropriate Filling in struct siginfo before calling force_sig_info a tedious and error prone process, where once in a great while the wrong fields are filled out, and siginfo has been inconsistently cleared. Simplify this process by using the helper force_sig_fault. Which takes as a parameters all of the information it needs, ensures all of the fiddly bits of filling in struct siginfo are done properly and then calls force_sig_info. In short about a 5 line reduction in code for every time force_sig_info is called, which makes the calling function clearer. Cc: Greentime Hu Cc: Vincent Chen Acked-by: Vincent Chen Signed-off-by: "Eric W. Biederman" --- arch/nds32/kernel/traps.c | 20 ++++---------------- arch/nds32/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 30 deletions(-) (limited to 'arch/nds32') diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c index 4691176..a6205fd 100644 --- a/arch/nds32/kernel/traps.c +++ b/arch/nds32/kernel/traps.c @@ -222,20 +222,13 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err) int bad_syscall(int n, struct pt_regs *regs) { - siginfo_t info; - if (current->personality != PER_LINUX) { send_sig(SIGSEGV, current, 1); return regs->uregs[0]; } - clear_siginfo(&info); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - 4; - - force_sig_info(SIGILL, &info, current); + force_sig_fault(SIGILL, ILL_ILLTRP, + (void __user *)instruction_pointer(regs) - 4, current); die_if_kernel("Oops - bad syscall", regs, n); return regs->uregs[0]; } @@ -288,16 +281,11 @@ void __init early_trap_init(void) void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code, int si_code) { - struct siginfo info; - tsk->thread.trap_no = ENTRY_DEBUG_RELATED; tsk->thread.error_code = error_code; - clear_siginfo(&info); - info.si_signo = SIGTRAP; - info.si_code = si_code; - info.si_addr = (void __user *)instruction_pointer(regs); - force_sig_info(SIGTRAP, &info, tsk); + force_sig_fault(SIGTRAP, si_code, + (void __user *)instruction_pointer(regs), tsk); } void do_debug_trap(unsigned long entry, unsigned long addr, diff --git a/arch/nds32/mm/fault.c b/arch/nds32/mm/fault.c index 876ee01..9bdb7c3 100644 --- a/arch/nds32/mm/fault.c +++ b/arch/nds32/mm/fault.c @@ -72,16 +72,15 @@ void do_page_fault(unsigned long entry, unsigned long addr, struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct *vma; - siginfo_t info; + int si_code; int fault; unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; - clear_siginfo(&info); error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE); tsk = current; mm = tsk->mm; - info.si_code = SEGV_MAPERR; + si_code = SEGV_MAPERR; /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -162,7 +161,7 @@ retry: */ good_area: - info.si_code = SEGV_ACCERR; + si_code = SEGV_ACCERR; /* first do some preliminary protection checks */ if (entry == ENTRY_PTE_NOT_PRESENT) { @@ -267,11 +266,7 @@ bad_area_nosemaphore: tsk->thread.address = addr; tsk->thread.error_code = error_code; tsk->thread.trap_no = entry; - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code has been set above */ - info.si_addr = (void *)addr; - force_sig_info(SIGSEGV, &info, tsk); + force_sig_fault(SIGSEGV, si_code, (void __user *)addr, tsk); return; } @@ -340,11 +335,7 @@ do_sigbus: tsk->thread.address = addr; tsk->thread.error_code = error_code; tsk->thread.trap_no = entry; - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *)addr; - force_sig_info(SIGBUS, &info, tsk); + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr, tsk); return; -- cgit v1.1