siginfo bugfixes and cleanups
Subsystems (32)
cover siginfo bugfixes and cleanups
Mostly this dealing with aliases of SI_USER, that make it impossible for userspace to tell what kind of siginfo it has received.
Also in this series is the change to ensure we have siginfo initialized so I can rip out the switch in copy_siginfo_to_user for better performance, and to ensure better backwards compatibility as siginfo as generated in the callers is passed to userspace.
There are also fixes for a few other siginfo bugs I have found.
There are cleanups of ifdefs on SEGV_BNDERR and BUS_MCERR_AX that are no longer necessary.
I plan to merge these bug fixes through my siginfo tree, but if you object to them or would prefer to have them go through your arch tree please let me know.
The changes are avaiable as a totality at:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git siginfo-review
Dmitry V. Levin (1):
sparc: fix compat siginfo ABI regression
Eric W. Biederman (16):
signal/alpha: Document a conflict with SI_USER for SIGFPE signal/sh: Use force_sig_fault in hw_breakpoint_handler signal/nds32: Use force_sig in unhandled_interruption and unhandled_exceptions signal/nds32: Use force_sig(SIGILL) in do_revisn
signal: Ensure every siginfo we send has all bits initialized
signal: Reduce copy_siginfo_to_user to just copy_to_user
signal: Stop special casing TRAP_FIXME and FPE_FIXME in siginfo_layout
signal: Remove SEGV_BNDERR ifdefs
signal: Remove ifdefs for BUS_MCEERR_AR and BUS_MCEERR_AO signal/alpha: Replace FPE_FIXME with FPE_FLTUNK
signal/ia64: Replace FPE_FIXME with FPE_FLTUNK
signal/powerpc: Replace FPE_FIXME with FPE_FLTUNK signal/unicore32: Use FPE_FLTUNK instead of 0 in ucf64_raise_sigfpe
signal: Add TRAP_UNK si_code for undiagnosted trap exceptions signal/alpha: Replace TRAP_FIXME with TRAP_UNK
signal/powerpc: Replace TRAP_FIXME with TRAP_UNK
arch/alpha/include/uapi/asm/siginfo.h | 14 ---- arch/alpha/kernel/osf_sys.c | 3 +- arch/alpha/kernel/signal.c | 2 + arch/alpha/kernel/traps.c | 11 ++- arch/alpha/mm/fault.c | 2 + arch/arc/mm/fault.c | 2 + arch/arm/kernel/ptrace.c | 1 + arch/arm/kernel/swp_emulate.c | 1 + arch/arm/kernel/traps.c | 5 ++ arch/arm/mm/alignment.c | 1 + arch/arm/mm/fault.c | 4 + arch/arm/vfp/vfpmodule.c | 3 +- arch/arm64/kernel/fpsimd.c | 2 +- arch/arm64/kernel/sys_compat.c | 1 + arch/arm64/kernel/traps.c | 1 + arch/arm64/mm/fault.c | 18 +++-- arch/c6x/kernel/traps.c | 1 + arch/hexagon/kernel/traps.c | 1 + arch/hexagon/mm/vm_fault.c | 1 + arch/ia64/include/uapi/asm/siginfo.h | 7 -- arch/ia64/kernel/brl_emu.c | 1 + arch/ia64/kernel/signal.c | 2 + arch/ia64/kernel/traps.c | 31 ++++++-- arch/ia64/kernel/unaligned.c | 1 + arch/ia64/mm/fault.c | 4 +- arch/m68k/kernel/traps.c | 2 + arch/microblaze/kernel/exceptions.c | 1 + arch/microblaze/mm/fault.c | 4 +- arch/mips/mm/fault.c | 1 + arch/nds32/kernel/traps.c | 19 ++--- arch/nds32/mm/fault.c | 1 + arch/nios2/kernel/traps.c | 1 + arch/openrisc/kernel/traps.c | 5 +- arch/openrisc/mm/fault.c | 1 + arch/parisc/kernel/ptrace.c | 1 + arch/parisc/kernel/traps.c | 2 + arch/parisc/kernel/unaligned.c | 1 + arch/parisc/math-emu/driver.c | 1 + arch/parisc/mm/fault.c | 1 + arch/powerpc/include/uapi/asm/siginfo.h | 15 ---- arch/powerpc/kernel/process.c | 1 + arch/powerpc/kernel/traps.c | 13 ++-- arch/powerpc/mm/fault.c | 1 + arch/powerpc/platforms/cell/spufs/fault.c | 2 +- arch/riscv/kernel/traps.c | 1 + arch/s390/kernel/traps.c | 5 +- arch/s390/mm/fault.c | 2 + arch/sh/kernel/hw_breakpoint.c | 9 +-- arch/sh/kernel/traps_32.c | 2 + arch/sh/math-emu/math.c | 1 + arch/sh/mm/fault.c | 1 + arch/sparc/include/uapi/asm/siginfo.h | 7 -- arch/sparc/kernel/process_64.c | 1 + arch/sparc/kernel/sys_sparc_32.c | 1 + arch/sparc/kernel/traps_32.c | 12 ++- arch/sparc/kernel/traps_64.c | 16 +++- arch/sparc/kernel/unaligned_32.c | 1 + arch/sparc/mm/fault_32.c | 1 + arch/sparc/mm/fault_64.c | 1 + arch/um/kernel/trap.c | 2 + arch/unicore32/kernel/fpu-ucf64.c | 8 +- arch/unicore32/mm/fault.c | 3 + arch/x86/entry/vsyscall/vsyscall_64.c | 2 +- arch/x86/kernel/ptrace.c | 2 +- arch/x86/kernel/signal_compat.c | 2 +- arch/x86/kernel/traps.c | 3 + arch/x86/kernel/umip.c | 1 + arch/x86/kvm/mmu.c | 1 + arch/x86/mm/fault.c | 1 + arch/xtensa/kernel/traps.c | 1 + arch/xtensa/mm/fault.c | 1 + fs/signalfd.c | 15 +--- include/linux/ptrace.h | 1 - include/linux/tracehook.h | 1 + include/uapi/asm-generic/siginfo.h | 3 +- kernel/signal.c | 123 +++--------------------------- virt/kvm/arm/mmu.c | 1 + 77 files changed, 194 insertions(+), 231 deletions(-)
PATCH 1/17 signal/alpha: Document a conflict with SI_USER for SIGFPE
Setting si_code to 0 is the same as setting si_code to SI_USER. This is the same si_code as SI_USER. Posix and common sense requires that SI_USER not be a signal specific si_code. As such this use of 0 for the si_code is a pretty horribly broken ABI.
Cc: Helge Deller <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Ivan Kokshaysky <[email protected]>
Cc: Matt Turner <[email protected]>
Cc: [email protected]
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
Ref: 0a635c7a84cf ("Fill in siginfo_t.")
--- arch/alpha/kernel/osf_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/alpha/kernel/osf_sys.c +1 -1
@@ -872,7 +872,7 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer, fex = (exc >>IEEE_STATUS_TO_EXCSUM_SHIFT ) & swcr;if (fex) {siginfo_t info; -int si_code =0 ; +int si_code =FPE_FIXME ;if (fex &IEEE_TRAP_ENABLE_DNO ) si_code =FPE_FLTUND ;if (fex &IEEE_TRAP_ENABLE_INE ) si_code =FPE_FLTRES ;
Signature · 1 line
2.14.1
PATCH 2/17 sparc: fix compat siginfo ABI regression
In reply to Eric W. BiedermanFrom: "Dmitry V. Levin" <[email protected]>
Starting with commit v4.14-rc1~60^2^2~1, a SIGFPE signal sent via kill results to wrong values in si_pid and si_uid fields of compat siginfo_t.
This happens due to FPE_FIXME being defined to 0 for sparc, and at the same time siginfo_layout() introduced by the same commit returns SIL_FAULT for SIGFPE if si_code == SI_USER and FPE_FIXME is defined to 0.
Fix this regression by removing FPE_FIXME macro and changing all its users to assign FPE_FLTUNK to si_code instead of FPE_FIXME.
Note that FPE_FLTUNK is a new macro introduced by commit 266da65e9156d93e1126e185259a4aae68188d0e.
Tested with commit v4.16-11958-g16e205cf42da.
This bug was found by strace test suite.
Quoted 1 line · In the discussion about FPE_FLTUNK on sparc David Miller
Eric, feel free to do something similar on Sparc.
Thanks-to: Anatoly Pugachev <[email protected]>
--- arch/sparc/include/uapi/asm/siginfo.h | 7 ------- arch/sparc/kernel/traps_32.c | 2 +- arch/sparc/kernel/traps_64.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-)
arch/sparc/include/uapi/asm/siginfo.h +0 -7
@@ -17,13 +17,6 @@#define SI_NOINFO 32767/* no information in siginfo_t */ -/* -* SIGFPE si_codes -*/ -#ifdef __KERNEL__ -#define FPE_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ -/* * SIGEMT si_codes */
arch/sparc/kernel/traps_32.c +1 -1
@@ -307,7 +307,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, info.si_errno =0 ; info.si_addr = (void __user *)pc; info.si_trapno =0 ; - info.si_code =FPE_FIXME ; + info.si_code =FPE_FLTUNK ;if ((fsr &0x1c000 ) == (1 <<14 )) {if (fsr &0x10 ) info.si_code =FPE_FLTINV ;
arch/sparc/kernel/traps_64.c +1 -1
@@ -2372,7 +2372,7 @@ static void do_fpe_common(struct pt_regs *regs) info.si_errno =0 ; info.si_addr = (void __user *)regs->tpc; info.si_trapno =0 ; - info.si_code =FPE_FIXME ; + info.si_code =FPE_FLTUNK ;if ((fsr &0x1c000 ) == (1 <<14 )) {if (fsr &0x10 ) info.si_code =FPE_FLTINV ;
Signature · 1 line
2.14.1
PATCH 3/17 signal/sh: Use force_sig_fault in hw_breakpoint_handler
In reply to Eric W. BiedermanThe call chain is:
breakpoint
notify_die
hw_breakpoint_exceptions_notify
hw_breakpoint_handler
So the signal number can only be SIGTRAP.
In hw_breakpoint_handler rc is either NOTIFY_STOP or NOTIF_DONE both of which notifier_to_errno converts to 0. So si_errno is 0.
Historically si_addr was left unitialized in struct siginfo which is a bug. There appears to be no consensus among the various architectures which value should be in si_addr. So since no usable value has been returned up to this point return NULL in si_addr.
--- arch/sh/kernel/hw_breakpoint.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
arch/sh/kernel/hw_breakpoint.c +2 -7
@@ -347,13 +347,8 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)/* Deliver the signal to userspace */ if (!arch_check_bp_in_kernelspace (bp)) { -siginfo_t info; - - info.si_signo = args->signr; - info.si_errno =notifier_to_errno (rc); - info.si_code =TRAP_HWBKPT ; - -force_sig_info (args->signr, &info, current); +force_sig_fault (SIGTRAP ,TRAP_HWBKPT , + (void __user *)NULL , current); }rcu_read_unlock ();
Signature · 1 line
2.14.1
PATCH 4/17 signal/nds32: Use force_sig in unhandled_interruption and unhandled_exceptions
In reply to Eric W. BiedermanNeither 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.
--- arch/nds32/kernel/traps.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
arch/nds32/kernel/traps.c +2 -9
@@ -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,
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 04/17] signal/nds32: Use force_sig in unhandled_interruption and unhandled_exceptions
2018-04-20 9:03 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 52 lines
Neither
unhandled_interruptnorunhandled_exceptionsfills 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 useforce_siginstead offorce_sig_info.Fixes 2923f5ea7738 ("nds32: Exception handling")Cc Vincent Chen <[email protected]>Cc Greentime Hu <[email protected]>Cc Arnd Bergmann <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/nds32/kernel/traps.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)arch/nds32/kernel/traps.c +2
-10@@ -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, --
Quoted 2 lines
2.14.1
Acked-by Vincent Chen
PATCH 5/17 signal/nds32: Use force_sig(SIGILL) in do_revisn
In reply to Eric W. BiedermanAs 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.
--- arch/nds32/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/nds32/kernel/traps.c +1 -4
@@ -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
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 05/17] signal/nds32: Use force_sig(SIGILL) in do_revisn
2018-04-20 9:03 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 35 lines
As originally committed
do_revisnwould deliver a siginfo for SIGILL with ansi_codecomposed 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 <[email protected]>Cc Greentime Hu <[email protected]>Cc Arnd Bergmann <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/nds32/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/nds32/kernel/traps.c +1
-5@@ -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 --
Quoted 2 lines
2.14.1
You are right we do not store any valuable information in sigingo_t now. However, We hope more information can be recorded by force_sig_fault() as below instead of calling force_sig() directly.
- force_sig(SIGILL, current);
+ force_sig_fault(SIGILL, ILL_ILLTRP,
+ (void __user *)instruction_pointer(regs), current);
Thanks
Vincent Chen
PATCH 1/1 signal/nds32: More information in do_revinsn
While reviewing f6ed1ecad56f ("signal/nds32: Use force_sig(SIGILL) in do_revisn") Vincent Chen asked if it was possible to provide more information in do_revinsn with force_sig_fault.
That seems reasonable and the appropirate si_code appears to be ILL_ILLOPC (illegal opcode) as the printk indicates this code path is triggered when a reserved instruction is exectured.
So update do_revinsn to use force_sig_fault(SIGILL, ILL_ILLOPC, ...). Giving userspace a much better experience when soemone attempts to execute a reserved instruction.
---
Vincent I have updated this from your suggestion to use ILL_ILLOPC as that appears the more appropriate si_code. Normally I expect you could just update your nds32 tree and make this kind of change but since I am touching this code anyway I will be happy to take this change along with the others.
Does this look good to you?
arch/nds32/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/nds32/kernel/traps.c +2 -1
@@ -349,7 +349,8 @@ void do_revinsn(struct pt_regs *regs)show_regs (regs);if (!user_mode (regs))do_exit (SIGILL ); -force_sig (SIGILL , current); +force_sig_fault (SIGILL ,ILL_ILLOPC , + (void __user *)instruction_pointer (regs), current); }#ifdef CONFIG_ALIGNMENT_TRAP
Signature · 1 line
2.14.1
Re: [PATCH] signal/nds32: More information in do_revinsn
2018-04-26 0:13 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 9 lines
While reviewing
f6ed1ecad56f("signal/nds32: Useforce_sig(SIGILL)indo_revisn") Vincent Chen asked if it was possible to provide more information indo_revinsnwithforce_sig_fault.That seems reasonable and the appropirate
si_codeappears to beILL_ILLOPC(illegal opcode) as the printk indicates this code path is triggered when a reserved instruction is exectured.
I think error code is set as ILL_ILLOPC is a good choice for normal reserved instruction
but it seems a little bit inappropriate for nds32. For nds32 reserved exception, It is possibly
triggered by illegal opcode, operand and immediate. Unfortunately, do_revisn() can not
identify the actual reason now. Therefore, I chose ILLTRAP to avoid confusing user when
the reserved exception is cauesd by wrong immediate or operand.
Quoted 10 lines
So update
do_revinsnto useforce_sig_fault(SIGILL, ILL_ILLOPC, ...). Giving userspace a much better experience when soemone attempts to execute a reserved instruction.Cc Greentime Hu <[email protected]>Cc Vincent Chen <[email protected]>Suggested-by Vincent Chen <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>---
Quoted 8 lines
Vincent I have updated this from your suggestion to use
ILL_ILLOPCas that appears the more appropriatesi_code. Normally I expect you could just update your nds32 tree and make this kind of change but since I am touching this code anyway I will be happy to take this change along with the others.Does this look good to you?
It is fine to commit this change along with the others.
Vincent Chen
Quoted 20 lines
arch/nds32/kernel/traps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)arch/nds32/kernel/traps.c +2
-2@@ -349,7 +349,8 @@ void do_revinsn(struct pt_regs *regs)show_regs (regs);if (!user_mode (regs))do_exit (SIGILL ); -force_sig (SIGILL , current); +force_sig_fault (SIGILL ,ILL_ILLOPC , + (void __user *)instruction_pointer (regs), current); }#ifdef CONFIG_ALIGNMENT_TRAP --2.14.1
PATCH 6/17 signal: Ensure every siginfo we send has all bits initialized
In reply to Eric W. BiedermanCall 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.
--- arch/alpha/kernel/osf_sys.c | 1 + arch/alpha/kernel/signal.c | 2 ++ arch/alpha/kernel/traps.c | 5 +++++ arch/alpha/mm/fault.c | 2 ++ arch/arc/mm/fault.c | 2 ++ arch/arm/kernel/ptrace.c | 1 + arch/arm/kernel/swp_emulate.c | 1 + arch/arm/kernel/traps.c | 5 +++++ arch/arm/mm/alignment.c | 1 + arch/arm/mm/fault.c | 4 ++++ arch/arm/vfp/vfpmodule.c | 3 +-- arch/arm64/kernel/fpsimd.c | 2 +- arch/arm64/kernel/sys_compat.c | 1 + arch/arm64/kernel/traps.c | 1 + arch/arm64/mm/fault.c | 18 ++++++++++++------ arch/c6x/kernel/traps.c | 1 + arch/hexagon/kernel/traps.c | 1 + arch/hexagon/mm/vm_fault.c | 1 + arch/ia64/kernel/brl_emu.c | 1 + arch/ia64/kernel/signal.c | 2 ++ arch/ia64/kernel/traps.c | 27 ++++++++++++++++++++++++--- arch/ia64/kernel/unaligned.c | 1 + arch/ia64/mm/fault.c | 4 +++- arch/m68k/kernel/traps.c | 2 ++ arch/microblaze/kernel/exceptions.c | 1 + arch/microblaze/mm/fault.c | 4 +++- arch/mips/mm/fault.c | 1 + arch/nds32/kernel/traps.c | 3 ++- arch/nds32/mm/fault.c | 1 + arch/nios2/kernel/traps.c | 1 + arch/openrisc/kernel/traps.c | 5 ++++- arch/openrisc/mm/fault.c | 1 + arch/parisc/kernel/ptrace.c | 1 + arch/parisc/kernel/traps.c | 2 ++ arch/parisc/kernel/unaligned.c | 1 + arch/parisc/math-emu/driver.c | 1 + arch/parisc/mm/fault.c | 1 + arch/powerpc/kernel/process.c | 1 + arch/powerpc/kernel/traps.c | 3 +-- arch/powerpc/mm/fault.c | 1 + arch/powerpc/platforms/cell/spufs/fault.c | 2 +- arch/riscv/kernel/traps.c | 1 + arch/s390/kernel/traps.c | 5 ++++- arch/s390/mm/fault.c | 2 ++ arch/sh/kernel/traps_32.c | 2 ++ arch/sh/math-emu/math.c | 1 + arch/sh/mm/fault.c | 1 + arch/sparc/kernel/process_64.c | 1 + arch/sparc/kernel/sys_sparc_32.c | 1 + arch/sparc/kernel/traps_32.c | 10 ++++++++++ arch/sparc/kernel/traps_64.c | 14 ++++++++++++++ arch/sparc/kernel/unaligned_32.c | 1 + arch/sparc/mm/fault_32.c | 1 + arch/sparc/mm/fault_64.c | 1 + arch/um/kernel/trap.c | 2 ++ arch/unicore32/kernel/fpu-ucf64.c | 2 +- arch/unicore32/mm/fault.c | 3 +++ arch/x86/entry/vsyscall/vsyscall_64.c | 2 +- arch/x86/kernel/ptrace.c | 2 +- arch/x86/kernel/traps.c | 3 +++ arch/x86/kernel/umip.c | 1 + arch/x86/kvm/mmu.c | 1 + arch/x86/mm/fault.c | 1 + arch/xtensa/kernel/traps.c | 1 + arch/xtensa/mm/fault.c | 1 + include/linux/ptrace.h | 1 - include/linux/tracehook.h | 1 + virt/kvm/arm/mmu.c | 1 + 68 files changed, 158 insertions(+), 24 deletions(-)
arch/alpha/kernel/osf_sys.c +1 -0
@@ -881,6 +881,7 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,if (fex &IEEE_TRAP_ENABLE_DZE ) si_code =FPE_FLTDIV ;if (fex &IEEE_TRAP_ENABLE_INV ) si_code =FPE_FLTINV ; +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_code = si_code;
arch/alpha/kernel/signal.c +2 -0
@@ -221,6 +221,7 @@ do_sigreturn(struct sigcontext __user *sc)if (ptrace_cancel_bpt (current)) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_BRKPT ;
@@ -255,6 +256,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame)if (ptrace_cancel_bpt (current)) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_BRKPT ;
arch/alpha/kernel/traps.c +5 -0
@@ -228,6 +228,7 @@ do_entArith(unsigned long summary, unsigned long write_mask, }die_if_kernel ("Arithmetic fault" , regs,0 ,NULL ); +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_code = si_code;
@@ -241,6 +242,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)siginfo_t info;int signo, code; +clear_siginfo (&info);if ((regs->ps & ~IPL_MAX ) ==0 ) {if (type ==1 ) {const unsigned int *data
@@ -430,6 +432,7 @@ do_entDbg(struct pt_regs *regs)die_if_kernel ("Instruction fault" , regs,0 ,NULL ); +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLOPC ;
@@ -761,6 +764,8 @@ do_entUnaUser(void __user * va, unsigned long opcode,siginfo_t info;long error; +clear_siginfo (&info); +/* Check the UAC bits to decide what the user wants us to do with the unaliged access. */
arch/alpha/mm/fault.c +2 -0
@@ -91,6 +91,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,siginfo_t info;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; +clear_siginfo (&info); +/* As of EV6, a load into $31/$f31 is a prefetch, and never faults (or is suppressed by the PALcode). Support that for older CPUs by ignoring such an instruction. */
arch/arc/mm/fault.c +2 -0
@@ -70,6 +70,8 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)int write = regs->ecr_cause &ECR_C_PROTV_STORE ;/* ST/EX */ unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; +clear_siginfo (&info); +/* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd.
arch/arm/kernel/ptrace.c +1 -0
@@ -205,6 +205,7 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_BRKPT ;
arch/arm/kernel/swp_emulate.c +1 -0
@@ -112,6 +112,7 @@ static void set_segfault(struct pt_regs *regs, unsigned long addr) {siginfo_t info; +clear_siginfo (&info);down_read (¤t->mm->mmap_sem);if (find_vma (current->mm, addr) ==NULL ) info.si_code =SEGV_MAPERR ;
arch/arm/kernel/traps.c +5 -0
@@ -439,6 +439,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)siginfo_t info;void __user *pc; +clear_siginfo (&info); pc = (void __user *)instruction_pointer (regs);if (processor_mode (regs) ==SVC_MODE ) {
@@ -537,6 +538,7 @@ static int bad_syscall(int n, struct pt_regs *regs) {siginfo_t info; +clear_siginfo (&info);if ((current->personality &PER_MASK ) !=PER_LINUX ) {send_sig (SIGSEGV , current,1 );return regs->ARM_r0;
@@ -604,6 +606,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) {siginfo_t info; +clear_siginfo (&info);if ((no >>16 ) != (__ARM_NR_BASE>>16 ))return bad_syscall (no, regs);
@@ -740,6 +743,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)unsigned long addr =instruction_pointer (regs);siginfo_t info; +clear_siginfo (&info); +#ifdef CONFIG_DEBUG_USER if (user_debug &UDBG_BADABORT ) { pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n",
arch/arm/mm/alignment.c +1 -0
@@ -950,6 +950,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)if (ai_usermode &UM_SIGNAL ) {siginfo_t si; +clear_siginfo (&si); si.si_signo =SIGBUS ; si.si_errno =0 ; si.si_code =BUS_ADRALN ;
arch/arm/mm/fault.c +4 -0
@@ -163,6 +163,8 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, {struct siginfo si; +clear_siginfo (&si); +#ifdef CONFIG_DEBUG_USER if (((user_debug &UDBG_SEGV ) && (sig ==SIGSEGV )) || ((user_debug &UDBG_BUS ) && (sig ==SIGBUS ))) {
@@ -557,6 +559,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) inf->name, fsr, addr);show_pte (current->mm, addr); +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
@@ -589,6 +592,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)pr_alert ("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n" , inf->name, ifsr, addr); +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
arch/arm/vfp/vfpmodule.c +1 -2
@@ -218,8 +218,7 @@ static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) {siginfo_t info; -memset (&info,0 ,sizeof (info)); - +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_code = sicode; info.si_addr = (void __user *)(instruction_pointer (regs) -4 );
arch/arm64/kernel/fpsimd.c +1 -1
@@ -882,7 +882,7 @@ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) si_code =FPE_FLTRES ; } -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_code = si_code; info.si_addr = (void __user *)instruction_pointer (regs);
arch/arm64/kernel/sys_compat.c +1 -0
@@ -112,6 +112,7 @@ long compat_arm_syscall(struct pt_regs *regs)break ; } +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLTRP ;
arch/arm64/kernel/traps.c +1 -0
@@ -634,6 +634,7 @@ asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)siginfo_t info;void __user *pc = (void __user *)instruction_pointer (regs); +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLOPC ;
arch/arm64/mm/fault.c +12 -6
@@ -305,11 +305,12 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re*/ if (user_mode (regs)) {const struct fault_info *inf =esr_to_fault_info (esr); -struct siginfo si = { - .si_signo = inf->sig, - .si_code = inf->code, - .si_addr = (void __user *)addr, - }; +struct siginfo si; + +clear_siginfo (&si); + si.si_signo = inf->sig; + si.si_code = inf->code; + si.si_addr = (void __user *)addr;__do_user_fault (&si, esr); }else {
@@ -583,6 +584,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)nmi_exit (); } +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
@@ -687,6 +689,7 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,show_pte (addr); } +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
@@ -729,6 +732,7 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,local_irq_enable (); } +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
@@ -772,7 +776,6 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, struct pt_regs *regs) {const struct fault_info *inf = debug_fault_info +DBG_ESR_EVT (esr); -struct siginfo info;int rv;/*
@@ -788,6 +791,9 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,if (!inf->fn (addr, esr, regs)) { rv =1 ; }else { +struct siginfo info; + +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
arch/c6x/kernel/traps.c +1 -0
@@ -246,6 +246,7 @@ static void do_trap(struct exception_info *except_info, struct pt_regs *regs)unsigned long addr =instruction_pointer (regs);siginfo_t info; +clear_siginfo (&info);if (except_info->code !=TRAP_BRKPT ) pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n", except_info->kernel_str, regs->pc,
arch/hexagon/kernel/traps.c +1 -0
@@ -414,6 +414,7 @@ void do_trap0(struct pt_regs *regs)if (user_mode (regs)) {struct siginfo info; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ;/*
arch/hexagon/mm/vm_fault.c +1 -0
@@ -56,6 +56,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)const struct exception_table_entry *fixup;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; +clear_siginfo (&info);/* * If we're in an interrupt or have no user context, * then must not take the fault.
arch/ia64/kernel/brl_emu.c +1 -0
@@ -62,6 +62,7 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)struct illegal_op_return rv;long tmp_taken, unimplemented_address; +clear_siginfo (&siginfo); rv.fkt = (unsigned long )-1 ;/*
arch/ia64/kernel/signal.c +2 -0
@@ -153,6 +153,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)return retval; give_sigsegv: +clear_siginfo (&si); si.si_signo =SIGSEGV ; si.si_errno =0 ; si.si_code =SI_KERNEL ;
@@ -236,6 +237,7 @@ force_sigsegv_info (int sig, void __user *addr)unsigned long flags;struct siginfo si; +clear_siginfo (&si);if (sig ==SIGSEGV ) {/* * Acquiring siglock around the sa_handler-update is almost
arch/ia64/kernel/traps.c +24 -3
@@ -104,6 +104,7 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)int sig, code;/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ +clear_siginfo (&siginfo); siginfo.si_addr = (void __user *) (regs->cr_iip +ia64_psr (regs)->ri); siginfo.si_imm = break_num; siginfo.si_flags =0 ;/* clear __ISR_VALID */
@@ -293,7 +294,6 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) {long exception, bundle[2 ];unsigned long fault_ip; -struct siginfo siginfo; fault_ip = regs->cr_iip;if (!fp_fault && (ia64_psr (regs)->ri ==0 ))
@@ -344,10 +344,13 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)printk (KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n" );return -1 ; }else { +struct siginfo siginfo; +/* is next instruction a trap? */ if (exception &2 ) {ia64_increment_ip (regs); } +clear_siginfo (&siginfo); siginfo.si_signo =SIGFPE ; siginfo.si_errno =0 ; siginfo.si_code =FPE_FIXME ;/* default code */
@@ -372,6 +375,9 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)return -1 ; }else if (exception !=0 ) {/* raise exception */ +struct siginfo siginfo; + +clear_siginfo (&siginfo); siginfo.si_signo =SIGFPE ; siginfo.si_errno =0 ; siginfo.si_code =FPE_FIXME ;/* default code */
@@ -420,7 +426,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,if (die_if_kernel (buf, ®s,0 ))return rv; -memset (&si,0 ,sizeof (si)); +clear_siginfo (&si); si.si_signo =SIGILL ; si.si_code =ILL_ILLOPC ; si.si_addr = (void __user *) (regs.cr_iip +ia64_psr (®s)->ri);
@@ -434,7 +440,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, long arg7, struct pt_regs regs) {unsigned long code, error = isr, iip; -struct siginfo siginfo;char buf[128 ];int result, sig;static const char *reason[] = {
@@ -485,6 +490,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,case 26 :/* NaT Consumption */ if (user_mode (®s)) { +struct siginfo siginfo;void __user *addr;if (((isr >>4 ) &0xf ) ==2 ) {
@@ -499,6 +505,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, addr = (void __user *) (regs.cr_iip +ia64_psr (®s)->ri); } +clear_siginfo (&siginfo); siginfo.si_signo = sig; siginfo.si_code = code; siginfo.si_errno =0 ;
@@ -515,6 +522,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,case 31 :/* Unsupported Data Reference */ if (user_mode (®s)) { +struct siginfo siginfo; + +clear_siginfo (&siginfo); siginfo.si_signo =SIGILL ; siginfo.si_code =ILL_ILLOPN ; siginfo.si_errno =0 ;
@@ -531,6 +541,10 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,case 29 :/* Debug */ case 35 :/* Taken Branch Trap */ case 36 :/* Single Step Trap */ + { +struct siginfo siginfo; + +clear_siginfo (&siginfo);if (fsys_mode (current, ®s)) {extern char __kernel_syscall_via_break[];/*
@@ -578,11 +592,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, siginfo.si_isr = isr;force_sig_info (SIGTRAP , &siginfo, current);return ; + }case 32 :/* fp fault */ case 33 :/* fp trap */ result =handle_fpu_swa ((vector ==32 ) ?1 :0 , ®s, isr);if ((result <0 ) || (current->thread.flags &IA64_THREAD_FPEMU_SIGFPE )) { +struct siginfo siginfo; + +clear_siginfo (&siginfo); siginfo.si_signo =SIGFPE ; siginfo.si_errno =0 ; siginfo.si_code =FPE_FLTINV ;
@@ -616,6 +634,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, }else {/* Unimplemented Instr. Address Trap */ if (user_mode (®s)) { +struct siginfo siginfo; + +clear_siginfo (&siginfo); siginfo.si_signo =SIGILL ; siginfo.si_code =ILL_BADIADDR ; siginfo.si_errno =0 ;
arch/ia64/kernel/unaligned.c +1 -0
@@ -1537,6 +1537,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)/* NOT_REACHED */ } force_sigbus: +clear_siginfo (&si); si.si_signo =SIGBUS ; si.si_errno =0 ; si.si_code =BUS_ADRALN ;
arch/ia64/mm/fault.c +3 -1
@@ -85,7 +85,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *reint signal =SIGSEGV , code =SEGV_MAPERR ;struct vm_area_struct *vma, *prev_vma;struct mm_struct *mm = current->mm; -struct siginfo si;unsigned long mask;int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ;
@@ -249,6 +248,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *rereturn ; }if (user_mode (regs)) { +struct siginfo si; + +clear_siginfo (&si); si.si_signo = signal; si.si_errno =0 ; si.si_code = code;
arch/m68k/kernel/traps.c +2 -0
@@ -1011,6 +1011,7 @@ asmlinkage void trap_c(struct frame *fp)int vector = (fp->ptregs.vector >>2 ) &0xff ;siginfo_t info; +clear_siginfo (&info);if (fp->ptregs.sr &PS_S ) {if (vector ==VEC_TRACE ) {/* traced a trapping instruction on a 68020/30,
@@ -1163,6 +1164,7 @@ asmlinkage void fpemu_signal(int signal, int code, void *addr) {siginfo_t info; +clear_siginfo (&info); info.si_signo = signal; info.si_errno =0 ; info.si_code = code;
arch/microblaze/kernel/exceptions.c +1 -0
@@ -65,6 +65,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)if (kernel_mode (regs))die ("Exception in kernel mode" , regs, signr); +clear_siginfo (&info); info.si_signo = signr; info.si_errno =0 ; info.si_code = code;
arch/microblaze/mm/fault.c +3 -1
@@ -88,7 +88,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, {struct vm_area_struct *vma;struct mm_struct *mm = current->mm; -siginfo_t info;int code =SEGV_MAPERR ;int is_write = error_code &ESR_S ;int fault;
@@ -295,6 +294,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, do_sigbus:up_read (&mm->mmap_sem);if (user_mode (regs)) { +siginfo_t info; + +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRERR ;
arch/mips/mm/fault.c +1 -0
@@ -63,6 +63,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,return ;#endif +clear_siginfo (&info); info.si_code =SEGV_MAPERR ;/*
arch/nds32/kernel/traps.c +2 -1
@@ -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);
arch/nds32/mm/fault.c +1 -0
@@ -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;
arch/nios2/kernel/traps.c +1 -0
@@ -28,6 +28,7 @@ static void _send_sig(int signo, int code, unsigned long addr) {siginfo_t info; +clear_siginfo (&info); info.si_signo = signo; info.si_errno =0 ; info.si_code = code;
arch/openrisc/kernel/traps.c +4 -1
@@ -251,7 +251,7 @@ void __init trap_init(void) asmlinkage void do_trap(struct pt_regs *regs, unsigned long address) {siginfo_t info; -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_code =TRAP_TRACE ; info.si_addr = (void *)address;
@@ -266,6 +266,7 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)if (user_mode (regs)) {/* Send a SIGBUS */ +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
@@ -285,6 +286,7 @@ asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)if (user_mode (regs)) {/* Send a SIGBUS */ +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRERR ;
@@ -485,6 +487,7 @@ asmlinkage void do_illegal_instruction(struct pt_regs *regs,if (user_mode (regs)) {/* Send a SIGILL */ +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLOPC ;
arch/openrisc/mm/fault.c +1 -0
@@ -56,6 +56,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; +clear_siginfo (&info); tsk = current;/*
arch/parisc/kernel/ptrace.c +1 -0
@@ -90,6 +90,7 @@ void user_enable_single_step(struct task_struct *task)ptrace_disable (task);/* Don't wake up the task, but let the parent know something happened. */ +clear_siginfo (&si); si.si_code =TRAP_TRACE ; si.si_addr = (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ); si.si_signo =SIGTRAP ;
arch/parisc/kernel/traps.c +2 -0
@@ -299,6 +299,7 @@ static void handle_gdb_break(struct pt_regs *regs, int wot) {struct siginfo si; +clear_siginfo (&si); si.si_signo =SIGTRAP ; si.si_errno =0 ; si.si_code = wot;
@@ -489,6 +490,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)unsigned long fault_space =0 ;struct siginfo si; +clear_siginfo (&si);if (code ==1 )pdc_console_restart ();/* switch back to pdc if HPMC */ else
arch/parisc/kernel/unaligned.c +1 -0
@@ -455,6 +455,7 @@ void handle_unaligned(struct pt_regs *regs)struct siginfo si; registerint flop=0 ;/* true if this is a flop */ +clear_siginfo (&si);__inc_irq_stat (irq_unaligned_count);/* log a message with pacing */
arch/parisc/math-emu/driver.c +1 -0
@@ -93,6 +93,7 @@ handle_fpe(struct pt_regs *regs)*/ __u64 frcopy[36 ]; +clear_siginfo (&si);memcpy (frcopy, regs->fr,sizeof regs->fr); frcopy[32 ] =0 ;
arch/parisc/mm/fault.c +1 -0
@@ -356,6 +356,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,struct siginfo si;unsigned int lsb =0 ; +clear_siginfo (&si);switch (code) {case 15 :/* Data TLB miss fault/Data page fault */ /* send SIGSEGV when outside of vma */
arch/powerpc/kernel/process.c +1 -0
@@ -632,6 +632,7 @@ void do_break (struct pt_regs *regs, unsigned long address,hw_breakpoint_disable ();/* Deliver the signal to userspace */ +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_HWBKPT ;
arch/powerpc/kernel/traps.c +1 -2
@@ -296,7 +296,6 @@ NOKPROBE_SYMBOL(die);void user_single_step_siginfo (struct task_struct *tsk,struct pt_regs *regs,siginfo_t *info) { -memset (info,0 ,sizeof (*info)); info->si_signo =SIGTRAP ; info->si_code =TRAP_TRACE ; info->si_addr = (void __user *)regs->nip;
@@ -334,7 +333,7 @@ void _exception_pkey(int signr, struct pt_regs *regs, int code,*/ thread_pkey_regs_save (¤t->thread); -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info); info.si_signo = signr; info.si_code = code; info.si_addr = (void __user *) addr;
arch/powerpc/mm/fault.c +1 -0
@@ -168,6 +168,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,return SIGBUS ; current->thread.trap_nr =BUS_ADRERR ; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRERR ;
arch/powerpc/platforms/cell/spufs/fault.c +1 -1
@@ -44,7 +44,7 @@ static void spufs_handle_event(struct spu_context *ctx,return ; } -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info);switch (type) {case SPE_EVENT_INVALID_DMA :
arch/riscv/kernel/traps.c +1 -0
@@ -68,6 +68,7 @@ static inline void do_trap_siginfo(int signo, int code, {siginfo_t info; +clear_siginfo (&info); info.si_signo = signo; info.si_errno =0 ; info.si_code = code;
arch/s390/kernel/traps.c +4 -1
@@ -47,6 +47,7 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)siginfo_t info;if (user_mode (regs)) { +clear_siginfo (&info); info.si_signo = si_signo; info.si_errno =0 ; info.si_code = si_code;
@@ -86,6 +87,7 @@ void do_per_trap(struct pt_regs *regs)return ;if (!current->ptrace)return ; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_HWBKPT ;
@@ -165,7 +167,6 @@ void translation_exception(struct pt_regs *regs)void illegal_op (struct pt_regs *regs) { -siginfo_t info;__u8 opcode[6 ];__u16 __user *location;int is_uprobe_insn =0 ;
@@ -178,6 +179,8 @@ void illegal_op(struct pt_regs *regs)return ;if (*((__u16 *) opcode) ==S390_BREAKPOINT_U16 ) {if (current->ptrace) { +siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_BRKPT ;
arch/s390/mm/fault.c +2 -0
@@ -268,6 +268,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code)struct siginfo si;report_user_fault (regs,SIGSEGV ,1 ); +clear_siginfo (&si); si.si_signo =SIGSEGV ; si.si_errno =0 ; si.si_code = si_code;
@@ -323,6 +324,7 @@ static noinline void do_sigbus(struct pt_regs *regs)* Send a sigbus, regardless of whether we were in kernel * or user mode. */ +clear_siginfo (&si); si.si_signo =SIGBUS ; si.si_errno =0 ; si.si_code =BUS_ADRERR ;
arch/sh/kernel/traps_32.c +2 -0
@@ -537,6 +537,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,"access (PC %lx PR %lx)\n" , current->comm, regs->pc, regs->pr); +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code = si_code;
@@ -600,6 +601,7 @@ asmlinkage void do_divide_error(unsigned long r4) {siginfo_t info; +clear_siginfo (&info);switch (r4) {case TRAP_DIVZERO_ERROR : info.si_code =FPE_INTDIV ;
arch/sh/math-emu/math.c +1 -0
@@ -560,6 +560,7 @@ static int ieee_fpe_handler(struct pt_regs *regs) ~(FPSCR_CAUSE_MASK |FPSCR_FLAG_MASK );task_thread_info (tsk)->status |=TS_USEDFPU ; }else { +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_code =FPE_FLTINV ;
arch/sh/mm/fault.c +1 -0
@@ -44,6 +44,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address, {siginfo_t info; +clear_siginfo (&info); info.si_signo = si_signo; info.si_errno =0 ; info.si_code = si_code;
arch/sparc/kernel/process_64.c +1 -0
@@ -520,6 +520,7 @@ static void stack_unaligned(unsigned long sp) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
arch/sparc/kernel/sys_sparc_32.c +1 -0
@@ -152,6 +152,7 @@ sparc_breakpoint (struct pt_regs *regs)#ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%x, nPC=%x\n" , regs->pc, regs->npc);#endif +clear_siginfo (&info); info.si_signo =SIGTRAP ; info.si_errno =0 ; info.si_code =TRAP_BRKPT ;
arch/sparc/kernel/traps_32.c +10 -0
@@ -104,6 +104,7 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type)if (regs->psr &PSR_PS )die_if_kernel ("Kernel bad trap" , regs); +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLTRP ;
@@ -124,6 +125,7 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon regs->pc, *(unsigned long *)regs->pc);#endif +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLOPC ;
@@ -139,6 +141,7 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long nif (psr &PSR_PS )die_if_kernel ("Penguin instruction from Penguin mode??!?!" , regs); +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_PRVOPC ;
@@ -165,6 +168,7 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned loninstruction_dump ((unsigned long *) regs->pc);printk ("do_MNA!\n" );#endif +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
@@ -303,6 +307,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, } fsr = fpt->thread.fsr; +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_addr = (void __user *)pc;
@@ -336,6 +341,7 @@ void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long nif (psr &PSR_PS )die_if_kernel ("Penguin overflow trap from kernel mode" , regs); +clear_siginfo (&info); info.si_signo =SIGEMT ; info.si_errno =0 ; info.si_code =EMT_TAGOVF ;
@@ -365,6 +371,7 @@ void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npcprintk ("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n" , pc, npc, psr);#endif +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_OBJERR ;
@@ -378,6 +385,7 @@ void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long np {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_COPROC ;
@@ -395,6 +403,7 @@ void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long nprintk ("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n" , pc, npc, psr);#endif +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_COPROC ;
@@ -408,6 +417,7 @@ void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_code =FPE_INTDIV ;
arch/sparc/kernel/traps_64.c +14 -0
@@ -107,6 +107,7 @@ void bad_trap(struct pt_regs *regs, long lvl) regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLTRP ;
@@ -206,6 +207,7 @@ void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, un regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGSEGV ; info.si_errno =0 ; info.si_code =SEGV_MAPERR ;
@@ -247,6 +249,7 @@ void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsig regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGSEGV ; info.si_errno =0 ; info.si_code =SEGV_MAPERR ;
@@ -338,6 +341,7 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unif (is_no_fault_exception (regs))return ; +clear_siginfo (&info); info.si_signo =SIGSEGV ; info.si_errno =0 ; info.si_code =SEGV_MAPERR ;
@@ -595,6 +599,7 @@ static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned lon regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_OBJERR ;
@@ -2211,6 +2216,7 @@ bool sun4v_nonresum_error_user_handled(struct pt_regs *regs, addr +=PAGE_SIZE ; } } +clear_siginfo (&info); info.si_signo =SIGKILL ; info.si_errno =0 ; info.si_trapno =0 ;
@@ -2221,6 +2227,7 @@ bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,if (attrs &SUN4V_ERR_ATTRS_PIO ) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_code =BUS_ADRERR ; info.si_addr = (void __user *)sun4v_get_vaddr (regs);
@@ -2368,6 +2375,7 @@ static void do_fpe_common(struct pt_regs *regs) regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_addr = (void __user *)regs->tpc;
@@ -2440,6 +2448,7 @@ void do_tof(struct pt_regs *regs) regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGEMT ; info.si_errno =0 ; info.si_code =EMT_TAGOVF ;
@@ -2465,6 +2474,7 @@ void do_div0(struct pt_regs *regs) regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_code =FPE_INTDIV ;
@@ -2666,6 +2676,7 @@ void do_illegal_instruction(struct pt_regs *regs) } } } +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_ILLOPC ;
@@ -2692,6 +2703,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned loif (is_no_fault_exception (regs))return ; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
@@ -2717,6 +2729,7 @@ void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_cif (is_no_fault_exception (regs))return ; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
@@ -2785,6 +2798,7 @@ void do_privop(struct pt_regs *regs) regs->tpc &=0xffffffff ; regs->tnpc &=0xffffffff ; } +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_PRVOPC ;
arch/sparc/kernel/unaligned_32.c +1 -0
@@ -313,6 +313,7 @@ static void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
arch/sparc/mm/fault_32.c +1 -0
@@ -129,6 +129,7 @@ static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs, {siginfo_t info; +clear_siginfo (&info); info.si_signo = sig; info.si_code = code; info.si_errno =0 ;
arch/sparc/mm/fault_64.c +1 -0
@@ -172,6 +172,7 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,unsigned long addr;siginfo_t info; +clear_siginfo (&info); info.si_code = code; info.si_signo = sig; info.si_errno =0 ;
arch/um/kernel/trap.c +2 -0
@@ -164,6 +164,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) {struct siginfo si; +clear_siginfo (&si); si.si_signo =SIGSEGV ; si.si_code =SEGV_ACCERR ; si.si_addr = (void __user *)FAULT_ADDRESS (fi);
@@ -220,6 +221,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,int is_write =FAULT_WRITE (fi);unsigned long address =FAULT_ADDRESS (fi); +clear_siginfo (&si);if (!is_user && regs) current->thread.segv_regs = container_of(regs, struct pt_regs, regs);
arch/unicore32/kernel/fpu-ucf64.c +1 -1
@@ -56,7 +56,7 @@ void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) {siginfo_t info; -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_code = sicode;
arch/unicore32/mm/fault.c +3 -0
@@ -125,6 +125,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, tsk->thread.address = addr; tsk->thread.error_code = fsr; tsk->thread.trap_no =14 ; +clear_siginfo (&si); si.si_signo = sig; si.si_errno =0 ; si.si_code = code;
@@ -472,6 +473,7 @@ asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,printk (KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n" , inf->name, fsr, addr); +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
@@ -491,6 +493,7 @@ asmlinkage void do_PrefetchAbort(unsigned long addr,printk (KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n" , inf->name, ifsr, addr); +clear_siginfo (&info); info.si_signo = inf->sig; info.si_errno =0 ; info.si_code = inf->code;
arch/x86/entry/vsyscall/vsyscall_64.c +1 -1
@@ -107,7 +107,7 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size) thread->cr2 = ptr; thread->trap_nr =X86_TRAP_PF ; -memset (&info,0 ,sizeof (info)); +clear_siginfo (&info); info.si_signo =SIGSEGV ; info.si_errno =0 ; info.si_code =SEGV_MAPERR ;
arch/x86/kernel/ptrace.c +1 -1
@@ -1377,7 +1377,6 @@ static void fill_sigtrap_info(struct task_struct *tsk, tsk->thread.trap_nr =X86_TRAP_DB ; tsk->thread.error_code = error_code; -memset (info,0 ,sizeof (*info)); info->si_signo =SIGTRAP ; info->si_code = si_code; info->si_addr =user_mode (regs) ? (void __user *)regs->ip :NULL ;
@@ -1395,6 +1394,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, {struct siginfo info; +clear_siginfo (&info);fill_sigtrap_info (tsk, regs, error_code, si_code, &info);/* Send us the fake SIGTRAP */ force_sig_info (SIGTRAP , &info, tsk);
arch/x86/kernel/traps.c +3 -0
@@ -299,6 +299,7 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str,if (notify_die (DIE_TRAP , str, regs, error_code, trapnr, signr) !=NOTIFY_STOP ) {cond_local_irq_enable (regs); +clear_siginfo (&info);do_trap (trapnr, signr, str, regs, error_code,fill_trap_info (regs, signr, trapnr, &info)); }
@@ -854,6 +855,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) task->thread.trap_nr = trapnr; task->thread.error_code = error_code; +clear_siginfo (&info); info.si_signo =SIGFPE ; info.si_errno =0 ; info.si_addr = (void __user *)uprobe_get_trap_addr (regs);
@@ -929,6 +931,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)RCU_LOCKDEP_WARN (!rcu_is_watching (),"entry code didn't wake RCU" );local_irq_enable (); +clear_siginfo (&info); info.si_signo =SIGILL ; info.si_errno =0 ; info.si_code =ILL_BADSTK ;
arch/x86/kernel/umip.c +1 -0
@@ -278,6 +278,7 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) tsk->thread.error_code =X86_PF_USER |X86_PF_WRITE ; tsk->thread.trap_nr =X86_TRAP_PF ; +clear_siginfo (&info); info.si_signo =SIGSEGV ; info.si_errno =0 ; info.si_code =SEGV_MAPERR ;
arch/x86/kvm/mmu.c +1 -0
@@ -3007,6 +3007,7 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct * {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_MCEERR_AR ;
arch/x86/mm/fault.c +1 -0
@@ -209,6 +209,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,unsigned lsb =0 ;siginfo_t info; +clear_siginfo (&info); info.si_signo = si_signo; info.si_errno =0 ; info.si_code = si_code;
arch/xtensa/kernel/traps.c +1 -0
@@ -334,6 +334,7 @@ do_unaligned_user (struct pt_regs *regs)"(pid = %d, pc = %#010lx)\n" , regs->excvaddr, current->comm, task_pid_nr(current), regs->pc); +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_ADRALN ;
arch/xtensa/mm/fault.c +1 -0
@@ -45,6 +45,7 @@ void do_page_fault(struct pt_regs *regs)int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; +clear_siginfo (&info); info.si_code =SEGV_MAPERR ;/* We fault-in kernel-space virtual memory on-demand. The
include/linux/ptrace.h +0 -1
@@ -345,7 +345,6 @@ extern void user_single_step_siginfo(struct task_struct *tsk,static inline void user_single_step_siginfo (struct task_struct *tsk,struct pt_regs *regs,siginfo_t *info) { -memset (info,0 ,sizeof (*info)); info->si_signo =SIGTRAP ; }#endif
include/linux/tracehook.h +1 -0
@@ -124,6 +124,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) {if (step) {siginfo_t info; +clear_siginfo (&info);user_single_step_siginfo (current, regs, &info);force_sig_info (SIGTRAP , &info, current);return ;
virt/kvm/arm/mmu.c +1 -0
@@ -1401,6 +1401,7 @@ static void kvm_send_hwpoison_signal(unsigned long address, {siginfo_t info; +clear_siginfo (&info); info.si_signo =SIGBUS ; info.si_errno =0 ; info.si_code =BUS_MCEERR_AR ;
Signature · 1 line
2.14.1
PATCH 7/17 signal: Reduce copy_siginfo_to_user to just copy_to_user
In reply to Eric W. BiedermanNow that every instance of struct siginfo is now initialized it is no longer necessary to copy struct siginfo piece by piece to userspace but instead the entire structure can be copied.
As well as making the code simpler and more efficient this means that copy_sinfo_to_user no longer cares which union member of struct siginfo is in use.
In practice this means that all 32bit architectures that define FPE_FIXME will handle properly send SI_USER when kill(SIGFPE) is sent. While still performing their historic architectural brokenness when 0 is used a floating pointer signal. This matches the current behavior of 64bit architectures that define FPE_FIXME who get lucky and an overloaded SI_USER has continuted to work through copy_siginfo_to_user because the 8 byte si_addr occupies the same bytes in struct siginfo as the 4 byte si_pid and the 4 byte si_uid.
Problematic architectures still need to fix their ABI so that signalfd and 32bit compat code will work properly.
--- kernel/signal.c | 84 ++------------------------------------------------------- 1 file changed, 2 insertions(+), 82 deletions(-)
kernel/signal.c +2 -82
@@ -2850,89 +2850,9 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)int copy_siginfo_to_user (siginfo_t __user *to,const siginfo_t *from) { -int err; - -if (!access_ok (VERIFY_WRITE , to,sizeof (siginfo_t))) +if (copy_to_user (to, from ,sizeof (struct siginfo )))return -EFAULT ; -if (from->si_code <0 ) -return __copy_to_user (to, from,sizeof (siginfo_t)) - ? -EFAULT :0 ; -/* -* If you change siginfo_t structure, please be sure -* this code is fixed accordingly. -* Please remember to update the signalfd_copyinfo() function -* inside fs/signalfd.c too, in case siginfo_t changes. -* It should never copy any pad contained in the structure -* to avoid security leaks, but must copy the generic -* 3 ints plus the relevant union member. -*/ - err =__put_user (from->si_signo, &to->si_signo); - err |=__put_user (from->si_errno, &to->si_errno); - err |=__put_user (from->si_code, &to->si_code); -switch (siginfo_layout (from->si_signo, from->si_code)) { -case SIL_KILL : - err |=__put_user (from->si_pid, &to->si_pid); - err |=__put_user (from->si_uid, &to->si_uid); -break ; -case SIL_TIMER : -/* Unreached SI_TIMER is negative */ -break ; -case SIL_POLL : - err |=__put_user (from->si_band, &to->si_band); - err |=__put_user (from->si_fd, &to->si_fd); -break ; -case SIL_FAULT : - err |=__put_user (from->si_addr, &to->si_addr); -#ifdef __ARCH_SI_TRAPNO - err |=__put_user (from->si_trapno, &to->si_trapno); -#endif -#ifdef __ia64__ - err |=__put_user (from->si_imm, &to->si_imm); - err |=__put_user (from->si_flags, &to->si_flags); - err |=__put_user (from->si_isr, &to->si_isr); -#endif -/* -* Other callers might not initialize the si_lsb field, -* so check explicitly for the right codes here. -*/ -#ifdef BUS_MCEERR_AR -if (from->si_signo ==SIGBUS && from->si_code ==BUS_MCEERR_AR ) - err |=__put_user (from->si_addr_lsb, &to->si_addr_lsb); -#endif -#ifdef BUS_MCEERR_AO -if (from->si_signo ==SIGBUS && from->si_code ==BUS_MCEERR_AO ) - err |=__put_user (from->si_addr_lsb, &to->si_addr_lsb); -#endif -#ifdef SEGV_BNDERR -if (from->si_signo ==SIGSEGV && from->si_code ==SEGV_BNDERR ) { - err |=__put_user (from->si_lower, &to->si_lower); - err |=__put_user (from->si_upper, &to->si_upper); - } -#endif -#ifdef SEGV_PKUERR -if (from->si_signo ==SIGSEGV && from->si_code ==SEGV_PKUERR ) - err |=__put_user (from->si_pkey, &to->si_pkey); -#endif -break ; -case SIL_CHLD : - err |=__put_user (from->si_pid, &to->si_pid); - err |=__put_user (from->si_uid, &to->si_uid); - err |=__put_user (from->si_status, &to->si_status); - err |=__put_user (from->si_utime, &to->si_utime); - err |=__put_user (from->si_stime, &to->si_stime); -break ; -case SIL_RT : - err |=__put_user (from->si_pid, &to->si_pid); - err |=__put_user (from->si_uid, &to->si_uid); - err |=__put_user (from->si_ptr, &to->si_ptr); -break ; -case SIL_SYS : - err |=__put_user (from->si_call_addr, &to->si_call_addr); - err |=__put_user (from->si_syscall, &to->si_syscall); - err |=__put_user (from->si_arch, &to->si_arch); -break ; - } -return err; +return 0 ; }#ifdef CONFIG_COMPAT
Signature · 1 line
2.14.1
PATCH 8/17 signal: Stop special casing TRAP_FIXME and FPE_FIXME in siginfo_layout
In reply to Eric W. BiedermanAfter more experience with the cases where no one the si_code of 0 is used both as a signal specific si_code, and as SI_USER it appears that no one cares about the signal specific si_code case and the good solution is to just fix the architectures by using
a different si_code.
In none of the conversations has anyone even suggested that anything depends on the signal specific redefinition of SI_USER.
There are at least test cases that care when si_code as 0 does not work as si_user.
So make things simple and keep the generic code from introducing problems by removing the special casing of TRAP_FIXME and FPE_FIXME. This will ensure the generic case of sending a signal with kill will always set SI_USER and work.
The architecture specific, and signal specific overloads that set si_code to 0 will now have problems with signalfd and
the 32bit compat versions of siginfo copying. At least
until they are fixed.
--- kernel/signal.c | 9 --------- 1 file changed, 9 deletions(-)
kernel/signal.c +0 -9
@@ -2835,15 +2835,6 @@ enum siginfo_layout siginfo_layout(int sig, int si_code) layout =SIL_POLL ; else if (si_code < 0) layout =SIL_RT ; -/* Tests to support buggy kernel ABIs */ -#ifdef TRAP_FIXME -if ((sig ==SIGTRAP ) && (si_code ==TRAP_FIXME )) - layout =SIL_FAULT ; -#endif -#ifdef FPE_FIXME -if ((sig ==SIGFPE ) && (si_code ==FPE_FIXME )) - layout =SIL_FAULT ; -#endif }return layout; }
Signature · 1 line
2.14.1
PATCH 9/17 signal: Remove SEGV_BNDERR ifdefs
In reply to Eric W. BiedermanAfter the last round of cleanups to siginfo.h SEGV_BNDERR is defined on all architectures so testing to see if it is defined is unnecessary.
--- kernel/signal.c | 6 ------ 1 file changed, 6 deletions(-)
kernel/signal.c +0 -6
@@ -1570,7 +1570,6 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *EXPORT_SYMBOL (send_sig_mceerr);#endif -#ifdef SEGV_BNDERR int force_sig_bnderr (void __user *addr,void __user *lower,void __user *upper) {struct siginfo info;
@@ -1584,7 +1583,6 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper) info.si_upper = upper;return force_sig_info (info.si_signo, &info, current); } -#endif #ifdef SEGV_PKUERR int force_sig_pkuerr (void __user *addr,u32 pkey)
@@ -2890,13 +2888,11 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,if ((from->si_signo ==SIGBUS ) && (from->si_code ==BUS_MCEERR_AO )) new.si_addr_lsb = from->si_addr_lsb;#endif -#ifdef SEGV_BNDERR if ((from->si_signo ==SIGSEGV ) && (from->si_code ==SEGV_BNDERR )) { new.si_lower =ptr_to_compat (from->si_lower); new.si_upper =ptr_to_compat (from->si_upper); } -#endif #ifdef SEGV_PKUERR if ((from->si_signo ==SIGSEGV ) && (from->si_code ==SEGV_PKUERR ))
@@ -2976,12 +2972,10 @@ int copy_siginfo_from_user32(struct siginfo *to,if ((from.si_signo ==SIGBUS ) && (from.si_code ==BUS_MCEERR_AO )) to->si_addr_lsb = from.si_addr_lsb;#endif -#ifdef SEGV_BNDERR if ((from.si_signo ==SIGSEGV ) && (from.si_code ==SEGV_BNDERR )) { to->si_lower =compat_ptr (from.si_lower); to->si_upper =compat_ptr (from.si_upper); } -#endif #ifdef SEGV_PKUERR if ((from.si_signo ==SIGSEGV ) && (from.si_code ==SEGV_PKUERR )) to->si_pkey = from.si_pkey;
Signature · 1 line
2.14.1
PATCH 10/17 signal: Remove ifdefs for BUS_MCEERR_AR and BUS_MCEERR_AO
In reply to Eric W. BiedermanWith the recent architecture cleanups these si_codes are always defined so there is no need to test for them.
--- fs/signalfd.c | 15 ++------------- kernel/signal.c | 24 ++++++++---------------- 2 files changed, 10 insertions(+), 29 deletions(-)
fs/signalfd.c +2 -13
@@ -117,26 +117,15 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,#ifdef __ARCH_SI_TRAPNO err |=__put_user (kinfo->si_trapno, &uinfo->ssi_trapno);#endif -#ifdef BUS_MCEERR_AO /* * Other callers might not initialize the si_lsb field, * so check explicitly for the right codes here. */ if (kinfo->si_signo ==SIGBUS && - kinfo->si_code ==BUS_MCEERR_AO ) + ((kinfo->si_code ==BUS_MCEERR_AR ) || + (kinfo->si_code ==BUS_MCEERR_AO ))) err |=__put_user ((short ) kinfo->si_addr_lsb, &uinfo->ssi_addr_lsb); -#endif -#ifdef BUS_MCEERR_AR -/* -* Other callers might not initialize the si_lsb field, -* so check explicitly for the right codes here. -*/ -if (kinfo->si_signo ==SIGBUS && - kinfo->si_code ==BUS_MCEERR_AR ) - err |=__put_user ((short ) kinfo->si_addr_lsb, - &uinfo->ssi_addr_lsb); -#endif break ;case SIL_CHLD : err |=__put_user (kinfo->si_pid, &uinfo->ssi_pid);
kernel/signal.c +8 -16
@@ -1539,7 +1539,6 @@ int send_sig_fault(int sig, int code, void __user *addrreturn send_sig_info (info.si_signo, &info, t); } -#if defined(BUS_MCEERR_AO ) && defined(BUS_MCEERR_AR )int force_sig_mceerr (int code,void __user *addr,short lsb,struct task_struct *t) {struct siginfo info;
@@ -1568,7 +1567,6 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *return send_sig_info (info.si_signo, &info, t); }EXPORT_SYMBOL (send_sig_mceerr); -#endif int force_sig_bnderr (void __user *addr,void __user *lower,void __user *upper) {
@@ -2880,14 +2878,11 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,#ifdef __ARCH_SI_TRAPNO new.si_trapno = from->si_trapno;#endif -#ifdef BUS_MCEERR_AR -if ((from->si_signo ==SIGBUS ) && (from->si_code ==BUS_MCEERR_AR )) - new.si_addr_lsb = from->si_addr_lsb; -#endif -#ifdef BUS_MCEERR_AO -if ((from->si_signo ==SIGBUS ) && (from->si_code ==BUS_MCEERR_AO )) +if ((from->si_signo ==SIGBUS ) && + ((from->si_code ==BUS_MCEERR_AR ) || + (from->si_code ==BUS_MCEERR_AO ))) new.si_addr_lsb = from->si_addr_lsb; -#endif +if ((from->si_signo ==SIGSEGV ) && (from->si_code ==SEGV_BNDERR )) { new.si_lower =ptr_to_compat (from->si_lower);
@@ -2964,14 +2959,11 @@ int copy_siginfo_from_user32(struct siginfo *to,#ifdef __ARCH_SI_TRAPNO to->si_trapno = from.si_trapno;#endif -#ifdef BUS_MCEERR_AR -if ((from.si_signo ==SIGBUS ) && (from.si_code ==BUS_MCEERR_AR )) +if ((from.si_signo ==SIGBUS ) && + ((from.si_code ==BUS_MCEERR_AR ) || + (from.si_code ==BUS_MCEERR_AO ))) to->si_addr_lsb = from.si_addr_lsb; -#endif -#ifdef BUS_MCEER_AO -if ((from.si_signo ==SIGBUS ) && (from.si_code ==BUS_MCEERR_AO )) - to->si_addr_lsb = from.si_addr_lsb; -#endif +if ((from.si_signo ==SIGSEGV ) && (from.si_code ==SEGV_BNDERR )) { to->si_lower =compat_ptr (from.si_lower); to->si_upper =compat_ptr (from.si_upper);
Signature · 1 line
2.14.1
PATCH 11/17 signal/alpha: Replace FPE_FIXME with FPE_FLTUNK
In reply to Eric W. BiedermanUsing an si_code of 0 that aliases with SI_USER is clearly the wrong thing todo, and causes problems in interesting ways.
The newly defined FPE_FLTUNK semantically appears to fit the bill so use it instead.
Given recent experience in this area odds are it will not break anything. Fixing it removes a hazard to kernel maintenance.
Cc: Helge Deller <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Ivan Kokshaysky <[email protected]>
Cc: Matt Turner <[email protected]>
Cc: [email protected]
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
--- arch/alpha/include/uapi/asm/siginfo.h | 7 ------- arch/alpha/kernel/osf_sys.c | 2 +- arch/alpha/kernel/traps.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-)
arch/alpha/include/uapi/asm/siginfo.h +0 -7
@@ -7,13 +7,6 @@#include <asm-generic/siginfo.h> -/* -* SIGFPE si_codes -*/ -#ifdef __KERNEL__ -#define FPE_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ -/* * SIGTRAP si_codes */
arch/alpha/kernel/osf_sys.c +1 -1
@@ -872,7 +872,7 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer, fex = (exc >>IEEE_STATUS_TO_EXCSUM_SHIFT ) & swcr;if (fex) {siginfo_t info; -int si_code =FPE_FIXME ; +int si_code =FPE_FLTUNK ;if (fex &IEEE_TRAP_ENABLE_DNO ) si_code =FPE_FLTUND ;if (fex &IEEE_TRAP_ENABLE_INE ) si_code =FPE_FLTRES ;
arch/alpha/kernel/traps.c +1 -1
@@ -328,7 +328,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)break ;case GEN_ROPRAND : signo =SIGFPE ; - code =FPE_FIXME ; + code =FPE_FLTUNK ;break ;case GEN_DECOVF :
Signature · 1 line
2.14.1
PATCH 12/17 signal/ia64: Replace FPE_FIXME with FPE_FLTUNK
In reply to Eric W. BiedermanUsing an si_code of 0 that aliases with SI_USER is clearly the wrong thing todo, and causes problems in interesting ways.
The newly defined FPE_FLTUNK semantically appears to fit the bill so use it instead.
Given recent experience in this area odds are it will not break anything. Fixing it removes a hazard to kernel maintenance.
--- arch/ia64/include/uapi/asm/siginfo.h | 7 ------- arch/ia64/kernel/traps.c | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-)
arch/ia64/include/uapi/asm/siginfo.h +0 -7
@@ -27,11 +27,4 @@#define __ISR_VALID_BIT 0#define __ISR_VALID (1 << __ISR_VALID_BIT) -/* -* SIGFPE si_codes -*/ -#ifdef __KERNEL__ -#define FPE_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ -#endif /* _UAPI_ASM_IA64_SIGINFO_H */
arch/ia64/kernel/traps.c +2 -2
@@ -353,7 +353,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)clear_siginfo (&siginfo); siginfo.si_signo =SIGFPE ; siginfo.si_errno =0 ; - siginfo.si_code =FPE_FIXME ;/* default code */ + siginfo.si_code =FPE_FLTUNK ;/* default code */ siginfo.si_addr = (void __user *) (regs->cr_iip +ia64_psr (regs)->ri);if (isr &0x11 ) { siginfo.si_code =FPE_FLTINV ;
@@ -380,7 +380,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)clear_siginfo (&siginfo); siginfo.si_signo =SIGFPE ; siginfo.si_errno =0 ; - siginfo.si_code =FPE_FIXME ;/* default code */ + siginfo.si_code =FPE_FLTUNK ;/* default code */ siginfo.si_addr = (void __user *) (regs->cr_iip +ia64_psr (regs)->ri);if (isr &0x880 ) { siginfo.si_code =FPE_FLTOVF ;
Signature · 1 line
2.14.1
PATCH 13/17 signal/powerpc: Replace FPE_FIXME with FPE_FLTUNK
In reply to Eric W. BiedermanUsing an si_code of 0 that aliases with SI_USER is clearly the wrong thing todo, and causes problems in interesting ways.
The newly defined FPE_FLTUNK semantically appears to fit the bill so use it instead.
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
--- arch/powerpc/include/uapi/asm/siginfo.h | 7 ------- arch/powerpc/kernel/traps.c | 6 +++--- 2 files changed, 3 insertions(+), 10 deletions(-)
arch/powerpc/include/uapi/asm/siginfo.h +0 -7
@@ -15,13 +15,6 @@#include <asm-generic/siginfo.h> -/* -* SIGFPE si_codes -*/ -#ifdef __KERNEL__ -#define FPE_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ -/* * SIGTRAP si_codes */
arch/powerpc/kernel/traps.c +3 -3
@@ -1031,7 +1031,7 @@ static void emulate_single_step(struct pt_regs *regs)static inline int __parse_fpscr (unsigned long fpscr) { -int ret =FPE_FIXME ; +int ret =FPE_FLTUNK ;/* Invalid operation */ if ((fpscr &FPSCR_VE ) && (fpscr &FPSCR_VX ))
@@ -1972,7 +1972,7 @@ void SPEFloatingPointException(struct pt_regs *regs)extern int do_spe_mathemu (struct pt_regs *regs);unsigned long spefscr;int fpexc_mode; -int code =FPE_FIXME ; +int code =FPE_FLTUNK ;int err;flush_spe_to_thread (current);
@@ -2041,7 +2041,7 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)printk (KERN_ERR "unrecognized spe instruction " "in %s at %lx\n" , current->comm, regs->nip); }else { -_exception (SIGFPE , regs,FPE_FIXME , regs->nip); +_exception (SIGFPE , regs,FPE_FLTUNK , regs->nip);return ; } }
Signature · 1 line
2.14.1
PATCH 14/17 signal/unicore32: Use FPE_FLTUNK instead of 0 in ucf64_raise_sigfpe
In reply to Eric W. BiedermanThe si_code of 0 (aka SI_USER) has fields si_pid and si_uid not si_addr so it so only by luck would the appropriate fields by copied to userspace by copy_siginfo_to_user.
This is just broken and wrong.
Make it obvious what is happening by moving the si_code from a parameter of the one call to ucf64_raise_sigfpe to a constant value that info.si_code gets set to.
Explicitly set the si_code to FPE_FLTUNK the newly reserved floating point si_code for an unknown floating point exception.
It looks like there is a fair chance that this is a code path that has never been used in real life on unicore32. The bad si_code and the print statement that calls it an unhandled exception. So I really don't expect anyone will mind if this just gets fixed.
In similar situations on more popular architectures the conclusion was just fix it.
--- arch/unicore32/kernel/fpu-ucf64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/unicore32/kernel/fpu-ucf64.c +3 -3
@@ -52,14 +52,14 @@* Raise a SIGFPE for the current process. * sicode describes the signal being raised. */ -void ucf64_raise_sigfpe (unsigned int sicode,struct pt_regs *regs) +void ucf64_raise_sigfpe (struct pt_regs *regs) {siginfo_t info;clear_siginfo (&info); info.si_signo =SIGFPE ; - info.si_code = sicode; + info.si_code =FPE_FLTUNK ; info.si_addr = (void __user *)(instruction_pointer (regs) -4 );/*
@@ -94,7 +94,7 @@ void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)pr_debug ("UniCore-F64 FPSCR 0x%08x INST 0x%08x\n" ,cff (FPSCR ), inst); -ucf64_raise_sigfpe (0 , regs); +ucf64_raise_sigfpe (regs);return ; }
Signature · 1 line
2.14.1
PATCH 15/17 signal: Add TRAP_UNK si_code for undiagnosted trap exceptions
In reply to Eric W. BiedermanBoth powerpc and alpha have cases where they wronly set si_code to 0 in combination with SIGTRAP and don't mean SI_USER.
About half the time this is because the architecture can not report accurately what kind of trap exception triggered the trap exception. The other half the time it looks like no one has bothered to figure out an appropriate si_code.
For the cases where the architecture does not have enough information or is too lazy to figure out exactly what kind of trap exception it is define TRAP_UNK.
--- arch/x86/kernel/signal_compat.c | 2 +- include/uapi/asm-generic/siginfo.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/signal_compat.c +1 -1
@@ -29,7 +29,7 @@ static inline void signal_compat_build_tests(void)BUILD_BUG_ON (NSIGFPE !=15 );BUILD_BUG_ON (NSIGSEGV !=7 );BUILD_BUG_ON (NSIGBUS !=5 ); -BUILD_BUG_ON (NSIGTRAP !=4 ); +BUILD_BUG_ON (NSIGTRAP !=5 );BUILD_BUG_ON (NSIGCHLD !=6 );BUILD_BUG_ON (NSIGSYS !=1 );
include/uapi/asm-generic/siginfo.h +2 -1
@@ -249,7 +249,8 @@ typedef struct siginfo {#define TRAP_TRACE 2/* process trace trap */ #define TRAP_BRANCH 3/* process taken branch trap */ #define TRAP_HWBKPT 4/* hardware breakpoint/watchpoint */ -#define NSIGTRAP 4 +#define TRAP_UNK 5/* undiagnosed trap */ +#define NSIGTRAP 5/* * There is an additional set of SIGTRAP si_codes used by ptrace
Signature · 1 line
2.14.1
PATCH 16/17 signal/alpha: Replace TRAP_FIXME with TRAP_UNK
In reply to Eric W. BiedermanUsing an si_code of 0 that aliases with SI_USER is clearly the wrong thing to do, and causes problems in interesting ways.
For it really is not clear to me if using TRAP_UNK bugcheck or the default case of gentrap is really the best way to handle things. There is certainly enough information that that a more specific si_code could potentially be used. That said TRAP_UNK is definitely an improvement over 0 as it removes the ambiguiuty of what si_code of 0 with SIGTRAP means on alpha.
Recent history suggests no actually cares about crazy corner cases of the kernel behavior like this so I don't expect any regressions from changing this. However if something does happen this change is easy to revert.
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
--- arch/alpha/include/uapi/asm/siginfo.h | 7 ------- arch/alpha/kernel/traps.c | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-)
arch/alpha/include/uapi/asm/siginfo.h +0 -7
@@ -7,11 +7,4 @@#include <asm-generic/siginfo.h> -/* -* SIGTRAP si_codes -*/ -#ifdef __KERNEL__ -#define TRAP_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ -#endif
arch/alpha/kernel/traps.c +2 -2
@@ -288,7 +288,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)case 1 :/* bugcheck */ info.si_signo =SIGTRAP ; info.si_errno =0 ; - info.si_code =TRAP_FIXME ; + info.si_code =TRAP_UNK ; info.si_addr = (void __user *) regs->pc; info.si_trapno =0 ;send_sig_info (SIGTRAP , &info, current);
@@ -350,7 +350,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)case GEN_SUBRNG7 :default : signo =SIGTRAP ; - code =TRAP_FIXME ; + code =TRAP_UNK ;break ; }
Signature · 1 line
2.14.1
PATCH 17/17 signal/powerpc: Replace TRAP_FIXME with TRAP_UNK
In reply to Eric W. BiedermanUsing an si_code of 0 that aliases with SI_USER is clearly the wrong thing todo, and causes problems in interesting ways.
For use in unknown_exception the recently defined TRAP_UNK semantically is a perfect fit. For use in RunModeException it looks like something more specific than TRAP_UNK could be used. No one has bothered to find a better fit than the broken si_code of 0 in all of these years and I don't see an obvious better fit so TRAP_UNK is switching RunModeException to return TRAP_UNK is clearly an improvement.
Recent history suggests no actually cares about crazy corner cases of the kernel behavior like this so I don't expect any regressions from changing this. However if something does happen this change is easy to revert.
Though I wonder if SIGKILL might not be a better fit.
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
--- arch/powerpc/include/uapi/asm/siginfo.h | 8 -------- arch/powerpc/kernel/traps.c | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-)
arch/powerpc/include/uapi/asm/siginfo.h +0 -8
@@ -15,12 +15,4 @@#include <asm-generic/siginfo.h> -/* -* SIGTRAP si_codes -*/ -#ifdef __KERNEL__ -#define TRAP_FIXME 0/* Broken dup of SI_USER */ -#endif /* __KERNEL__ */ - -#endif /* _ASM_POWERPC_SIGINFO_H */
arch/powerpc/kernel/traps.c +2 -2
@@ -969,7 +969,7 @@ void unknown_exception(struct pt_regs *regs)printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , regs->nip, regs->msr, regs->trap); -_exception (SIGTRAP , regs,TRAP_FIXME ,0 ); +_exception (SIGTRAP , regs,TRAP_UNK ,0 );exception_exit (prev_state); }
@@ -991,7 +991,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)void RunModeException (struct pt_regs *regs) { -_exception (SIGTRAP , regs,TRAP_FIXME ,0 ); +_exception (SIGTRAP , regs,TRAP_UNK ,0 ); }void single_step_exception (struct pt_regs *regs)
Signature · 1 line
2.14.1
cover Simplifying siginfo users
In reply to Eric W. BiedermanThis patchset is almost completely updating the various pieces of architecture code from filling out a struct siginfo and then calling force_sig_info. To using the helper force_sig_fault instead. Which takes the values that would have gone in siginfo as arguments.
As the diffstat below shows this noticeable reduces the amount of code.
There are a couple of minor and straight forward bug fixes as well that I came across while working on the aforementioned changes.
This applies on my last round of siginfo changes simply to remove the possibility of conflicts. The changes should be semantically separate.
I intend to merge these changes through my siginfo tree. If you have any objections or would prefer to carry these changes in your architecture trees please let me know.
The changes are also available at:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git siginfo-review2
Eric W. Biederman (22):
signal/alpha: Use send_sig_fault where appropriate signal/alpha: Use force_sig_fault where appropriate signal/c6x: Use force_sig_fault where appropriate signal/hexagon: Use force_sig_fault as appropriate signal/m68k: Use force_sig_fault where appropriate signal/microblaze: Remove the commented out force_sig_info in do_page_fault signal/microblaze: Use force_sig_fault where appropriate signal/mips: Use force_sig_fault where appropriate signal/nds32: Use force_sig_fault where appropriate signal/nios2: Use force_sig_fault where appropriate signal/openrisc: Use force_sig_fault where appropriate signal/parisc: Use force_sig_mceerr where appropriate signal/parisc: Use force_sig_fault where appropriate signal/riscv: Use force_sig_fault where appropriate signal/s390: Use force_sig_fault where appropriate
signal/sh: Use force_sig_fault where appropriate
signal/sparc: Use send_sig_fault where appropriate signal/sparc: Use force_sig_fault where appropriate
signal/um: Use force_sig_fault in relay_signal.
signal/um: Use force_sig_fault where appropriate signal/xtensa: Consistenly use SIGBUS in do_unaligned_user signal/xtensa: Use force_sig_fault where appropriate
arch/alpha/kernel/osf_sys.c | 10 +-- arch/alpha/kernel/signal.c | 22 +----- arch/alpha/kernel/traps.c | 80 +++++--------------- arch/alpha/mm/fault.c | 15 +--- arch/c6x/kernel/traps.c | 10 +-- arch/hexagon/kernel/traps.c | 10 +-- arch/hexagon/mm/vm_fault.c | 21 ++---- arch/m68k/kernel/traps.c | 60 +++++++-------- arch/m68k/mm/fault.c | 25 +++---- arch/microblaze/kernel/exceptions.c | 9 +-- arch/microblaze/mm/fault.c | 14 +--- arch/mips/kernel/traps.c | 65 +++++----------- arch/mips/mm/fault.c | 19 ++--- arch/nds32/kernel/traps.c | 20 +---- arch/nds32/mm/fault.c | 19 ++--- arch/nios2/kernel/traps.c | 9 +-- arch/openrisc/kernel/traps.c | 33 +------- arch/openrisc/mm/fault.c | 19 ++--- arch/parisc/kernel/ptrace.c | 11 +-- arch/parisc/kernel/traps.c | 63 +++++----------- arch/parisc/kernel/unaligned.c | 16 +--- arch/parisc/math-emu/driver.c | 9 +-- arch/parisc/mm/fault.c | 55 +++++++------- arch/riscv/kernel/traps.c | 9 +-- arch/s390/kernel/traps.c | 32 ++------ arch/s390/mm/fault.c | 23 ++---- arch/sh/kernel/traps_32.c | 19 ++--- arch/sh/math-emu/math.c | 9 +-- arch/sh/mm/fault.c | 10 +-- arch/sparc/kernel/process_64.c | 10 +-- arch/sparc/kernel/sys_sparc_32.c | 9 +-- arch/sparc/kernel/sys_sparc_64.c | 8 +- arch/sparc/kernel/traps_32.c | 114 +++++----------------------- arch/sparc/kernel/traps_64.c | 145 +++++++----------------------------- arch/sparc/kernel/unaligned_32.c | 12 +-- arch/sparc/mm/fault_32.c | 13 +--- arch/sparc/mm/fault_64.c | 9 +-- arch/um/kernel/ptrace.c | 13 +--- arch/um/kernel/trap.c | 54 ++++++-------- arch/xtensa/kernel/traps.c | 10 +-- arch/xtensa/mm/fault.c | 19 ++--- 41 files changed, 280 insertions(+), 852 deletions(-)
Eric
PATCH 1/22 signal/alpha: Use send_sig_fault where appropriate
Filling in struct siginfo before calling send_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 send_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 send_sig_info.
In short about a 5 line reduction in code for every time send_sig_info is called, which makes the calling function clearer.
--- arch/alpha/kernel/osf_sys.c | 10 ++----- arch/alpha/kernel/signal.c | 22 +++----------- arch/alpha/kernel/traps.c | 71 +++++++++++---------------------------------- 3 files changed, 24 insertions(+), 79 deletions(-)
arch/alpha/kernel/osf_sys.c +3 -7
@@ -871,7 +871,6 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,send a signal. Old exceptions are not signaled. */ fex = (exc >>IEEE_STATUS_TO_EXCSUM_SHIFT ) & swcr;if (fex) { -siginfo_t info;int si_code =FPE_FLTUNK ;if (fex &IEEE_TRAP_ENABLE_DNO ) si_code =FPE_FLTUND ;
@@ -881,12 +880,9 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,if (fex &IEEE_TRAP_ENABLE_DZE ) si_code =FPE_FLTDIV ;if (fex &IEEE_TRAP_ENABLE_INV ) si_code =FPE_FLTINV ; -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr =NULL ;/* FIXME */ -send_sig_info (SIGFPE , &info, current); +send_sig_fault (SIGFPE , si_code, + (void __user *)NULL ,/* FIXME */ +0 , current); }return 0 ; }
arch/alpha/kernel/signal.c +4 -18
@@ -219,15 +219,8 @@ do_sigreturn(struct sigcontext __user *sc)/* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_BRKPT ; - info.si_addr = (void __user *) regs->pc; - info.si_trapno =0 ; -send_sig_info (SIGTRAP , &info, current); +send_sig_fault (SIGTRAP ,TRAP_BRKPT , (void __user *) regs->pc,0 , + current); }return ;
@@ -254,15 +247,8 @@ do_rt_sigreturn(struct rt_sigframe __user *frame)/* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_BRKPT ; - info.si_addr = (void __user *) regs->pc; - info.si_trapno =0 ; -send_sig_info (SIGTRAP , &info, current); +send_sig_fault (SIGTRAP ,TRAP_BRKPT , (void __user *) regs->pc,0 , + current); }return ;
arch/alpha/kernel/traps.c +17 -54
154 lines not on this page · raw message
Signature · 1 line
2.14.1
PATCH 2/22 signal/alpha: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/alpha/kernel/traps.c | 9 +-------- arch/alpha/mm/fault.c | 15 ++------------- 2 files changed, 3 insertions(+), 21 deletions(-)
arch/alpha/kernel/traps.c +1 -8
@@ -400,16 +400,9 @@ do_entIF(unsigned long type, struct pt_regs *regs) asmlinkage voiddo_entDbg (struct pt_regs *regs) { -siginfo_t info; -die_if_kernel ("Instruction fault" , regs,0 ,NULL ); -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_ILLOPC ; - info.si_addr = (void __user *) regs->pc; -force_sig_info (SIGILL , &info, current); +force_sig_fault (SIGILL ,ILL_ILLOPC , (void __user *)regs->pc,0 , current); }
arch/alpha/mm/fault.c +2 -13
@@ -88,11 +88,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,struct mm_struct *mm = current->mm;const struct exception_table_entry *fixup;int fault, si_code =SEGV_MAPERR ; -siginfo_t info;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; -clear_siginfo (&info); -/* As of EV6, a load into $31/$f31 is a prefetch, and never faults (or is suppressed by the PALcode). Support that for older CPUs by ignoring such an instruction. */
@@ -223,21 +220,13 @@ do_page_fault(unsigned long address, unsigned long mmcsr,up_read (&mm->mmap_sem);/* Send a sigbus, regardless of whether we were in kernel or user mode. */ - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void __user *) address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *) address,0 , current);if (!user_mode (regs)) goto no_context;return ; do_sigsegv: - info.si_signo =SIGSEGV ; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void __user *) address; -force_sig_info (SIGSEGV , &info, current); +force_sig_fault (SIGSEGV , si_code, (void __user *) address,0 , current);return ;#ifdef CONFIG_ALPHA_LARGE_VMALLOC
Signature · 1 line
2.14.1
PATCH 3/22 signal/c6x: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/c6x/kernel/traps.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
arch/c6x/kernel/traps.c +2 -8
@@ -244,9 +244,7 @@ static struct exception_info eexcept_table[128] = {static void do_trap (struct exception_info *except_info,struct pt_regs *regs) {unsigned long addr =instruction_pointer (regs); -siginfo_t info; -clear_siginfo (&info);if (except_info->code !=TRAP_BRKPT ) pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n", except_info->kernel_str, regs->pc,
@@ -254,12 +252,8 @@ static void do_trap(struct exception_info *except_info, struct pt_regs *regs)die_if_kernel (except_info->kernel_str, regs, addr); - info.si_signo = except_info->signo; - info.si_errno =0 ; - info.si_code = except_info->code; - info.si_addr = (void __user *)addr; - -force_sig_info (except_info->signo, &info, current); +force_sig_fault (except_info->signo, except_info->code, + (void __user *)addr, current); }/*
Signature · 1 line
2.14.1
PATCH 4/22 signal/hexagon: Use force_sig_fault as appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/hexagon/kernel/traps.c | 10 ++-------- arch/hexagon/mm/vm_fault.c | 21 +++++++-------------- 2 files changed, 9 insertions(+), 22 deletions(-)
arch/hexagon/kernel/traps.c +2 -8
@@ -412,11 +412,6 @@ void do_trap0(struct pt_regs *regs)case TRAP_DEBUG :/* Trap0 0xdb is debug breakpoint */ if (user_mode (regs)) { -struct siginfo info; - -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ;/* * Some architecures add some per-thread state * to distinguish between breakpoint traps and
@@ -424,9 +419,8 @@ void do_trap0(struct pt_regs *regs)* set the si_code value appropriately, or we * may want to use a different trap0 flavor. */ - info.si_code =TRAP_BRKPT ; - info.si_addr = (void __user *)pt_elr (regs); -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_BRKPT , + (void __user *)pt_elr (regs), current); }else {#ifdef CONFIG_KGDB kgdb_handle_exception(pt_cause(regs), SIGTRAP,
arch/hexagon/mm/vm_fault.c +7 -14
@@ -50,13 +50,12 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs) {struct vm_area_struct *vma;struct mm_struct *mm = current->mm; -siginfo_t info; +int si_signo;int si_code =SEGV_MAPERR ;int fault;const struct exception_table_entry *fixup;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; -clear_siginfo (&info);/* * If we're in an interrupt or have no user context, * then must not take the fault.
@@ -141,28 +140,22 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)* unable to fix up the page fault. */ if (fault &VM_FAULT_SIGBUS ) { - info.si_signo =SIGBUS ; - info.si_code =BUS_ADRERR ; + si_signo =SIGBUS ; + si_code =BUS_ADRERR ; }/* Address is not in the memory map */ else { - info.si_signo =SIGSEGV ; - info.si_code =SEGV_ACCERR ; + si_signo =SIGSEGV ; + si_code =SEGV_ACCERR ; } - info.si_errno =0 ; - info.si_addr = (void __user *)address; -force_sig_info (info.si_signo, &info, current); +force_sig_fault (si_signo, si_code, (void __user *)address, current);return ; bad_area:up_read (&mm->mmap_sem);if (user_mode (regs)) { - info.si_signo =SIGSEGV ; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void *)address; -force_sig_info (info.si_signo, &info, current); +force_sig_fault (SIGSEGV , si_code, (void __user *)address, current);return ; }/* Kernel-mode fault falls through */
Signature · 1 line
2.14.1
PATCH 5/22 signal/m68k: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/m68k/kernel/traps.c | 60 ++++++++++++++++++++---------------------------- arch/m68k/mm/fault.c | 25 +++++++++----------- 2 files changed, 36 insertions(+), 49 deletions(-)
arch/m68k/kernel/traps.c +25 -35
@@ -1007,11 +1007,10 @@ void bad_super_trap (struct frame *fp) asmlinkage void trap_c(struct frame *fp) { -int sig; +int sig, si_code; +void __user *addr;int vector = (fp->ptregs.vector >>2 ) &0xff ; -siginfo_t info; -clear_siginfo (&info);if (fp->ptregs.sr &PS_S ) {if (vector ==VEC_TRACE ) {/* traced a trapping instruction on a 68020/30,
@@ -1030,21 +1029,21 @@ asmlinkage void trap_c(struct frame *fp)/* send the appropriate signal to the user program */ switch (vector) {case VEC_ADDRERR : - info.si_code =BUS_ADRALN ; + si_code =BUS_ADRALN ; sig =SIGBUS ;break ;case VEC_ILLEGAL :case VEC_LINE10 :case VEC_LINE11 : - info.si_code =ILL_ILLOPC ; + si_code =ILL_ILLOPC ; sig =SIGILL ;break ;case VEC_PRIV : - info.si_code =ILL_PRVOPC ; + si_code =ILL_PRVOPC ; sig =SIGILL ;break ;case VEC_COPROC : - info.si_code =ILL_COPROC ; + si_code =ILL_COPROC ; sig =SIGILL ;break ;case VEC_TRAP1 :
@@ -1061,76 +1060,74 @@ asmlinkage void trap_c(struct frame *fp)case VEC_TRAP12 :case VEC_TRAP13 :case VEC_TRAP14 : - info.si_code =ILL_ILLTRP ; + si_code =ILL_ILLTRP ; sig =SIGILL ;break ;case VEC_FPBRUC :case VEC_FPOE :case VEC_FPNAN : - info.si_code =FPE_FLTINV ; + si_code =FPE_FLTINV ; sig =SIGFPE ;break ;case VEC_FPIR : - info.si_code =FPE_FLTRES ; + si_code =FPE_FLTRES ; sig =SIGFPE ;break ;case VEC_FPDIVZ : - info.si_code =FPE_FLTDIV ; + si_code =FPE_FLTDIV ; sig =SIGFPE ;break ;case VEC_FPUNDER : - info.si_code =FPE_FLTUND ; + si_code =FPE_FLTUND ; sig =SIGFPE ;break ;case VEC_FPOVER : - info.si_code =FPE_FLTOVF ; + si_code =FPE_FLTOVF ; sig =SIGFPE ;break ;case VEC_ZERODIV : - info.si_code =FPE_INTDIV ; + si_code =FPE_INTDIV ; sig =SIGFPE ;break ;case VEC_CHK :case VEC_TRAP : - info.si_code =FPE_INTOVF ; + si_code =FPE_INTOVF ; sig =SIGFPE ;break ;case VEC_TRACE :/* ptrace single step */ - info.si_code =TRAP_TRACE ; + si_code =TRAP_TRACE ; sig =SIGTRAP ;break ;case VEC_TRAP15 :/* breakpoint */ - info.si_code =TRAP_BRKPT ; + si_code =TRAP_BRKPT ; sig =SIGTRAP ;break ;default : - info.si_code =ILL_ILLOPC ; + si_code =ILL_ILLOPC ; sig =SIGILL ;break ; } - info.si_signo = sig; - info.si_errno =0 ;switch (fp->ptregs.format) {default : - info.si_addr = (void *) fp->ptregs.pc; + addr = (void __user *) fp->ptregs.pc;break ;case 2 : - info.si_addr = (void *) fp->un.fmt2.iaddr; + addr = (void __user *) fp->un.fmt2.iaddr;break ;case 7 : - info.si_addr = (void *) fp->un.fmt7.effaddr; + addr = (void __user *) fp->un.fmt7.effaddr;break ;case 9 : - info.si_addr = (void *) fp->un.fmt9.iaddr; + addr = (void __user *) fp->un.fmt9.iaddr;break ;case 10 : - info.si_addr = (void *) fp->un.fmta.daddr; + addr = (void __user *) fp->un.fmta.daddr;break ;case 11 : - info.si_addr = (void *) fp->un.fmtb.daddr; + addr = (void __user *) fp->un.fmtb.daddr;break ; } -force_sig_info (sig, &info, current); +force_sig_fault (sig, si_code, addr, current); }void die_if_kernel (char *str,struct pt_regs *fp,int nr)
@@ -1162,13 +1159,6 @@ asmlinkage void fpsp040_die(void)#ifdef CONFIG_M68KFPU_EMU asmlinkage void fpemu_signal(int signal, int code, void *addr) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo = signal; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = addr; -force_sig_info (signal, &info, current); +force_sig_fault (signal, code, addr, current); }#endif
arch/m68k/mm/fault.c +11 -14
@@ -21,35 +21,32 @@ extern void die_if_kernel(char *, struct pt_regs *, long);int send_fault_sig (struct pt_regs *regs) { -siginfo_t siginfo; +int signo, si_code; +void __user *addr; -clear_siginfo (&siginfo); - siginfo.si_signo = current->thread.signo; - siginfo.si_code = current->thread.code; - siginfo.si_addr = (void *)current->thread.faddr; -pr_debug ("send_fault_sig: %p,%d,%d\n" , siginfo.si_addr, - siginfo.si_signo, siginfo.si_code); + signo = current->thread.signo; + si_code = current->thread.code; + addr = (void __user *)current->thread.faddr; +pr_debug ("send_fault_sig: %p,%d,%d\n" , addr, signo, si_code);if (user_mode (regs)) { -force_sig_info (siginfo.si_signo, - &siginfo, current); +force_sig_fault (signo, si_code, addr, current); }else {if (fixup_exception (regs))return -1 ; -//if (siginfo.si_signo == SIGBUS) -// force_sig_info(siginfo.si_signo, -// &siginfo, current); +//if (signo == SIGBUS) +// force_sig_fault(si_signo, si_code, addr, current); /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ -if ((unsigned long )siginfo.si_addr <PAGE_SIZE ) +if ((unsigned long )addr <PAGE_SIZE )pr_alert ("Unable to handle kernel NULL pointer dereference" );else pr_alert ("Unable to handle kernel access" ); -pr_cont (" at virtual address %p\n" , siginfo.si_addr); +pr_cont (" at virtual address %p\n" , addr);die_if_kernel ("Oops" , regs,0 /*error_code*/ );do_exit (SIGKILL ); }
Signature · 1 line
2.14.1
PATCH 6/22 signal/microblaze: Remove the commented out force_sig_info in do_page_fault
In reply to Eric W. BiedermanRemove the commented out call to force_sig_info right after a call to _exception in do_page_fault. The function _exception does exactly the work the commented out code does so there is no reason for the commented out code.
--- arch/microblaze/mm/fault.c | 5 ----- 1 file changed, 5 deletions(-)
arch/microblaze/mm/fault.c +0 -5
@@ -268,11 +268,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,/* User mode accesses cause a SIGSEGV */ if (user_mode (regs)) {_exception (SIGSEGV , regs, code, address); -/* info.si_signo = SIGSEGV; -info.si_errno = 0; -info.si_code = code; -info.si_addr = (void *) address; -force_sig_info(SIGSEGV, &info, current);*/ return ; }
Signature · 1 line
2.14.1
PATCH 7/22 signal/microblaze: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/microblaze/kernel/exceptions.c | 9 +-------- arch/microblaze/mm/fault.c | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-)
arch/microblaze/kernel/exceptions.c +1 -8
@@ -60,17 +60,10 @@ asmlinkage void sw_exception(struct pt_regs *regs)void _exception (int signr,struct pt_regs *regs,int code,unsigned long addr) { -siginfo_t info; -if (kernel_mode (regs))die ("Exception in kernel mode" , regs, signr); -clear_siginfo (&info); - info.si_signo = signr; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *) addr; -force_sig_info (signr, &info, current); +force_sig_fault (signr, code, (void __user *)addr, current); } asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
arch/microblaze/mm/fault.c +1 -8
@@ -289,14 +289,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, do_sigbus:up_read (&mm->mmap_sem);if (user_mode (regs)) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void __user *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, current);return ; }bad_page_fault (regs, address,SIGBUS );
Signature · 1 line
2.14.1
PATCH 8/22 signal/mips: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/mips/kernel/traps.c | 65 ++++++++++++++---------------------------------- arch/mips/mm/fault.c | 19 ++++---------- 2 files changed, 23 insertions(+), 61 deletions(-)
arch/mips/kernel/traps.c +18 -47
@@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) {enum ctx_state prev_state; -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_code =FPE_INTOVF ; - info.si_addr = (void __user *)regs->cp0_epc; prev_state =exception_enter ();die_if_kernel ("Integer overflow" , regs); -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , (void __user *)regs->cp0_epc, current);exception_exit (prev_state); }
@@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs)void force_fcr31_sig (unsigned long fcr31,void __user *fault_addr,struct task_struct *tsk) { -struct siginfo si; - -clear_siginfo (&si); - si.si_addr = fault_addr; - si.si_signo =SIGFPE ; +int si_code;if (fcr31 &FPU_CSR_INV_X ) - si.si_code =FPE_FLTINV ; + si_code =FPE_FLTINV ;else if (fcr31 &FPU_CSR_DIV_X ) - si.si_code =FPE_FLTDIV ; + si_code =FPE_FLTDIV ;else if (fcr31 &FPU_CSR_OVF_X ) - si.si_code =FPE_FLTOVF ; + si_code =FPE_FLTOVF ;else if (fcr31 &FPU_CSR_UDF_X ) - si.si_code =FPE_FLTUND ; + si_code =FPE_FLTUND ;else if (fcr31 &FPU_CSR_INE_X ) - si.si_code =FPE_FLTRES ; + si_code =FPE_FLTRES ; -force_sig_info (SIGFPE , &si, tsk); +force_sig_fault (SIGFPE , si_code, fault_addr, tsk); }int process_fpemu_return (int sig,void __user *fault_addr,unsigned long fcr31) { -struct siginfo si; +int si_code;struct vm_area_struct *vma; -clear_siginfo (&si);switch (sig) {case 0 :return 0 ;
@@ -757,23 +746,18 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)return 1 ;case SIGBUS : - si.si_addr = fault_addr; - si.si_signo = sig; - si.si_code =BUS_ADRERR ; -force_sig_info (sig, &si, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , fault_addr, current);return 1 ;case SIGSEGV : - si.si_addr = fault_addr; - si.si_signo = sig;down_read (¤t->mm->mmap_sem); vma =find_vma (current->mm, (unsigned long )fault_addr);if (vma && (vma->vm_start <= (unsigned long )fault_addr)) - si.si_code =SEGV_ACCERR ; + si_code =SEGV_ACCERR ;else - si.si_code =SEGV_MAPERR ; + si_code =SEGV_MAPERR ;up_read (¤t->mm->mmap_sem); -force_sig_info (sig, &si, current); +force_sig_fault (SIGSEGV , si_code, fault_addr, current);return 1 ;default :
@@ -896,10 +880,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)void do_trap_or_bp (struct pt_regs *regs,unsigned int code,int si_code,const char *str) { -siginfo_t info;char b[40 ]; -clear_siginfo (&info);#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap (DIE_TRAP , str, regs, code, current->thread.trap_nr,SIGTRAP ) ==NOTIFY_STOP )
@@ -921,13 +903,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,case BRK_DIVZERO :scnprintf (b,sizeof (b),"%s instruction in kernel code" , str);die_if_kernel (b, regs); -if (code ==BRK_DIVZERO ) - info.si_code =FPE_INTDIV ; -else - info.si_code =FPE_INTOVF ; - info.si_signo =SIGFPE ; - info.si_addr = (void __user *) regs->cp0_epc; -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE , + code ==BRK_DIVZERO ?FPE_INTDIV :FPE_INTOVF , + (void __user *) regs->cp0_epc, current);break ;case BRK_BUG :die_if_kernel ("Kernel bug detected" , regs);
@@ -952,9 +930,7 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,scnprintf (b,sizeof (b),"%s instruction in kernel code" , str);die_if_kernel (b, regs);if (si_code) { - info.si_signo =SIGTRAP ; - info.si_code = si_code; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP , si_code,NULL , current); }else {force_sig (SIGTRAP , current); }
@@ -1506,13 +1482,8 @@ asmlinkage void do_mdmx(struct pt_regs *regs)*/ asmlinkage void do_watch(struct pt_regs *regs) { -siginfo_t info;enum ctx_state prev_state; -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_code =TRAP_HWBKPT ; - prev_state =exception_enter ();/* * Clear WP (bit 22) bit of cause register so we don't loop
@@ -1528,7 +1499,7 @@ asmlinkage void do_watch(struct pt_regs *regs)if (test_tsk_thread_flag (current,TIF_LOAD_WATCH )) {mips_read_watch_registers ();local_irq_enable (); -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_HWBKPT ,NULL , current); }else {mips_clear_watch_registers ();local_irq_enable ();
arch/mips/mm/fault.c +5 -14
@@ -42,7 +42,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,struct task_struct *tsk = current;struct mm_struct *mm = tsk->mm;const int field =sizeof (unsigned long ) *2 ; -siginfo_t info; +int si_code;int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ;
@@ -63,8 +63,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,return ;#endif -clear_siginfo (&info); - info.si_code =SEGV_MAPERR ; + si_code =SEGV_MAPERR ;/* * We fault-in kernel-space virtual memory on-demand. The
@@ -113,7 +112,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,* we can handle it.. */ good_area: - info.si_code =SEGV_ACCERR ; + si_code =SEGV_ACCERR ;if (write) {if (!(vma->vm_flags &VM_WRITE ))
@@ -224,11 +223,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,pr_cont ("\n" ); } current->thread.trap_nr = (regs->cp0_cause >>2 ) &0x1f ; - info.si_signo =SIGSEGV ; - info.si_errno =0 ; -/* info.si_code has been set above */ - info.si_addr = (void __user *) address; -force_sig_info (SIGSEGV , &info, tsk); +force_sig_fault (SIGSEGV , si_code, (void __user *)address, tsk);return ; }
@@ -284,11 +279,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,#endif current->thread.trap_nr = (regs->cp0_cause >>2 ) &0x1f ; tsk->thread.cp0_badvaddr = address; - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void __user *) address; -force_sig_info (SIGBUS , &info, tsk); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, tsk);return ;#ifndef CONFIG_64BIT
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 08/22] signal/mips: Use force_sig_fault where appropriate
Hi Eric,
Quoted 45 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Ralf Baechle <[email protected]>Cc James Hogan <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/mips/kernel/traps.c | 65 ++++++++++++++---------------------------------- arch/mips/mm/fault.c | 19 ++++---------- 2 files changed, 23 insertions(+), 61 deletions(-)arch/mips/kernel/traps.c +1
-7@@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) {enum ctx_state prev_state; -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_code =FPE_INTOVF ; - info.si_addr = (void __user *)regs->cp0_epc; prev_state =exception_enter ();die_if_kernel ("Integer overflow" , regs); -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , (void __user *)regs->cp0_epc, current);exception_exit (prev_state); }
arch/mips/kernel/traps.c asmlinkage void do_ov(struct pt_regs *regs) · line 719
Quoted 9 lines
arch/mips/kernel/traps.c +1
-5@@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs)void force_fcr31_sig (unsigned long fcr31,void __user *fault_addr,struct task_struct *tsk) { -struct siginfo si; - -clear_siginfo (&si); - si.si_addr = fault_addr; - si.si_signo =SIGFPE ; +int si_code;
This is giving build errors in Linux next (https://storage.kernelci.org/next/master/next-20180509/mips/defconfig+kselftest/build.log)
si_code would have ended up as 0 before from the clear_siginfo(), but perhaps
int si_code = FPE_FLTUNK;
Would make a more sensible default?
Thanks,
Matt
Quoted 180 lines
arch/mips/kernel/traps.c +16
-35if (fcr31 &FPU_CSR_INV_X ) - si.si_code =FPE_FLTINV ; + si_code =FPE_FLTINV ;else if (fcr31 &FPU_CSR_DIV_X ) - si.si_code =FPE_FLTDIV ; + si_code =FPE_FLTDIV ;else if (fcr31 &FPU_CSR_OVF_X ) - si.si_code =FPE_FLTOVF ; + si_code =FPE_FLTOVF ;else if (fcr31 &FPU_CSR_UDF_X ) - si.si_code =FPE_FLTUND ; + si_code =FPE_FLTUND ;else if (fcr31 &FPU_CSR_INE_X ) - si.si_code =FPE_FLTRES ; + si_code =FPE_FLTRES ; -force_sig_info (SIGFPE , &si, tsk); +force_sig_fault (SIGFPE , si_code, fault_addr, tsk); }int process_fpemu_return (int sig,void __user *fault_addr,unsigned long fcr31) { -struct siginfo si; +int si_code;struct vm_area_struct *vma; -clear_siginfo (&si);switch (sig) {case 0 :return 0 ;@@ -757,23 +746,18 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)return 1 ;case SIGBUS : - si.si_addr = fault_addr; - si.si_signo = sig; - si.si_code =BUS_ADRERR ; -force_sig_info (sig, &si, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , fault_addr, current);return 1 ;case SIGSEGV : - si.si_addr = fault_addr; - si.si_signo = sig;down_read (¤t->mm->mmap_sem); vma =find_vma (current->mm, (unsigned long )fault_addr);if (vma && (vma->vm_start <= (unsigned long )fault_addr)) - si.si_code =SEGV_ACCERR ; + si_code =SEGV_ACCERR ;else - si.si_code =SEGV_MAPERR ; + si_code =SEGV_MAPERR ;up_read (¤t->mm->mmap_sem); -force_sig_info (sig, &si, current); +force_sig_fault (SIGSEGV , si_code, fault_addr, current);return 1 ;default :@@ -896,10 +880,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)void do_trap_or_bp (struct pt_regs *regs,unsigned int code,int si_code,const char *str) { -siginfo_t info;char b[40 ]; -clear_siginfo (&info);#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap (DIE_TRAP , str, regs, code, current->thread.trap_nr,SIGTRAP ) ==NOTIFY_STOP )@@ -921,13 +903,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,case BRK_DIVZERO :scnprintf (b,sizeof (b),"%s instruction in kernel code" , str);die_if_kernel (b, regs); -if (code ==BRK_DIVZERO ) - info.si_code =FPE_INTDIV ; -else - info.si_code =FPE_INTOVF ; - info.si_signo =SIGFPE ; - info.si_addr = (void __user *) regs->cp0_epc; -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE , + code ==BRK_DIVZERO ?FPE_INTDIV :FPE_INTOVF , + (void __user *) regs->cp0_epc, current);break ;case BRK_BUG :die_if_kernel ("Kernel bug detected" , regs);@@ -952,9 +930,7 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,scnprintf (b,sizeof (b),"%s instruction in kernel code" , str);die_if_kernel (b, regs);if (si_code) { - info.si_signo =SIGTRAP ; - info.si_code = si_code; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP , si_code,NULL , current); }else {force_sig (SIGTRAP , current); }@@ -1506,13 +1482,8 @@ asmlinkage void do_mdmx(struct pt_regs *regs)*/ asmlinkage void do_watch(struct pt_regs *regs) { -siginfo_t info;enum ctx_state prev_state; -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_code =TRAP_HWBKPT ; - prev_state =exception_enter ();/* * Clear WP (bit 22) bit of cause register so we don't loop @@ -1528,7 +1499,7 @@ asmlinkage void do_watch(struct pt_regs *regs)if (test_tsk_thread_flag (current,TIF_LOAD_WATCH )) {mips_read_watch_registers ();local_irq_enable (); -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_HWBKPT ,NULL , current); }else {mips_clear_watch_registers ();local_irq_enable ();arch/mips/mm/fault.c +5
-14@@ -42,7 +42,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,struct task_struct *tsk = current;struct mm_struct *mm = tsk->mm;const int field =sizeof (unsigned long ) *2 ; -siginfo_t info; +int si_code;int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ;@@ -63,8 +63,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,return ;#endif -clear_siginfo (&info); - info.si_code =SEGV_MAPERR ; + si_code =SEGV_MAPERR ;/* * We fault-in kernel-space virtual memory on-demand. The @@ -113,7 +112,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,* we can handle it.. */ good_area: - info.si_code =SEGV_ACCERR ; + si_code =SEGV_ACCERR ;if (write) {if (!(vma->vm_flags &VM_WRITE ))@@ -224,11 +223,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,pr_cont ("\n" ); } current->thread.trap_nr = (regs->cp0_cause >>2 ) &0x1f ; - info.si_signo =SIGSEGV ; - info.si_errno =0 ; -/* info.si_code has been set above */ - info.si_addr = (void __user *) address; -force_sig_info (SIGSEGV , &info, tsk); +force_sig_fault (SIGSEGV , si_code, (void __user *)address, tsk);return ; }@@ -284,11 +279,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,#endif current->thread.trap_nr = (regs->cp0_cause >>2 ) &0x1f ; tsk->thread.cp0_badvaddr = address; - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void __user *) address; -force_sig_info (SIGBUS , &info, tsk); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, tsk);return ;#ifndef CONFIG_64BIT
Re: [REVIEW][PATCH 08/22] signal/mips: Use force_sig_fault where appropriate
Quoted 58 lines · Matt Redfearn
Hi Eric,
Quoted 41 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Ralf Baechle <[email protected]>Cc James Hogan <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/mips/kernel/traps.c | 65 ++++++++++++++---------------------------------- arch/mips/mm/fault.c | 19 ++++---------- 2 files changed, 23 insertions(+), 61 deletions(-)arch/mips/kernel/traps.c +1
-6@@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) {enum ctx_state prev_state; -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_code =FPE_INTOVF ; - info.si_addr = (void __user *)regs->cp0_epc; prev_state =exception_enter ();die_if_kernel ("Integer overflow" , regs); -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , (void __user *)regs->cp0_epc, current);exception_exit (prev_state); }arch/mips/kernel/traps.c static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
Quoted 10 lines
arch/mips/kernel/traps.c +1
-5@@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs) void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, struct task_struct *tsk) { -struct siginfo si; - -clear_siginfo (&si); - si.si_addr = fault_addr; - si.si_signo =SIGFPE ; +int si_code;This is giving build errors in Linux next
(https://storage.kernelci.org/next/master/next-20180509/mips/defconfig+kselftest/build.log)
Quoted 1 line
si_codewould have ended up as 0 before from theclear_siginfo(), but perhaps
And si_code 0 is not a valid si_code to use with a floating point siginfo layout.
Quoted 3 lines
int
si_code=FPE_FLTUNK;Would make a more sensible default?
FPE_FLTUNK would make a more sensible default.
I seem to remember someone telling me that case can never happen in practice so I have simply not worried about it. Perhaps I am misremembering this.
Eric
Re: [REVIEW][PATCH 08/22] signal/mips: Use force_sig_fault where appropriate
Hi Eric,
Quoted 67 lines · Eric W. Biederman
Quoted 58 lines · Matt Redfearn
Hi Eric,
Quoted 41 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Ralf Baechle <[email protected]>Cc James Hogan <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/mips/kernel/traps.c | 65 ++++++++++++++---------------------------------- arch/mips/mm/fault.c | 19 ++++---------- 2 files changed, 23 insertions(+), 61 deletions(-)arch/mips/kernel/traps.c +1
-6@@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) {enum ctx_state prev_state; -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_code =FPE_INTOVF ; - info.si_addr = (void __user *)regs->cp0_epc; prev_state =exception_enter ();die_if_kernel ("Integer overflow" , regs); -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , (void __user *)regs->cp0_epc, current);exception_exit (prev_state); }arch/mips/kernel/traps.c static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
Quoted 10 lines
arch/mips/kernel/traps.c +1
-5@@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs) void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, struct task_struct *tsk) { -struct siginfo si; - -clear_siginfo (&si); - si.si_addr = fault_addr; - si.si_signo =SIGFPE ; +int si_code;This is giving build errors in Linux next
(https://storage.kernelci.org/next/master/next-20180509/mips/defconfig+kselftest/build.log)Quoted 1 line
si_codewould have ended up as 0 before from theclear_siginfo(), but perhapsAnd
si_code0 is not a validsi_codeto use with a floating point siginfo layout.Quoted 2 lines
int
si_code=FPE_FLTUNK;
Quoted 7 lines
Quoted 1 line
Would make a more sensible default?
FPE_FLTUNKwould make a more sensible default.I seem to remember someone telling me that case can never happen in practice so I have simply not worried about it. Perhaps I am misremembering this.
It probably can't happen in practise - but the issue is that the kernel doesn't even compile because -Werror=maybe-uninitialized results in a build error since the compiler can't know that one of the branches will definitely be taken to set si_code.
Thanks,
Matt
Quoted 3 lines
Eric
Re: [REVIEW][PATCH 08/22] signal/mips: Use force_sig_fault where appropriate
Quoted 74 lines · Matt Redfearn
Hi Eric,
Quoted 71 lines · Eric W. Biederman
Quoted 58 lines · Matt Redfearn
Hi Eric,
Quoted 41 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Ralf Baechle <[email protected]>Cc James Hogan <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/mips/kernel/traps.c | 65 ++++++++++++++---------------------------------- arch/mips/mm/fault.c | 19 ++++---------- 2 files changed, 23 insertions(+), 61 deletions(-)arch/mips/kernel/traps.c +1
-6@@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) {enum ctx_state prev_state; -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_code =FPE_INTOVF ; - info.si_addr = (void __user *)regs->cp0_epc; prev_state =exception_enter ();die_if_kernel ("Integer overflow" , regs); -force_sig_info (SIGFPE , &info, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , (void __user *)regs->cp0_epc, current);exception_exit (prev_state); }arch/mips/kernel/traps.c static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
Quoted 10 lines
arch/mips/kernel/traps.c +1
-5@@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs) void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, struct task_struct *tsk) { -struct siginfo si; - -clear_siginfo (&si); - si.si_addr = fault_addr; - si.si_signo =SIGFPE ; +int si_code;This is giving build errors in Linux next
(https://storage.kernelci.org/next/master/next-20180509/mips/defconfig+kselftest/build.log)Quoted 1 line
si_codewould have ended up as 0 before from theclear_siginfo(), but perhapsAnd
si_code0 is not a validsi_codeto use with a floating point siginfo layout.Quoted 3 lines
int
si_code=FPE_FLTUNK;Would make a more sensible default?
FPE_FLTUNKwould make a more sensible default.
Quoted 8 lines
Quoted 3 lines
I seem to remember someone telling me that case can never happen in practice so I have simply not worried about it. Perhaps I am misremembering this.
It probably can't happen in practise - but the issue is that the kernel doesn't even compile because -Werror=maybe-uninitialized results in a build error since the compiler can't know that one of the branches will definitely be taken to set
si_code.
My cross compile work. So I don't know where that -Werror=maybe-unitialized comes from.
I agree it is an issue. I agree that FPE_FLTUNK is one of the good
solutions. Another is to add a final else where you return without doing anything.
Right now this looks like mips people issue that I have unearthed. I could appreciate some guidance on which way mips folks would like to handle this.
If you can point me to where the fatal error is coming from I will definitely do something in my tree so that this is not a harmful issue.
Eric
PATCH 9/22 signal/nds32: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/nds32/kernel/traps.c | 20 ++++---------------- arch/nds32/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 30 deletions(-)
arch/nds32/kernel/traps.c +4 -16
@@ -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,
arch/nds32/mm/fault.c +5 -14
@@ -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 @@ void do_page_fault(unsigned long entry, unsigned long addr,*/ 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 @@ void do_page_fault(unsigned long entry, unsigned long addr, 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 @@ void do_page_fault(unsigned long entry, unsigned long addr, 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 ;
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 09/22] signal/nds32: Use force_sig_fault where appropriate
2018-04-20 22:37 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 55 lines
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Greentime Hu <[email protected]>Cc Vincent Chen <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/nds32/kernel/traps.c | 20 ++++---------------- arch/nds32/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 30 deletions(-)arch/nds32/kernel/traps.c +2
-11@@ -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;
arch/nds32/kernel/traps.c void __init early_trap_init(void) · line 290
Quoted 10 lines
arch/nds32/kernel/traps.c +2
-5-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); }
I found a comma is missing after argument si_code.
Quoted 60 lines
arch/nds32/kernel/traps.c +0
-0void do_debug_trap(unsigned long entry, unsigned long addr,arch/nds32/mm/fault.c +5
-15@@ -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 @@ void do_page_fault(unsigned long entry, unsigned long addr,*/ 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 @@ void do_page_fault(unsigned long entry, unsigned long addr, 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 @@ void do_page_fault(unsigned long entry, unsigned long addr, 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 ; --
Quoted 2 lines
2.14.1
Except the missing comma in send_sigtrap(), I think this patch for nds32 is OK.
Vincent Chen
Re: [REVIEW][PATCH 09/22] signal/nds32: Use force_sig_fault where appropriate
Quoted 57 lines · Vincent Chen
2018-04-20 22:37 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 56 lines
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Greentime Hu <[email protected]>Cc Vincent Chen <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/nds32/kernel/traps.c | 20 ++++---------------- arch/nds32/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 30 deletions(-)arch/nds32/kernel/traps.c +2
-11@@ -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;
Quoted 11 lines
arch/nds32/kernel/traps.c void __init early_trap_init(void) · line 290
Quoted 9 lines
arch/nds32/kernel/traps.c +2
-5-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); }I found a comma is missing after argument
si_code.
Good catch. Fixed.
Unfortunately the only compiler I have for nds32 is my eyeballs so this slipped through. Grr.
Quoted 2 lines
Except the missing comma in
send_sigtrap(), I think this patch for nds32 is OK.
I have corrected the change as you suggested and have added your Acked by.
Eric
Re: [REVIEW][PATCH 09/22] signal/nds32: Use force_sig_fault where appropriate
2018-04-25 23:57 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 71 lines
Quoted 57 lines · Vincent Chen
2018-04-20 22:37 GMT+08:00 Eric W. Biederman <[email protected]>:
Quoted 56 lines
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Greentime Hu <[email protected]>Cc Vincent Chen <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/nds32/kernel/traps.c | 20 ++++---------------- arch/nds32/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 30 deletions(-)arch/nds32/kernel/traps.c +2
-11@@ -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;Quoted 11 lines
arch/nds32/kernel/traps.c void __init early_trap_init(void) · line 290
Quoted 9 lines
arch/nds32/kernel/traps.c +2
-5-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); }I found a comma is missing after argument
si_code.
Quoted 6 lines
Good catch. Fixed.
Unfortunately the only compiler I have for nds32 is my eyeballs so this slipped through. Grr.
Sorry for that. Our nds32 toolchain upstreaming is on-going. You may try this one. It is able to build defconfig and allnoconfig
https://lkml.org/lkml/2018/4/17/395
https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/6.4.0/x86_64-gcc-6.4.0-nolibc-nds32le-linux.tar.xz
or this one with glibc support
https://github.com/andestech/build_script.git
https://github.com/greentime/prebuilt-nds32-toolchain/releases
PATCH 10/22 signal/nios2: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/nios2/kernel/traps.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
arch/nios2/kernel/traps.c +1 -8
@@ -26,14 +26,7 @@ static DEFINE_SPINLOCK(die_lock);static void _send_sig (int signo,int code,unsigned long addr) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo = signo; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *) addr; -force_sig_info (signo, &info, current); +force_sig_fault (signo, code, (void __user *) addr, current); }void die (const char *str,struct pt_regs *regs,long err)
Signature · 1 line
2.14.1
PATCH 11/22 signal/openrisc: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/openrisc/kernel/traps.c | 33 ++++----------------------------- arch/openrisc/mm/fault.c | 19 +++++-------------- 2 files changed, 9 insertions(+), 43 deletions(-)
arch/openrisc/kernel/traps.c +4 -29
@@ -250,28 +250,16 @@ void __init trap_init(void) asmlinkage void do_trap(struct pt_regs *regs, unsigned long address) { -siginfo_t info; -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_code =TRAP_TRACE ; - info.si_addr = (void *)address; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_TRACE , (void __user *)address, current); regs->pc +=4 ; } asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) { -siginfo_t info; -if (user_mode (regs)) {/* Send a SIGBUS */ -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRALN ; - info.si_addr = (void __user *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRALN , (void __user *)address, current); }else {printk ("KERNEL: Unaligned Access 0x%.8lx\n" , address);show_registers (regs);
@@ -282,16 +270,9 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address) { -siginfo_t info; -if (user_mode (regs)) {/* Send a SIGBUS */ -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, current); }else {/* Kernel mode */ printk ("KERNEL: Bus error (SIGBUS) 0x%.8lx\n" , address);show_registers (regs);
@@ -466,7 +447,6 @@ static inline void simulate_swa(struct pt_regs *regs, unsigned long address, asmlinkage void do_illegal_instruction(struct pt_regs *regs,unsigned long address) { -siginfo_t info;unsigned int op;unsigned int insn = *((unsigned int *)address);
@@ -487,12 +467,7 @@ asmlinkage void do_illegal_instruction(struct pt_regs *regs,if (user_mode (regs)) {/* Send a SIGILL */ -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_ILLOPC ; - info.si_addr = (void *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGILL ,ILL_ILLOPC , (void __user *)address, current); }else {/* Kernel mode */ printk ("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n" , address);
arch/openrisc/mm/fault.c +5 -14
@@ -52,11 +52,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,struct task_struct *tsk;struct mm_struct *mm;struct vm_area_struct *vma; -siginfo_t info; +int si_code;int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; -clear_siginfo (&info); tsk = current;/*
@@ -98,7 +97,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, } mm = tsk->mm; - info.si_code =SEGV_MAPERR ; + si_code =SEGV_MAPERR ;/* * If we're in an interrupt or have no user
@@ -140,7 +139,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,*/ good_area: - info.si_code =SEGV_ACCERR ; + si_code =SEGV_ACCERR ;/* first do some preliminary protection checks */
@@ -214,11 +213,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,/* User mode accesses just cause a SIGSEGV */ if (user_mode (regs)) { - info.si_signo =SIGSEGV ; - info.si_errno =0 ; -/* info.si_code has been set above */ - info.si_addr = (void *)address; -force_sig_info (SIGSEGV , &info, tsk); +force_sig_fault (SIGSEGV , si_code, (void __user *)address, tsk);return ; }
@@ -283,11 +278,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,* Send a sigbus, regardless of whether we were in kernel * or user mode. */ - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void *)address; -force_sig_info (SIGBUS , &info, tsk); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, tsk);/* Kernel mode? Handle exceptions or die */ if (!user_mode (regs))
Signature · 1 line
2.14.1
PATCH 12/22 signal/parisc: Use force_sig_mceerr where appropriate
In reply to Eric W. BiedermanIn do_page_fault where an mceerr is generated stop and call force_sig_mceerr. Keeping the mcerr handling logic out of the force_sig_info call below.
This ensures that only and always in the mcerr case is lsb interesting.
This ensures setting set si_lsb in the future won't accidentally stomp another siginfo field in the non mcerr case.
--- arch/parisc/mm/fault.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
arch/parisc/mm/fault.c +15 -15
@@ -354,7 +354,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,if (user_mode (regs)) {struct siginfo si; -unsigned int lsb =0 ;clear_siginfo (&si);switch (code) {
@@ -391,26 +390,27 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,#ifdef CONFIG_MEMORY_FAILURE if (fault & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) { +unsigned int lsb =0 ;printk (KERN_ERR "MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n" , tsk->comm, tsk->pid, address); - si.si_signo =SIGBUS ; - si.si_code =BUS_MCEERR_AR ; +/* +* Either small page or large page may be poisoned. +* In other words, VM_FAULT_HWPOISON_LARGE and +* VM_FAULT_HWPOISON are mutually exclusive. +*/ +if (fault &VM_FAULT_HWPOISON_LARGE ) + lsb =hstate_index_to_shift (VM_FAULT_GET_HINDEX (fault)); +else if (fault &VM_FAULT_HWPOISON ) + lsb =PAGE_SHIFT ; + +force_sig_mceerr (BUS_MCEERR_AR , (void __user *) address, + lsb, current); +return ; }#endif -/* -* Either small page or large page may be poisoned. -* In other words, VM_FAULT_HWPOISON_LARGE and -* VM_FAULT_HWPOISON are mutually exclusive. -*/ -if (fault &VM_FAULT_HWPOISON_LARGE ) - lsb =hstate_index_to_shift (VM_FAULT_GET_HINDEX (fault)); -else if (fault &VM_FAULT_HWPOISON ) - lsb =PAGE_SHIFT ; -else -show_signal_msg (regs, code, address, tsk, vma); - si.si_addr_lsb = lsb; +show_signal_msg (regs, code, address, tsk, vma); si.si_errno =0 ; si.si_addr = (void __user *) address;
Signature · 1 line
2.14.1
PATCH 13/22 signal/parisc: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/parisc/kernel/ptrace.c | 11 ++------ arch/parisc/kernel/traps.c | 63 ++++++++++++++---------------------------- arch/parisc/kernel/unaligned.c | 16 +++-------- arch/parisc/math-emu/driver.c | 9 ++---- arch/parisc/mm/fault.c | 25 +++++++---------- 5 files changed, 39 insertions(+), 85 deletions(-)
arch/parisc/kernel/ptrace.c +3 -8
@@ -76,8 +76,6 @@ void user_enable_single_step(struct task_struct *task)set_tsk_thread_flag (task,TIF_SINGLESTEP );if (pa_psw (task)->n) { -struct siginfo si; -/* Nullified, just crank over the queue. */ task_regs (task)->iaoq[0 ] =task_regs (task)->iaoq[1 ];task_regs (task)->iasq[0 ] =task_regs (task)->iasq[1 ];
@@ -90,12 +88,9 @@ void user_enable_single_step(struct task_struct *task)ptrace_disable (task);/* Don't wake up the task, but let the parent know something happened. */ -clear_siginfo (&si); - si.si_code =TRAP_TRACE ; - si.si_addr = (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ); - si.si_signo =SIGTRAP ; - si.si_errno =0 ; -force_sig_info (SIGTRAP , &si, task); +force_sig_fault (SIGTRAP ,TRAP_TRACE , + (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ), + task);/* notify_parent(task, SIGCHLD); */ return ; }
arch/parisc/kernel/traps.c +20 -43
126 lines not on this page · raw message
arch/parisc/kernel/unaligned.c +4 -12
@@ -452,10 +452,8 @@ void handle_unaligned(struct pt_regs *regs)unsigned long newbase =R1 (regs->iir)?regs->gr[R1 (regs->iir)]:0 ;int modify =0 ;int ret =ERR_NOTHANDLED ; -struct siginfo si; registerint flop=0 ;/* true if this is a flop */ -clear_siginfo (&si);__inc_irq_stat (irq_unaligned_count);/* log a message with pacing */
@@ -691,21 +689,15 @@ void handle_unaligned(struct pt_regs *regs)if (ret ==ERR_PAGEFAULT ) { - si.si_signo =SIGSEGV ; - si.si_errno =0 ; - si.si_code =SEGV_MAPERR ; - si.si_addr = (void __user *)regs->ior; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV ,SEGV_MAPERR , + (void __user *)regs->ior, current); }else { force_sigbus:/* couldn't handle it ... */ - si.si_signo =SIGBUS ; - si.si_errno =0 ; - si.si_code =BUS_ADRALN ; - si.si_addr = (void __user *)regs->ior; -force_sig_info (SIGBUS , &si, current); +force_sig_fault (SIGBUS ,BUS_ADRALN , + (void __user *)regs->ior, current); }return ;
arch/parisc/math-emu/driver.c +2 -7
@@ -81,7 +81,6 @@ int handle_fpe(struct pt_regs *regs) {extern void printbinary (unsigned long x,int nbits); -struct siginfo si;unsigned int orig_sw, sw;int signalcode;/* need an intermediate copy of float regs because FPU emulation
@@ -93,7 +92,6 @@ handle_fpe(struct pt_regs *regs)*/ __u64 frcopy[36 ]; -clear_siginfo (&si);memcpy (frcopy, regs->fr,sizeof regs->fr); frcopy[32 ] =0 ;
@@ -118,11 +116,8 @@ handle_fpe(struct pt_regs *regs)memcpy (regs->fr, frcopy,sizeof regs->fr);if (signalcode !=0 ) { - si.si_signo = signalcode >>24 ; - si.si_errno =0 ; - si.si_code = signalcode &0xffffff ; - si.si_addr = (void __user *) regs->iaoq[0 ]; -force_sig_info (si.si_signo, &si, current); +force_sig_fault (signalcode >>24 , signalcode &0xffffff , + (void __user *) regs->iaoq[0 ], current);return -1 ; }
arch/parisc/mm/fault.c +10 -15
@@ -353,23 +353,22 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,up_read (&mm->mmap_sem);if (user_mode (regs)) { -struct siginfo si; +int signo, si_code; -clear_siginfo (&si);switch (code) {case 15 :/* Data TLB miss fault/Data page fault */ /* send SIGSEGV when outside of vma */ if (!vma || address < vma->vm_start || address >= vma->vm_end) { - si.si_signo =SIGSEGV ; - si.si_code =SEGV_MAPERR ; + signo =SIGSEGV ; + si_code =SEGV_MAPERR ;break ; }/* send SIGSEGV for wrong permissions */ if ((vma->vm_flags & acc_type) != acc_type) { - si.si_signo =SIGSEGV ; - si.si_code =SEGV_ACCERR ; + signo =SIGSEGV ; + si_code =SEGV_ACCERR ;break ; }
@@ -377,17 +376,16 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,/* fall through */ case 17 :/* NA data TLB miss / page fault */ case 18 :/* Unaligned access - PCXS only */ - si.si_signo =SIGBUS ; - si.si_code = (code ==18 ) ?BUS_ADRALN :BUS_ADRERR ; + signo =SIGBUS ; + si_code = (code ==18 ) ?BUS_ADRALN :BUS_ADRERR ;break ;case 16 :/* Non-access instruction TLB miss fault */ case 26 :/* PCXL: Data memory access rights trap */ default : - si.si_signo =SIGSEGV ; - si.si_code = (code ==26 ) ?SEGV_ACCERR :SEGV_MAPERR ; + signo =SIGSEGV ; + si_code = (code ==26 ) ?SEGV_ACCERR :SEGV_MAPERR ;break ; } -#ifdef CONFIG_MEMORY_FAILURE if (fault & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) {unsigned int lsb =0 ;
@@ -409,12 +407,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, return; }#endif -show_signal_msg (regs, code, address, tsk, vma); - si.si_errno =0 ; - si.si_addr = (void __user *) address; -force_sig_info (si.si_signo, &si, current); +force_sig_fault (signo, si_code, (void __user *) address, current);return ; }
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 13/22] signal/parisc: Use force_sig_fault where appropriate
Quoted 9 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.
Quoted 7 lines
In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc James Bottomley <[email protected]>Cc Helge Deller <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>
I pulled this whole patch series from your git tree and booted it on 32- and 64-bit parisc kernels.
Thanks!
Helge
Quoted 321 lines
--- arch/parisc/kernel/ptrace.c | 11 ++------ arch/parisc/kernel/traps.c | 63 ++++++++++++++---------------------------- arch/parisc/kernel/unaligned.c | 16 +++-------- arch/parisc/math-emu/driver.c | 9 ++---- arch/parisc/mm/fault.c | 25 +++++++---------- 5 files changed, 39 insertions(+), 85 deletions(-)arch/parisc/kernel/ptrace.c +3
-8@@ -76,8 +76,6 @@ void user_enable_single_step(struct task_struct *task)set_tsk_thread_flag (task,TIF_SINGLESTEP );if (pa_psw (task)->n) { -struct siginfo si; -/* Nullified, just crank over the queue. */ task_regs (task)->iaoq[0 ] =task_regs (task)->iaoq[1 ];task_regs (task)->iasq[0 ] =task_regs (task)->iasq[1 ];@@ -90,12 +88,9 @@ void user_enable_single_step(struct task_struct *task)ptrace_disable (task);/* Don't wake up the task, but let the parent know something happened. */ -clear_siginfo (&si); - si.si_code =TRAP_TRACE ; - si.si_addr = (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ); - si.si_signo =SIGTRAP ; - si.si_errno =0 ; -force_sig_info (SIGTRAP , &si, task); +force_sig_fault (SIGTRAP ,TRAP_TRACE , + (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ), + task);/* notify_parent(task, SIGCHLD); */ return ; }arch/parisc/kernel/traps.c +20
-43@@ -297,14 +297,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)#define GDB_BREAK_INSN 0x10004static void handle_gdb_break (struct pt_regs *regs,int wot) { -struct siginfo si; - -clear_siginfo (&si); - si.si_signo =SIGTRAP ; - si.si_errno =0 ; - si.si_code = wot; - si.si_addr = (void __user *) (regs->iaoq[0 ] & ~3 ); -force_sig_info (SIGTRAP , &si, current); +force_sig_fault (SIGTRAP , wot, + (void __user *) (regs->iaoq[0 ] & ~3 ), current); }static void handle_break (struct pt_regs *regs)@@ -488,9 +482,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs) {unsigned long fault_address =0 ;unsigned long fault_space =0 ; -struct siginfo si; +int si_code; -clear_siginfo (&si);if (code ==1 )pdc_console_restart ();/* switch back to pdc if HPMC */ else @@ -573,7 +566,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)case 8 :/* Illegal instruction trap */ die_if_kernel ("Illegal instruction" , regs, code); - si.si_code =ILL_ILLOPC ; + si_code =ILL_ILLOPC ; goto give_sigill;case 9 :@@ -584,7 +577,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)case 10 :/* Privileged operation trap */ die_if_kernel ("Privileged operation" , regs, code); - si.si_code =ILL_PRVOPC ; + si_code =ILL_PRVOPC ; goto give_sigill;case 11 :@@ -607,20 +600,16 @@ void notrace handle_interruption(int code, struct pt_regs *regs) }die_if_kernel ("Privileged register usage" , regs, code); - si.si_code =ILL_PRVREG ; + si_code =ILL_PRVREG ; give_sigill: - si.si_signo =SIGILL ; - si.si_errno =0 ; - si.si_addr = (void __user *) regs->iaoq[0 ]; -force_sig_info (SIGILL , &si, current); +force_sig_fault (SIGILL , si_code, + (void __user *) regs->iaoq[0 ], current);return ;case 12 :/* Overflow Trap, let the userland signal handler do the cleanup */ - si.si_signo =SIGFPE ; - si.si_code =FPE_INTOVF ; - si.si_addr = (void __user *) regs->iaoq[0 ]; -force_sig_info (SIGFPE , &si, current); +force_sig_fault (SIGFPE ,FPE_INTOVF , + (void __user *) regs->iaoq[0 ], current);return ;case 13 :@@ -628,13 +617,11 @@ void notrace handle_interruption(int code, struct pt_regs *regs)The condition succeeds in an instruction which traps on condition */ if (user_mode (regs)){ - si.si_signo =SIGFPE ;/* Let userspace app figure it out from the insn pointed * to by si_addr. */ - si.si_code =FPE_CONDTRAP ; - si.si_addr = (void __user *) regs->iaoq[0 ]; -force_sig_info (SIGFPE , &si, current); +force_sig_fault (SIGFPE ,FPE_CONDTRAP , + (void __user *) regs->iaoq[0 ], current);return ; }/* The kernel doesn't want to handle condition codes */ @@ -743,14 +730,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)return ;die_if_kernel ("Protection id trap" , regs, code); - si.si_code =SEGV_MAPERR ; - si.si_signo =SIGSEGV ; - si.si_errno =0 ; -if (code ==7 ) - si.si_addr = (void __user *) regs->iaoq[0 ]; -else - si.si_addr = (void __user *) regs->ior; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV ,SEGV_MAPERR , + (code ==7 )? + ((void __user *) regs->iaoq[0 ]) : + ((void __user *) regs->ior), current);return ;case 28 :@@ -764,11 +747,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)"handle_interruption() pid=%d command='%s'\n" , task_pid_nr(current), current->comm);/* SIGBUS, for lack of a better one. */ - si.si_signo =SIGBUS ; - si.si_code =BUS_OBJERR ; - si.si_errno =0 ; - si.si_addr = (void __user *) regs->ior; -force_sig_info (SIGBUS , &si, current); +force_sig_fault (SIGBUS ,BUS_OBJERR , + (void __user *)regs->ior, current);return ; }pdc_chassis_send_status (PDC_CHASSIS_DIRECT_PANIC );@@ -783,11 +763,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)"User fault %d on space 0x%08lx, pid=%d command='%s'\n" , code, fault_space, task_pid_nr(current), current->comm); - si.si_signo =SIGSEGV ; - si.si_errno =0 ; - si.si_code =SEGV_MAPERR ; - si.si_addr = (void __user *) regs->ior; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV ,SEGV_MAPERR , + (void __user *)regs->ior, current);return ; } }arch/parisc/kernel/unaligned.c +4
-12@@ -452,10 +452,8 @@ void handle_unaligned(struct pt_regs *regs)unsigned long newbase =R1 (regs->iir)?regs->gr[R1 (regs->iir)]:0 ;int modify =0 ;int ret =ERR_NOTHANDLED ; -struct siginfo si; registerint flop=0 ;/* true if this is a flop */ -clear_siginfo (&si);__inc_irq_stat (irq_unaligned_count);/* log a message with pacing */ @@ -691,21 +689,15 @@ void handle_unaligned(struct pt_regs *regs)if (ret ==ERR_PAGEFAULT ) { - si.si_signo =SIGSEGV ; - si.si_errno =0 ; - si.si_code =SEGV_MAPERR ; - si.si_addr = (void __user *)regs->ior; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV ,SEGV_MAPERR , + (void __user *)regs->ior, current); }else { force_sigbus:/* couldn't handle it ... */ - si.si_signo =SIGBUS ; - si.si_errno =0 ; - si.si_code =BUS_ADRALN ; - si.si_addr = (void __user *)regs->ior; -force_sig_info (SIGBUS , &si, current); +force_sig_fault (SIGBUS ,BUS_ADRALN , + (void __user *)regs->ior, current); }return ;arch/parisc/math-emu/driver.c +2
-7@@ -81,7 +81,6 @@ int handle_fpe(struct pt_regs *regs) {extern void printbinary (unsigned long x,int nbits); -struct siginfo si;unsigned int orig_sw, sw;int signalcode;/* need an intermediate copy of float regs because FPU emulation @@ -93,7 +92,6 @@ handle_fpe(struct pt_regs *regs)*/ __u64 frcopy[36 ]; -clear_siginfo (&si);memcpy (frcopy, regs->fr,sizeof regs->fr); frcopy[32 ] =0 ;@@ -118,11 +116,8 @@ handle_fpe(struct pt_regs *regs)memcpy (regs->fr, frcopy,sizeof regs->fr);if (signalcode !=0 ) { - si.si_signo = signalcode >>24 ; - si.si_errno =0 ; - si.si_code = signalcode &0xffffff ; - si.si_addr = (void __user *) regs->iaoq[0 ]; -force_sig_info (si.si_signo, &si, current); +force_sig_fault (signalcode >>24 , signalcode &0xffffff , + (void __user *) regs->iaoq[0 ], current);return -1 ; }arch/parisc/mm/fault.c +10
-15@@ -353,23 +353,22 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,up_read (&mm->mmap_sem);if (user_mode (regs)) { -struct siginfo si; +int signo, si_code; -clear_siginfo (&si);switch (code) {case 15 :/* Data TLB miss fault/Data page fault */ /* send SIGSEGV when outside of vma */ if (!vma || address < vma->vm_start || address >= vma->vm_end) { - si.si_signo =SIGSEGV ; - si.si_code =SEGV_MAPERR ; + signo =SIGSEGV ; + si_code =SEGV_MAPERR ;break ; }/* send SIGSEGV for wrong permissions */ if ((vma->vm_flags & acc_type) != acc_type) { - si.si_signo =SIGSEGV ; - si.si_code =SEGV_ACCERR ; + signo =SIGSEGV ; + si_code =SEGV_ACCERR ;break ; }@@ -377,17 +376,16 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,/* fall through */ case 17 :/* NA data TLB miss / page fault */ case 18 :/* Unaligned access - PCXS only */ - si.si_signo =SIGBUS ; - si.si_code = (code ==18 ) ?BUS_ADRALN :BUS_ADRERR ; + signo =SIGBUS ; + si_code = (code ==18 ) ?BUS_ADRALN :BUS_ADRERR ;break ;case 16 :/* Non-access instruction TLB miss fault */ case 26 :/* PCXL: Data memory access rights trap */ default : - si.si_signo =SIGSEGV ; - si.si_code = (code ==26 ) ?SEGV_ACCERR :SEGV_MAPERR ; + signo =SIGSEGV ; + si_code = (code ==26 ) ?SEGV_ACCERR :SEGV_MAPERR ;break ; } -#ifdef CONFIG_MEMORY_FAILURE if (fault & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) {unsigned int lsb =0 ;@@ -409,12 +407,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, return; }#endif -show_signal_msg (regs, code, address, tsk, vma); - si.si_errno =0 ; - si.si_addr = (void __user *) address; -force_sig_info (si.si_signo, &si, current); +force_sig_fault (signo, si_code, (void __user *) address, current);return ; }
PATCH 14/22 signal/riscv: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/riscv/kernel/traps.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
arch/riscv/kernel/traps.c +1 -8
@@ -66,14 +66,7 @@ void die(struct pt_regs *regs, const char *str)static inline void do_trap_siginfo (int signo,int code,unsigned long addr,struct task_struct *tsk) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo = signo; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *)addr; -force_sig_info (signo, &info, tsk); +force_sig_fault (signo, code, (void __user *)addr, tsk); } void do_trap(struct pt_regs *regs, int signo, int code,
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 14/22] signal/riscv: Use force_sig_fault where appropriate
Quoted 28 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Palmer Dabbelt <[email protected]>Cc Albert Ou <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/riscv/kernel/traps.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)arch/riscv/kernel/traps.c +0
-0@@ -66,14 +66,7 @@ void die(struct pt_regs *regs, const char *str)static inline void do_trap_siginfo (int signo,int code,unsigned long addr,struct task_struct *tsk) {
arch/riscv/kernel/traps.c void die(struct pt_regs *regs, const char *str) · line 70
Quoted 10 lines
arch/riscv/kernel/traps.c +1
-8-siginfo_t info; - -clear_siginfo (&info); - info.si_signo = signo; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *)addr; -force_sig_info (signo, &info, tsk); +force_sig_fault (signo, code, (void __user *)addr, tsk); }
Please kill the do_trap_siginfo helper and use force_sig_fault directly in both callers.
[REVIEW][PATCH 23/22] signal/riscv: Replace do_trap_siginfo with force_sig_fault
The function force_sig_fault is just the generic version of do_trap_siginfo with a (void __user *) instead of an unsigned long parameter for the address.
So just use force_sig_fault to simplify the code.
--- arch/riscv/kernel/traps.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
arch/riscv/kernel/traps.c +2 -8
@@ -63,12 +63,6 @@ void die(struct pt_regs *regs, const char *str)do_exit (SIGSEGV ); } -static inline void do_trap_siginfo (int signo,int code, -unsigned long addr,struct task_struct *tsk) -{ -force_sig_fault (signo, code, (void __user *)addr, tsk); -} -void do_trap (struct pt_regs *regs,int signo,int code,unsigned long addr,struct task_struct *tsk) {
@@ -81,7 +75,7 @@ void do_trap(struct pt_regs *regs, int signo, int code,show_regs (regs); } -do_trap_siginfo (signo, code, addr, tsk); +force_sig_fault (signo, code, (void __user *)addr, tsk); } static void do_trap_error(struct pt_regs *regs, int signo, int code,
@@ -143,7 +137,7 @@ asmlinkage void do_trap_break(struct pt_regs *regs) }#endif /* CONFIG_GENERIC_BUG */ -do_trap_siginfo (SIGTRAP ,TRAP_BRKPT , regs->sepc, current); +force_sig_fault (SIGTRAP ,TRAP_BRKPT , (void __user *)(regs->sepc), current); regs->sepc +=0x4 ; }
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 14/22] signal/riscv: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanQuoted 30 lines · On Fri, 20 Apr 2018 07:38:03 PDT (-0700), [email protected] wrote:
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Palmer Dabbelt <[email protected]>Cc Albert Ou <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/riscv/kernel/traps.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)arch/riscv/kernel/traps.c +0
-2@@ -66,14 +66,7 @@ void die(struct pt_regs *regs, const char *str)static inline void do_trap_siginfo (int signo,int code,unsigned long addr,struct task_struct *tsk) { -siginfo_t info; -
arch/riscv/kernel/traps.c void die(struct pt_regs *regs, const char *str) · line 72
Quoted 10 lines
arch/riscv/kernel/traps.c +1
-6-clear_siginfo (&info); - info.si_signo = signo; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *)addr; -force_sig_info (signo, &info, tsk); +force_sig_fault (signo, code, (void __user *)addr, tsk); } void do_trap(struct pt_regs *regs, int signo, int code,
If I understand this correctly, any change in behavior this causes would have been a bug on our end not filling out siginfo correctly? In that case then feel free to add an
Thanks!
Re: [REVIEW][PATCH 14/22] signal/riscv: Use force_sig_fault where appropriate
Quoted 40 lines · Palmer Dabbelt
Quoted 39 lines · On Fri, 20 Apr 2018 07:38:03 PDT (-0700), [email protected] wrote:
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Palmer Dabbelt <[email protected]>Cc Albert Ou <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/riscv/kernel/traps.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)arch/riscv/kernel/traps.c +1
-8@@ -66,14 +66,7 @@ void die(struct pt_regs *regs, const char *str)static inline void do_trap_siginfo (int signo,int code,unsigned long addr,struct task_struct *tsk) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo = signo; - info.si_errno =0 ; - info.si_code = code; - info.si_addr = (void __user *)addr; -force_sig_info (signo, &info, tsk); +force_sig_fault (signo, code, (void __user *)addr, tsk); }
Quoted 5 lines
arch/riscv/kernel/traps.c void die(struct pt_regs *regs, const char *str) · line 72
Quoted 1 line
arch/riscv/kernel/traps.c +0
-0void do_trap(struct pt_regs *regs, int signo, int code,If I understand this correctly, any change in behavior this causes would have been a bug on our end not filling out siginfo correctly? In that case then feel free to add an
If this change above causes any user visible changes it is a bug. As Christoph rightly pointed out force_sig_fault is simply the arch generic version of do_trap_siginfo.
Eric
PATCH 15/22 signal/s390: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/s390/kernel/traps.c | 32 ++++++-------------------------- arch/s390/mm/fault.c | 23 ++++++----------------- 2 files changed, 12 insertions(+), 43 deletions(-)
arch/s390/kernel/traps.c +6 -26
@@ -44,15 +44,8 @@ int is_valid_bugaddr(unsigned long addr)void do_report_trap (struct pt_regs *regs,int si_signo,int si_code,char *str) { -siginfo_t info; -if (user_mode (regs)) { -clear_siginfo (&info); - info.si_signo = si_signo; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr =get_trap_ip (regs); -force_sig_info (si_signo, &info, current); +force_sig_fault (si_signo, si_code,get_trap_ip (regs), current);report_user_fault (regs, si_signo,0 ); }else {const struct exception_table_entry *fixup;
@@ -81,19 +74,12 @@ NOKPROBE_SYMBOL(do_trap);void do_per_trap (struct pt_regs *regs) { -siginfo_t info; -if (notify_die (DIE_SSTEP ,"sstep" , regs,0 ,0 ,SIGTRAP ) ==NOTIFY_STOP )return ;if (!current->ptrace)return ; -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_HWBKPT ; - info.si_addr = - (void __force __user *) current->thread.per_event.address; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_HWBKPT , + (void __force __user *) current->thread.per_event.address, current); }NOKPROBE_SYMBOL (do_per_trap);
@@ -178,15 +164,9 @@ void illegal_op(struct pt_regs *regs)if (get_user (*((__u16 *) opcode), (__u16 __user *) location))return ;if (*((__u16 *) opcode) ==S390_BREAKPOINT_U16 ) { -if (current->ptrace) { -siginfo_t info; -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_BRKPT ; - info.si_addr = location; -force_sig_info (SIGTRAP , &info, current); - }else +if (current->ptrace) +force_sig_fault (SIGTRAP ,TRAP_BRKPT , location, current); +else signal =SIGILL ; #ifdef CONFIG_UPROBES }else if (*((__u16 *) opcode) ==UPROBE_SWBP_INSN ) {
arch/s390/mm/fault.c +6 -17
@@ -265,15 +265,10 @@ void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault)*/ static noinline void do_sigsegv(struct pt_regs *regs, int si_code) { -struct siginfo si; -report_user_fault (regs,SIGSEGV ,1 ); -clear_siginfo (&si); - si.si_signo =SIGSEGV ; - si.si_errno =0 ; - si.si_code = si_code; - si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK); -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV , si_code, + (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK), + current); } static noinline void do_no_context(struct pt_regs *regs)
@@ -317,19 +312,13 @@ static noinline void do_low_address(struct pt_regs *regs) static noinline void do_sigbus(struct pt_regs *regs) { -struct task_struct *tsk = current; -struct siginfo si; -/* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ -clear_siginfo (&si); - si.si_signo =SIGBUS ; - si.si_errno =0 ; - si.si_code =BUS_ADRERR ; - si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK); -force_sig_info (SIGBUS , &si, tsk); +force_sig_fault (SIGBUS ,BUS_ADRERR , + (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK), + current); } static noinline int signal_return(struct pt_regs *regs)
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 15/22] signal/s390: Use force_sig_fault where appropriate
Quoted 12 lines · On Fri, 20 Apr 2018 09:38:04 -0500 "Eric W. Biederman" <[email protected]>…
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.
Quoted 8 lines
Cc Martin Schwidefsky <[email protected]>Cc Heiko Carstens <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/s390/kernel/traps.c | 32 ++++++-------------------------- arch/s390/mm/fault.c | 23 ++++++----------------- 2 files changed, 12 insertions(+), 43 deletions(-)
Compiles & boots. Comparing old vs. new the same values are set in siginfo. Looks good.
Signature · 4 lines
blue skies, Martin. "Reality continues to ruin my life." - Calvin.
PATCH 16/22 signal/sh: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/sh/kernel/traps_32.c | 19 +++++-------------- arch/sh/math-emu/math.c | 9 ++------- arch/sh/mm/fault.c | 10 +--------- 3 files changed, 8 insertions(+), 30 deletions(-)
arch/sh/kernel/traps_32.c +5 -14
@@ -477,7 +477,6 @@ asmlinkage void do_address_error(struct pt_regs *regs, {unsigned long error_code =0 ;mm_segment_t oldfs; -siginfo_t info;insn_size_t instruction;int tmp;
@@ -537,12 +536,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,"access (PC %lx PR %lx)\n" , current->comm, regs->pc, regs->pr); -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void __user *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS , si_code, (void __user *)address, current); }else {inc_unaligned_kernel_access ();
@@ -599,20 +593,17 @@ int is_dsp_inst(struct pt_regs *regs)#ifdef CONFIG_CPU_SH2A asmlinkage void do_divide_error(unsigned long r4) { -siginfo_t info; +int code; -clear_siginfo (&info);switch (r4) {case TRAP_DIVZERO_ERROR : - info.si_code =FPE_INTDIV ; + code =FPE_INTDIV ;break ;case TRAP_DIVOVF_ERROR : - info.si_code =FPE_INTOVF ; + code =FPE_INTOVF ;break ; } - - info.si_signo =SIGFPE ; -force_sig_info (info.si_signo, &info, current); +force_sig_fault (SIGFPE , code,NULL , current); }#endif
arch/sh/math-emu/math.c +2 -7
@@ -507,7 +507,6 @@ static int ieee_fpe_handler(struct pt_regs *regs)unsigned short insn = *(unsigned short *)regs->pc;unsigned short finsn;unsigned long nextpc; -siginfo_t info;int nib[4 ] = { (insn >>12 ) &0xf , (insn >>8 ) &0xf ,
@@ -560,12 +559,8 @@ static int ieee_fpe_handler(struct pt_regs *regs) ~(FPSCR_CAUSE_MASK |FPSCR_FLAG_MASK );task_thread_info (tsk)->status |=TS_USEDFPU ; }else { -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_errno =0 ; - info.si_code =FPE_FLTINV ; - info.si_addr = (void __user *)regs->pc; -force_sig_info (SIGFPE , &info, tsk); +force_sig_fault (SIGFPE ,FPE_FLTINV , + (void __user *)regs->pc, tsk); } regs->pc = nextpc;
arch/sh/mm/fault.c +1 -9
@@ -42,15 +42,7 @@ static void force_sig_info_fault(int si_signo, int si_code, unsigned long address, struct task_struct *tsk) { - siginfo_t info; - -clear_siginfo (&info); - info.si_signo = si_signo; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void __user *)address; - -force_sig_info (si_signo, &info, tsk); + force_sig_fault(si_signo, si_code, (void __user *)address, tsk); }/*
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 16/22] signal/sh: Use force_sig_fault where appropriate
Quoted 123 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Yoshinori Sato <[email protected]>Cc Rich Felker <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/sh/kernel/traps_32.c | 19 +++++-------------- arch/sh/math-emu/math.c | 9 ++------- arch/sh/mm/fault.c | 10 +--------- 3 files changed, 8 insertions(+), 30 deletions(-)arch/sh/kernel/traps_32.c +5
-14@@ -477,7 +477,6 @@ asmlinkage void do_address_error(struct pt_regs *regs, {unsigned long error_code =0 ;mm_segment_t oldfs; -siginfo_t info;insn_size_t instruction;int tmp;@@ -537,12 +536,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,"access (PC %lx PR %lx)\n" , current->comm, regs->pc, regs->pr); -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void __user *)address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS , si_code, (void __user *)address, current); }else {inc_unaligned_kernel_access ();@@ -599,20 +593,17 @@ int is_dsp_inst(struct pt_regs *regs)#ifdef CONFIG_CPU_SH2A asmlinkage void do_divide_error(unsigned long r4) { -siginfo_t info; +int code; -clear_siginfo (&info);switch (r4) {case TRAP_DIVZERO_ERROR : - info.si_code =FPE_INTDIV ; + code =FPE_INTDIV ;break ;case TRAP_DIVOVF_ERROR : - info.si_code =FPE_INTOVF ; + code =FPE_INTOVF ;break ; } - - info.si_signo =SIGFPE ; -force_sig_info (info.si_signo, &info, current); +force_sig_fault (SIGFPE , code,NULL , current); }#endif arch/sh/math-emu/math.c +2
-7@@ -507,7 +507,6 @@ static int ieee_fpe_handler(struct pt_regs *regs)unsigned short insn = *(unsigned short *)regs->pc;unsigned short finsn;unsigned long nextpc; -siginfo_t info;int nib[4 ] = { (insn >>12 ) &0xf , (insn >>8 ) &0xf ,@@ -560,12 +559,8 @@ static int ieee_fpe_handler(struct pt_regs *regs) ~(FPSCR_CAUSE_MASK |FPSCR_FLAG_MASK );task_thread_info (tsk)->status |=TS_USEDFPU ; }else { -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_errno =0 ; - info.si_code =FPE_FLTINV ; - info.si_addr = (void __user *)regs->pc; -force_sig_info (SIGFPE , &info, tsk); +force_sig_fault (SIGFPE ,FPE_FLTINV , + (void __user *)regs->pc, tsk); } regs->pc = nextpc;arch/sh/mm/fault.c +1
-9@@ -42,15 +42,7 @@ static void force_sig_info_fault(int si_signo, int si_code, unsigned long address, struct task_struct *tsk) { - siginfo_t info; - -clear_siginfo (&info); - info.si_signo = si_signo; - info.si_errno =0 ; - info.si_code = si_code; - info.si_addr = (void __user *)address; - -force_sig_info (si_signo, &info, tsk); + force_sig_fault(si_signo, si_code, (void __user *)address, tsk); }/* Signature · 1 line
2.14.1
Geert Uytterhoeven
maintainerRe: [REVIEW][PATCH 16/22] signal/sh: Use force_sig_fault where appropriate
Quoted 28 lines · Rich Felker
Quoted 27 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Yoshinori Sato <[email protected]>Cc Rich Felker <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>arch/sh/kernel/traps_32.c +1
-1@@ -599,20 +593,17 @@ int is_dsp_inst(struct pt_regs *regs)#ifdef CONFIG_CPU_SH2A asmlinkage void do_divide_error(unsigned long r4) { -siginfo_t info; +int code;
Quoted 15 lines
Quoted 5 lines
arch/sh/kernel/traps_32.c +1
-2-clear_siginfo (&info);switch (r4) {case TRAP_DIVZERO_ERROR : - info.si_code =FPE_INTDIV ; + code =FPE_INTDIV ;arch/sh/kernel/traps_32.c int is_dsp_inst(struct pt_regs *regs) · line 606
Quoted 10 lines
arch/sh/kernel/traps_32.c +2
-4break ;case TRAP_DIVOVF_ERROR : - info.si_code =FPE_INTOVF ; + code =FPE_INTOVF ;break ; } - - info.si_signo =SIGFPE ; -force_sig_info (info.si_signo, &info, current); +force_sig_fault (SIGFPE , code,NULL , current);
/kisskb/src/arch/sh/kernel/traps_32.c:606:17: error: 'code' may be used uninitialized in this function [-Werror=uninitialized]
http://kisskb.ellerman.id.au/kisskb/buildresult/13366052/
http://kisskb.ellerman.id.au/kisskb/buildresult/13366048/
http://kisskb.ellerman.id.au/kisskb/buildresult/13366072/
Quoted 3 lines
arch/sh/kernel/traps_32.c int is_dsp_inst(struct pt_regs *regs) · line 607
Quoted 1 line
arch/sh/kernel/traps_32.c +0
-0}Acked-by Rich Felker <[email protected]>
Gr{oetje,eeting}s,
Geert
Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected] In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
PATCH 1/1 signal/sh: Stop gcc warning about an impossible case in do_divide_error
Geert Uytterhoeven <[email protected]> reported:
Quoted 5 lines
HOSTLD
scripts/mod/modpost
CCarch/sh/kernel/traps_32.oarch/sh/kernel/traps_32.c: In function 'do_divide_error':arch/sh/kernel/traps_32.c:606:17: error: 'code' may be used uninitialized in this function [-Werror=uninitialized]
cc1: all warnings being treated as errors
It is clear from inspection that do_divide_error is only called with TRAP_DIVZERO_ERROR or TRAP_DIVOVF_ERROR, as that is the way set_exception_table_vec is called. So let gcc know the other cases should not be considered by returning in all other cases.
This removes the warning and let's the code continue to build.
---
I am adding this fix to my tree to at least let the code build.
arch/sh/kernel/traps_32.c | 3 +++ 1 file changed, 3 insertions(+)
arch/sh/kernel/traps_32.c +3 -0
@@ -602,6 +602,9 @@ asmlinkage void do_divide_error(unsigned long r4)case TRAP_DIVOVF_ERROR : code =FPE_INTOVF ;break ; +default : +/* Let gcc know unhandled cases don't make it past here */ +return ; }force_sig_fault (SIGFPE , code,NULL , current); }
Signature · 1 line
2.14.1
Re: [PATCH] signal/sh: Stop gcc warning about an impossible case in do_divide_error
Hello!
Quoted 7 lines · Eric W. Biederman
Geert Uytterhoeven <[email protected]> reported:
Quoted 5 lines
HOSTLD
scripts/mod/modpost
CCarch/sh/kernel/traps_32.oarch/sh/kernel/traps_32.c: In function 'do_divide_error':arch/sh/kernel/traps_32.c:606:17: error: 'code' may be used uninitialized in this function [-Werror=uninitialized]
cc1: all warnings being treated as errors
Quoted 6 lines
It is clear from inspection that
do_divide_erroris only called withTRAP_DIVZERO_ERRORorTRAP_DIVOVF_ERROR, as that is the wayset_exception_table_vecis called. So let gcc know the other cases should not be considered by returning in all other cases.This removes the warning and let's the code continue to build.
Lets. :-)
Quoted 3 lines
Reported-by Geert Uytterhoeven <[email protected]>Fixes c65626c0cd4d ("signal/sh: Use force_sig_fault where appropriate")Signed-off-by "Eric W. Biederman" <[email protected]>
[...]
MBR, Sergei
PATCH 17/22 signal/sparc: Use send_sig_fault where appropriate
In reply to Eric W. BiedermanFilling in struct siginfo before calling send_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 send_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 send_sig_info.
In short about a 5 line reduction in code for every time send_sig_info is called, which makes the calling function clearer.
--- arch/sparc/kernel/traps_32.c | 93 ++++++++-------------------------------- arch/sparc/kernel/unaligned_32.c | 12 ++---- 2 files changed, 20 insertions(+), 85 deletions(-)
arch/sparc/kernel/traps_32.c +17 -76
@@ -116,8 +116,6 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type)void do_illegal_instruction (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -if (psr &PSR_PS )die_if_kernel ("Kernel illegal instruction" , regs);#ifdef TRAP_DEBUG
@@ -125,29 +123,15 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon regs->pc, *(unsigned long *)regs->pc);#endif -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_ILLOPC ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGILL , &info, current); +send_sig_fault (SIGILL ,ILL_ILLOPC , (void __user *)pc,0 , current); }void do_priv_instruction (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -if (psr &PSR_PS )die_if_kernel ("Penguin instruction from Penguin mode??!?!" , regs); -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_PRVOPC ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGILL , &info, current); +send_sig_fault (SIGILL ,ILL_PRVOPC , (void __user *)pc,0 , current); }/* XXX User may want to be allowed to do this. XXX */
@@ -155,8 +139,6 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long nvoid do_memaccess_unaligned (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -if (regs->psr &PSR_PS ) {printk ("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n" , pc, npc, regs->u_regs[UREG_RETPC ]);
@@ -168,13 +150,9 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned loninstruction_dump ((unsigned long *) regs->pc);printk ("do_MNA!\n" );#endif -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRALN ; - info.si_addr =/* FIXME: Should dig out mna address */ (void *)0 ; - info.si_trapno =0 ; -send_sig_info (SIGBUS , &info, current); +send_sig_fault (SIGBUS ,BUS_ADRALN , +/* FIXME: Should dig out mna address */ (void *)0 , +0 , current); }static unsigned long init_fsr =0x0UL ;
@@ -230,9 +208,9 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) {static int calls; -siginfo_t info;unsigned long fsr;int ret =0 ; +int code;#ifndef CONFIG_SMP struct task_struct *fpt = last_task_used_math;#else
@@ -307,25 +285,20 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, } fsr = fpt->thread.fsr; -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_errno =0 ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; - info.si_code =FPE_FLTUNK ; + code =FPE_FLTUNK ;if ((fsr &0x1c000 ) == (1 <<14 )) {if (fsr &0x10 ) - info.si_code =FPE_FLTINV ; + code =FPE_FLTINV ;else if (fsr &0x08 ) - info.si_code =FPE_FLTOVF ; + code =FPE_FLTOVF ;else if (fsr &0x04 ) - info.si_code =FPE_FLTUND ; + code =FPE_FLTUND ;else if (fsr &0x02 ) - info.si_code =FPE_FLTDIV ; + code =FPE_FLTDIV ;else if (fsr &0x01 ) - info.si_code =FPE_FLTRES ; + code =FPE_FLTRES ; } -send_sig_info (SIGFPE , &info, fpt); +send_sig_fault (SIGFPE , code, (void __user *)pc,0 , fpt);#ifndef CONFIG_SMP last_task_used_math =NULL ;#endif
@@ -337,17 +310,9 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,void handle_tag_overflow (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -if (psr &PSR_PS )die_if_kernel ("Penguin overflow trap from kernel mode" , regs); -clear_siginfo (&info); - info.si_signo =SIGEMT ; - info.si_errno =0 ; - info.si_code =EMT_TAGOVF ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGEMT , &info, current); +send_sig_fault (SIGEMT ,EMT_TAGOVF , (void __user *)pc,0 , current); } void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -383,47 +348,23 @@ void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npcvoid handle_cp_disabled (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_COPROC ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGILL , &info, current); +send_sig_fault (SIGILL ,ILL_COPROC , (void __user *)pc,0 , current); }void handle_cp_exception (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -#ifdef TRAP_DEBUG printk ("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n" , pc, npc, psr);#endif -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_COPROC ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGILL , &info, current); +send_sig_fault (SIGILL ,ILL_COPROC , (void __user *)pc,0 , current); }void handle_hw_divzero (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGFPE ; - info.si_errno =0 ; - info.si_code =FPE_INTDIV ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -send_sig_info (SIGFPE , &info, current); +send_sig_fault (SIGFPE ,FPE_INTDIV , (void __user *)pc,0 , current); }#ifdef CONFIG_DEBUG_BUGVERBOSE
arch/sparc/kernel/unaligned_32.c +3 -9
@@ -311,15 +311,9 @@ static inline int ok_for_user(struct pt_regs *regs, unsigned int insn,static void user_mna_trap_fault (struct pt_regs *regs,unsigned int insn) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRALN ; - info.si_addr = (void __user *)safe_compute_effective_address (regs, insn); - info.si_trapno =0 ; -send_sig_info (SIGBUS , &info, current); +send_sig_fault (SIGBUS ,BUS_ADRALN , + (void __user *)safe_compute_effective_address (regs, insn), +0 , current); } asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
Signature · 1 line
2.14.1
PATCH 18/22 signal/sparc: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/sparc/kernel/process_64.c | 10 +-- arch/sparc/kernel/sys_sparc_32.c | 9 +-- arch/sparc/kernel/sys_sparc_64.c | 8 +-- arch/sparc/kernel/traps_32.c | 21 +----- arch/sparc/kernel/traps_64.c | 145 ++++++++------------------------------- arch/sparc/mm/fault_32.c | 13 +--- arch/sparc/mm/fault_64.c | 9 +-- 7 files changed, 37 insertions(+), 178 deletions(-)
arch/sparc/kernel/process_64.c +1 -9
@@ -518,15 +518,7 @@ void synchronize_user_stack(void)static void stack_unaligned (unsigned long sp) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRALN ; - info.si_addr = (void __user *) sp; - info.si_trapno =0 ; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRALN , (void __user *) sp,0 , current); }void fault_in_user_windows (void )
arch/sparc/kernel/sys_sparc_32.c +1 -8
@@ -147,18 +147,11 @@ SYSCALL_DEFINE0(nis_syscall) asmlinkage voidsparc_breakpoint (struct pt_regs *regs) { -siginfo_t info;#ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%x, nPC=%x\n" , regs->pc, regs->npc);#endif -clear_siginfo (&info); - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_BRKPT ; - info.si_addr = (void __user *)regs->pc; - info.si_trapno =0 ; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_BRKPT , (void __user *)regs->pc,0 , current);#ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%x nPC=%x\n" , regs->pc, regs->npc);
arch/sparc/kernel/sys_sparc_64.c +1 -7
@@ -502,7 +502,6 @@ SYSCALL_DEFINE0(nis_syscall) asmlinkage void sparc_breakpoint(struct pt_regs *regs) {enum ctx_state prev_state =exception_enter (); -siginfo_t info;if (test_thread_flag (TIF_32BIT )) { regs->tpc &=0xffffffff ;
@@ -511,12 +510,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)#ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n" , regs->tpc, regs->tnpc);#endif - info.si_signo =SIGTRAP ; - info.si_errno =0 ; - info.si_code =TRAP_BRKPT ; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno =0 ; -force_sig_info (SIGTRAP , &info, current); +force_sig_fault (SIGTRAP ,TRAP_BRKPT , (void __user *)regs->tpc,0 , current);#ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n" , regs->tpc, regs->tnpc);#endif
arch/sparc/kernel/traps_32.c +3 -18
@@ -93,8 +93,6 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)void do_hw_interrupt (struct pt_regs *regs,unsigned long type) { -siginfo_t info; -if (type <0x80 ) {/* Sun OS's puke from bad traps, Linux survives! */ printk ("Unimplemented Sparc TRAP, type = %02lx\n" , type);
@@ -104,13 +102,8 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type)if (regs->psr &PSR_PS )die_if_kernel ("Kernel bad trap" , regs); -clear_siginfo (&info); - info.si_signo =SIGILL ; - info.si_errno =0 ; - info.si_code =ILL_ILLTRP ; - info.si_addr = (void __user *)regs->pc; - info.si_trapno = type -0x80 ; -force_sig_info (SIGILL , &info, current); +force_sig_fault (SIGILL ,ILL_ILLTRP , + (void __user *)regs->pc, type -0x80 , current); } void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -330,19 +323,11 @@ void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npcvoid handle_reg_access (struct pt_regs *regs,unsigned long pc,unsigned long npc,unsigned long psr) { -siginfo_t info; -#ifdef TRAP_DEBUG printk ("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n" , pc, npc, psr);#endif -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_OBJERR ; - info.si_addr = (void __user *)pc; - info.si_trapno =0 ; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_OBJERR , (void __user *)pc,0 , current); } void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
arch/sparc/kernel/traps_64.c +28 -117
311 lines not on this page · raw message
arch/sparc/mm/fault_32.c +2 -11
@@ -127,20 +127,11 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,static void __do_fault_siginfo (int code,int sig,struct pt_regs *regs,unsigned long addr) { -siginfo_t info; - -clear_siginfo (&info); - info.si_signo = sig; - info.si_code = code; - info.si_errno =0 ; - info.si_addr = (void __user *) addr; - info.si_trapno =0 ; -if (unlikely (show_unhandled_signals)) -show_signal_msg (regs, sig, info.si_code, +show_signal_msg (regs, sig, code, addr, current); -force_sig_info (sig, &info, current); +force_sig_fault (sig, code, (void __user *) addr,0 , current); }static unsigned long compute_si_addr (struct pt_regs *regs,int text_fault)
arch/sparc/mm/fault_64.c +1 -8
@@ -170,12 +170,7 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, int fault_code) {unsigned long addr; -siginfo_t info; -clear_siginfo (&info); - info.si_code = code; - info.si_signo = sig; - info.si_errno =0 ;if (fault_code &FAULT_CODE_ITLB ) { addr = regs->tpc; }else {
@@ -188,13 +183,11 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,else addr = fault_addr; } - info.si_addr = (void __user *) addr; - info.si_trapno =0 ;if (unlikely (show_unhandled_signals))show_signal_msg (regs, sig, code, addr, current); -force_sig_info (sig, &info, current); +force_sig_fault (sig, code, (void __user *) addr,0 , current); }static unsigned int get_fault_insn (struct pt_regs *regs,unsigned int insn)
Signature · 1 line
2.14.1
PATCH 19/22 signal/um: Use force_sig_fault in relay_signal.
In reply to Eric W. BiedermanToday user mode linux only works on x86 and x86_64 and this allows simplifications of relay_signal.
- x86 always set si_errno to 0 in fault handlers.
- x86 does not implement si_trapno.
- Only si_codes between SI_USER and SI_KERNEL have a fault address.
Therefore warn if si_errno is set (it should never be). Use force_sig_info in the case where we know we have a good fault.
For signals whose content it is not clear how to relay use plain force_sig and let the signal sending code come up with an appropriate generic siginfo.
--- arch/um/kernel/trap.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)
arch/um/kernel/trap.c +13 -15
@@ -296,9 +296,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,void relay_signal (int sig,struct siginfo *si,struct uml_pt_regs *regs) { -struct faultinfo *fi; -struct siginfo clean_si; -if (!UPT_IS_USER (regs)) {if (sig ==SIGBUS ) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -308,29 +305,30 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)arch_examine_signal (sig, regs); -clear_siginfo (&clean_si); - clean_si.si_signo = si->si_signo; - clean_si.si_errno = si->si_errno; - clean_si.si_code = si->si_code; +if (unlikely (si->si_errno)) { +printk (KERN_ERR "Attempted to relay signal %d (si_code = %d) with errno %d\n" , + sig, si->si_code, si->si_errno); + }switch (sig) {case SIGILL :case SIGFPE :case SIGSEGV :case SIGBUS :case SIGTRAP : - fi =UPT_FAULTINFO (regs); - clean_si.si_addr = (void __user *)FAULT_ADDRESS (*fi); - current->thread.arch.faultinfo = *fi; -#ifdef __ARCH_SI_TRAPNO - clean_si.si_trapno = si->si_trapno; -#endif -break ; +if ((si->si_code >SI_USER ) && (si->si_code <SI_KERNEL )) { +struct faultinfo *fi =UPT_FAULTINFO (regs); + current->thread.arch.faultinfo = *fi; +force_sig_fault (sig, si->si_code, + (void __user *)FAULT_ADDRESS (*fi), + current); +break ; + }default :printk (KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n" , sig, si->si_code); } -force_sig_info (sig, &clean_si, current); +force_sig (sig, current); }void bus_handler (int sig,struct siginfo *si,struct uml_pt_regs *regs)
Signature · 1 line
2.14.1
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Quoted 2 lines · Eric W. Biederman
Today user mode linux only works on x86 and
x86_64and this allows simplifications ofrelay_signal.
I believe someone recently fixed the ARM port. I have not had the time to try the fixes though.
I have added the new list we are migrating to the cc list.
A.
Quoted 77 lines
- x86 always set
si_errnoto 0 in fault handlers.
- x86 does not implementsi_trapno.
- Onlysi_codesbetweenSI_USERandSI_KERNELhave a fault address.Therefore warn if
si_errnois set (it should never be). Useforce_sig_infoin the case where we know we have a good fault.For signals whose content it is not clear how to relay use plain
force_sigand let the signal sending code come up with an appropriate generic siginfo.Cc Jeff Dike <[email protected]>Cc Richard Weinberger <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>--- arch/um/kernel/trap.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)arch/um/kernel/trap.c +13
-15@@ -296,9 +296,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,void relay_signal (int sig,struct siginfo *si,struct uml_pt_regs *regs) { -struct faultinfo *fi; -struct siginfo clean_si; -if (!UPT_IS_USER (regs)) {if (sig ==SIGBUS ) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "@@ -308,29 +305,30 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)arch_examine_signal (sig, regs); -clear_siginfo (&clean_si); - clean_si.si_signo = si->si_signo; - clean_si.si_errno = si->si_errno; - clean_si.si_code = si->si_code; +if (unlikely (si->si_errno)) { +printk (KERN_ERR "Attempted to relay signal %d (si_code = %d) with errno %d\n" , + sig, si->si_code, si->si_errno); + }switch (sig) {case SIGILL :case SIGFPE :case SIGSEGV :case SIGBUS :case SIGTRAP : - fi =UPT_FAULTINFO (regs); - clean_si.si_addr = (void __user *)FAULT_ADDRESS (*fi); - current->thread.arch.faultinfo = *fi; -#ifdef __ARCH_SI_TRAPNO - clean_si.si_trapno = si->si_trapno; -#endif -break ; +if ((si->si_code >SI_USER ) && (si->si_code <SI_KERNEL )) { +struct faultinfo *fi =UPT_FAULTINFO (regs); + current->thread.arch.faultinfo = *fi; +force_sig_fault (sig, si->si_code, + (void __user *)FAULT_ADDRESS (*fi), + current); +break ; + }default :printk (KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n" , sig, si->si_code); } -force_sig_info (sig, &clean_si, current); +force_sig (sig, current); }void bus_handler (int sig,struct siginfo *si,struct uml_pt_regs *regs)
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Quoted 9 lines · Anton Ivanov
Quoted 3 lines · Eric W. Biederman
Today user mode linux only works on x86 and
x86_64and this allows simplifications ofrelay_signal.I believe someone recently fixed the ARM port. I have not had the time to try the fixes though.
Huh? UML is for ages x86 only.
Signature · 2 lines
Thanks, //richard
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Hi Richard,
There was a post to uml-devel during the days when the sourceforge mailing list was working in random drop mode which claimed that "this fixes the arm build".
I have not kept it locally and I do not see it the archive (I do not see a few other posts there either - including some of mine).
The joys of having a broken list :(
Whoever posted it, if you are reading it, please re-post again so we can have a look.
In the meantime we are as you said - x86 only.
A.
Quoted 10 lines · Richard Weinberger
Quoted 6 lines · Anton Ivanov
Quoted 2 lines · Eric W. Biederman
Today user mode linux only works on x86 and
x86_64and this allows simplifications ofrelay_signal.I believe someone recently fixed the ARM port. I have not had the time to try the fixes though.
Huh? UML is for ages x86 only.
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Sigh I should have Cc'd Martin Partel as well as this bit is his original code.
Quoted 8 lines · Anton Ivanov
Hi Richard,
There was a post to uml-devel during the days when the sourceforge mailing list was working in random drop mode which claimed that "this fixes the arm build".
I have not kept it locally and I do not see it the archive (I do not see a few other posts there either - including some of mine).
Quoted 6 lines
The joys of having a broken list :(
Whoever posted it, if you are reading it, please re-post again so we can have a look.
In the meantime we are as you said - x86 only.
The only case I can see my changed relay_signal affecting on arm is the nasty hach where errno is set in conjunction with trap_trace.
Having a second look I really don't understand what relay_signal is trying to do.
The function relay_signal does not pass siginfo through unchanged. The function relay_signal does not handle cases where si_code is not SI_USER or SI_KERNEL, or any of the other signal independent si_codes.
In my change I believe I have preserved the character of relay_signal of just passing through the fault.
Still even after reading the commit that upgraded relay_signal to preserve si_code and si_addr I really don't understand the intended logic.
Am I missing something subtle or have the subtle details of siginfo just always been ignored?
commit d3c1cfcdb43e023ab1b1c7a555cd9e929026500a
Author: Martin Pärtel <[email protected]> Date: Thu Aug 2 00:49:17 2012 +0200
um: pass siginfo to guest process
UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct where previously they were si_addr = NULL and si_code = 128.
Eric
A message that is not in the archive (sent off-list or not yet received): CAMD8JhwgcWCp6c=O4-spNW1VdY5M-eAjr7M5PieeAfeTSe_4yw@mail.gmail.com
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
And once more in plain text..
Quoted 22 lines · Martin Pärtel
Hi all,
This was ages ago, but from what I remember...
Quoted 5 lines
Having a second look I really don't understand what
relay_signalis trying to do.The function
relay_signaldoes not pass siginfo through unchanged.Just copying the entire struct would do the wrong thing. It was discussed here:
https://marc.info/?l=user-mode-linux-devel&m=133910707911999&w=2Quoted 3 lines
Am I missing something subtle or have the subtle details of siginfo just always been ignored?
My guess is they have. I was almost certainly oblivious to such subtleties when writing my commit.
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Quoted 17 lines · Martin Pärtel
And once more in plain text..
Quoted 14 lines · Martin Pärtel
Hi all,
This was ages ago, but from what I remember...
Quoted 5 lines
Having a second look I really don't understand what
relay_signalis trying to do.The function
relay_signaldoes not pass siginfo through unchanged.Just copying the entire struct would do the wrong thing. It was discussed here:
https://marc.info/?l=user-mode-linux-devel&m=133910707911999&w=2
So you are regnerating siginfo to ensure you don't copy unintended things such as the host pid and host uid.
Then my analysis is correct that you simply missed filtering out the si codes that are not signal specific and do not use the fault layout in struct siginfo.
Is si_addr safe to copy across? I presume so since the kernel just ptraces an ordinary process, but I figure I should ask and double check.
I am going to respin my patch. I would say that you really need a white-list of si_codes that whose use of struct siginfo that you know. Otherwise you could get into the same problem of under or over copying data.
Eric
Re: [uml-devel] [REVIEW][PATCH 19/22] signal/um: Use force_sig_fault in relay_signal.
Quoted 10 lines
Then my analysis is correct that you simply missed filtering out the si codes that are not signal specific and do not use the fault layout in struct siginfo.
...
I would say that you really need a
white-list ofsi_codesthat whose use of struct siginfo that you know. Otherwise you could get into the same problem of under or over copying data.
I think that's correct, but I'm not super familiar with either UML or signal handling.
cover Improving siginfo_layout and fixing uml's relay_signal
This patchset is a respin of my latest patch to relay_signal for uml.
As I understand relay_signal it very carefully scrubs the signal information it gets from the host kernel before passing it on. Basically making certain it recognizes what it is dealing with.
This patchset updates siginfo_layout so that relay_signal and arm64's force_signal_inject can reliably use it to verify the kind of signal being processed, by recognizing the specializations of SIL_FAULT as separate cases.
To make the siginfo_layout changes clean. signalfd is first brought into the modern world of using a single copy_to_user, no default case statement (so gcc will flag missing cases), and handling SIGSYS for seccomp.
The net is a simpler relay_signal is also more careful about which signals it relays.
Eric
The changes are also available at:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git siginfo-review3
Eric W. Biederman (5):
signal/signalfd: Remove __put_user from signalfd_copyinfo signal/signalfd: Add support for SIGSYS
signal: Remove unncessary #ifdef SEGV_PKUERR in 32bit compat code
signal: Extend siginfo_layout with SIL_FAULT_{MCEERR|BNDERR|PKUERR} signal/um: More carefully relay signals in relay_signal.
arch/um/kernel/trap.c | 38 ++++++++------------ fs/signalfd.c | 84 +++++++++++++++++++++++++------------------ include/linux/signal.h | 3 ++ include/uapi/linux/signalfd.h | 6 +++- kernel/signal.c | 82 +++++++++++++++++++++++++++--------------- 5 files changed, 125 insertions(+), 88 deletions(-)
PATCH 1/5 signal/signalfd: Remove __put_user from signalfd_copyinfo
Put a signalfd_siginfo structure on the stack fully initializae it and then copy it to userspace.
The code is a little less wordy, and this avoids a long series of the somewhat costly __put_user calls.
--- fs/signalfd.c | 56 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-)
fs/signalfd.c +29 -27
@@ -81,41 +81,41 @@ static __poll_t signalfd_poll(struct file *file, poll_table *wait)static int signalfd_copyinfo (struct signalfd_siginfo __user *uinfo,siginfo_t const *kinfo) { -long err; +struct signalfd_siginfo new;BUILD_BUG_ON (sizeof (struct signalfd_siginfo ) !=128 );/* * Unused members should be zero ... */ - err =__clear_user (uinfo,sizeof (*uinfo)); +memset (&new,0 ,sizeof (new));/* * If you change siginfo_t structure, please be sure * this code is fixed accordingly. */ - err |=__put_user (kinfo->si_signo, &uinfo->ssi_signo); - err |=__put_user (kinfo->si_errno, &uinfo->ssi_errno); - err |=__put_user (kinfo->si_code, &uinfo->ssi_code); + new.ssi_signo = kinfo->si_signo; + new.ssi_errno = kinfo->si_errno; + new.ssi_code = kinfo->si_code;switch (siginfo_layout (kinfo->si_signo, kinfo->si_code)) {case SIL_KILL : - err |=__put_user (kinfo->si_pid, &uinfo->ssi_pid); - err |=__put_user (kinfo->si_uid, &uinfo->ssi_uid); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid;break ;case SIL_TIMER : - err |=__put_user (kinfo->si_tid, &uinfo->ssi_tid); - err |=__put_user (kinfo->si_overrun, &uinfo->ssi_overrun); - err |=__put_user ((long ) kinfo->si_ptr, &uinfo->ssi_ptr); - err |=__put_user (kinfo->si_int, &uinfo->ssi_int); + new.ssi_tid = kinfo->si_tid; + new.ssi_overrun = kinfo->si_overrun; + new.ssi_ptr = (long ) kinfo->si_ptr; + new.ssi_int = kinfo->si_int;break ;case SIL_POLL : - err |=__put_user (kinfo->si_band, &uinfo->ssi_band); - err |=__put_user (kinfo->si_fd, &uinfo->ssi_fd); + new.ssi_band = kinfo->si_band; + new.ssi_fd = kinfo->si_fd;break ;case SIL_FAULT : - err |=__put_user ((long ) kinfo->si_addr, &uinfo->ssi_addr); + new.ssi_addr = (long ) kinfo->si_addr;#ifdef __ARCH_SI_TRAPNO - err |=__put_user (kinfo->si_trapno, &uinfo->ssi_trapno); + new.ssi_trapno = kinfo->si_trapno;#endif /* * Other callers might not initialize the si_lsb field,
@@ -124,29 +124,31 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,if (kinfo->si_signo ==SIGBUS && ((kinfo->si_code ==BUS_MCEERR_AR ) || (kinfo->si_code ==BUS_MCEERR_AO ))) - err |=__put_user ((short ) kinfo->si_addr_lsb, - &uinfo->ssi_addr_lsb); + new.ssi_addr_lsb = (short ) kinfo->si_addr_lsb;break ;case SIL_CHLD : - err |=__put_user (kinfo->si_pid, &uinfo->ssi_pid); - err |=__put_user (kinfo->si_uid, &uinfo->ssi_uid); - err |=__put_user (kinfo->si_status, &uinfo->ssi_status); - err |=__put_user (kinfo->si_utime, &uinfo->ssi_utime); - err |=__put_user (kinfo->si_stime, &uinfo->ssi_stime); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid; + new.ssi_status = kinfo->si_status; + new.ssi_utime = kinfo->si_utime; + new.ssi_stime = kinfo->si_stime;break ;case SIL_RT :default :/* * This case catches also the signals queued by sigqueue(). */ - err |=__put_user (kinfo->si_pid, &uinfo->ssi_pid); - err |=__put_user (kinfo->si_uid, &uinfo->ssi_uid); - err |=__put_user ((long ) kinfo->si_ptr, &uinfo->ssi_ptr); - err |=__put_user (kinfo->si_int, &uinfo->ssi_int); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid; + new.ssi_ptr = (long ) kinfo->si_ptr; + new.ssi_int = kinfo->si_int;break ; } -return err ? -EFAULT :sizeof (*uinfo); +if (copy_to_user (uinfo, &new,sizeof (struct signalfd_siginfo ))) +return -EFAULT ; + +return sizeof (*uinfo); } static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
Signature · 1 line
2.14.1
PATCH 2/5 signal/signalfd: Add support for SIGSYS
In reply to Eric W. BiedermanI don't know why signalfd has never grown support for SIGSYS but grow it now.
This corrects an oversight and removes a need for a default in the switch statement. Allowing gcc to warn when future members are added to the enum siginfo_layout, and signalfd does not handle them.
--- fs/signalfd.c | 6 +++++- include/uapi/linux/signalfd.h | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-)
fs/signalfd.c +5 -1
@@ -134,7 +134,6 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, new.ssi_stime = kinfo->si_stime;break ;case SIL_RT : -default :/* * This case catches also the signals queued by sigqueue(). */
@@ -143,6 +142,11 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, new.ssi_ptr = (long ) kinfo->si_ptr; new.ssi_int = kinfo->si_int;break ; +case SIL_SYS : + new.ssi_call_addr = (long ) kinfo->si_call_addr; + new.ssi_syscall = kinfo->si_syscall; + new.ssi_arch = kinfo->si_arch; +break ; }if (copy_to_user (uinfo, &new,sizeof (struct signalfd_siginfo )))
include/uapi/linux/signalfd.h +5 -1
@@ -35,6 +35,10 @@ struct signalfd_siginfo {__u64 ssi_stime;__u64 ssi_addr;__u16 ssi_addr_lsb; +__u16 __pad2; +__s32 ssi_syscall; +__u64 ssi_call_addr; +__u32 ssi_arch;/* * Pad strcture to 128 bytes. Remember to update the
@@ -45,7 +49,7 @@ struct signalfd_siginfo {* comes out of a read(2) and we really don't want to have * a compat on read(2). */ -__u8 __pad[46 ]; +__u8 __pad[28 ]; };
Signature · 1 line
2.14.1
PATCH 3/5 signal: Remove unncessary #ifdef SEGV_PKUERR in 32bit compat code
In reply to Eric W. BiedermanThe only architecture that does not support SEGV_PKUERR is ia64 and ia64 has not had 32bit support since some time in 2008. Therefore copy_siginfo_to_user32 and copy_siginfo_from_user32 do not need to include support for a missing SEGV_PKUERR.
Compile test on ia64.
--- kernel/signal.c | 5 ----- 1 file changed, 5 deletions(-)
kernel/signal.c +0 -5
@@ -2888,12 +2888,9 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to, new.si_lower =ptr_to_compat (from->si_lower); new.si_upper =ptr_to_compat (from->si_upper); } -#ifdef SEGV_PKUERR if ((from->si_signo ==SIGSEGV ) && (from->si_code ==SEGV_PKUERR )) new.si_pkey = from->si_pkey; -#endif -break ;case SIL_CHLD : new.si_pid = from->si_pid;
@@ -2968,10 +2965,8 @@ int copy_siginfo_from_user32(struct siginfo *to, to->si_lower =compat_ptr (from.si_lower); to->si_upper =compat_ptr (from.si_upper); } -#ifdef SEGV_PKUERR if ((from.si_signo ==SIGSEGV ) && (from.si_code ==SEGV_PKUERR )) to->si_pkey = from.si_pkey; -#endif break ;case SIL_CHLD : to->si_pid = from.si_pid;
Signature · 1 line
2.14.1
PATCH 4/5 signal: Extend siginfo_layout with SIL_FAULT_{MCEERR|BNDERR|PKUERR}
In reply to Eric W. BiedermanUpdate the siginfo_layout function and enum siginfo_layout to represent all of the possible field layouts of struct siginfo.
This allows the uses of siginfo_layout in um and arm64 where they are testing for SIL_FAULT to be more accurate as this rules out the other cases.
Further this allows the switch statements on siginfo_layout to be simpler if perhaps a little more wordy. Making it easier to understand what is actually going on.
As SIL_FAULT_BNDERR and SIL_FAULT_PKUERR are never expected to appear in signalfd just treat them as SIL_FAULT. To include them would take 20 extra bytes an pretty much fill up what is left of signalfd_siginfo.
--- fs/signalfd.c | 24 ++++++++++----- include/linux/signal.h | 3 ++ kernel/signal.c | 81 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 75 insertions(+), 33 deletions(-)
fs/signalfd.c +16 -8
@@ -112,19 +112,27 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, new.ssi_band = kinfo->si_band; new.ssi_fd = kinfo->si_fd;break ; +case SIL_FAULT_BNDERR : +case SIL_FAULT_PKUERR : +/* +* Fall through to the SIL_FAULT case. Both SIL_FAULT_BNDERR +* and SIL_FAULT_PKUERR are only generated by faults that +* deliver them synchronously to userspace. In case someone +* injects one of these signals and signalfd catches it treat +* it as SIL_FAULT. +*/ case SIL_FAULT : new.ssi_addr = (long ) kinfo->si_addr;#ifdef __ARCH_SI_TRAPNO new.ssi_trapno = kinfo->si_trapno;#endif -/* -* Other callers might not initialize the si_lsb field, -* so check explicitly for the right codes here. -*/ -if (kinfo->si_signo ==SIGBUS && - ((kinfo->si_code ==BUS_MCEERR_AR ) || - (kinfo->si_code ==BUS_MCEERR_AO ))) - new.ssi_addr_lsb = (short ) kinfo->si_addr_lsb; +break ; +case SIL_FAULT_MCEERR : + new.ssi_addr = (long ) kinfo->si_addr; +#ifdef __ARCH_SI_TRAPNO + new.ssi_trapno = kinfo->si_trapno; +#endif + new.ssi_addr_lsb = (short ) kinfo->si_addr_lsb;break ;case SIL_CHLD : new.ssi_pid = kinfo->si_pid;
include/linux/signal.h +3 -0
@@ -28,6 +28,9 @@ enum siginfo_layout {SIL_TIMER ,SIL_POLL ,SIL_FAULT , +SIL_FAULT_MCEERR , +SIL_FAULT_BNDERR , +SIL_FAULT_PKUERR ,SIL_CHLD ,SIL_RT , SIL_SYS,
kernel/signal.c +56 -25
100 lines not on this page · raw message
Signature · 1 line
2.14.1
PATCH 5/5 signal/um: More carefully relay signals in relay_signal.
In reply to Eric W. BiedermanThere is a bug in relay signal. It assumes that when a signal is relayed the signal never uses a signal independent si_code, such as SI_USER, SI_KERNEL, SI_QUEUE, ... SI_SIGIO etc. In practice siginfo was assuming it was relaying a signal with the SIL_FAULT layout. As that is the common cases for the signals it supported that is a reasonable assumption.
Further user mode linux must be very careful when relaying different kinds of signals to prevent an information leak. This means simply increasing the kinds of signals that are handled in relay_signal is non-trivial.
Therefore use siginfo_layout and force_sig_fault to simplify the signal relaying in relay_signal.
By taking advantage of the fact that user mode linux only works on x86 and x86_64 we can assume that si_trapno can be ignored, and that si_errno is always zero.
For the signals SIGLL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP the only fault handler I know of that sets si_errno is SIGTRAP TRAP_HWBKPT on a few oddball architectures. Those architectures have been modified to use force_sig_ptrace_errno_trap.
Similarly only a few architectures set __ARCH_SI_TRAPNO.
At the point uml supports those architectures again these additional cases can be examined and supported if desired in relay_signal.
--- arch/um/kernel/trap.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-)
arch/um/kernel/trap.c +14 -24
@@ -286,9 +286,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,void relay_signal (int sig,struct siginfo *si,struct uml_pt_regs *regs) { -struct faultinfo *fi; -struct siginfo clean_si; - +int code, err;if (!UPT_IS_USER (regs)) {if (sig ==SIGBUS ) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -298,29 +296,21 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)arch_examine_signal (sig, regs); -clear_siginfo (&clean_si); - clean_si.si_signo = si->si_signo; - clean_si.si_errno = si->si_errno; - clean_si.si_code = si->si_code; -switch (sig) { -case SIGILL : -case SIGFPE : -case SIGSEGV : -case SIGBUS : -case SIGTRAP : - fi =UPT_FAULTINFO (regs); - clean_si.si_addr = (void __user *)FAULT_ADDRESS (*fi); +/* Is the signal layout for the signal known? +* Signal data must be scrubbed to prevent information leaks. +*/ + code = si->si_code; + err = si->si_errno; +if ((err ==0 ) && (siginfo_layout (sig, code) ==SIL_FAULT )) { +struct faultinfo *fi =UPT_FAULTINFO (regs); current->thread.arch.faultinfo = *fi; -#ifdef __ARCH_SI_TRAPNO - clean_si.si_trapno = si->si_trapno; -#endif -break ; -default : -printk (KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n" , - sig, si->si_code); +force_sig_fault (sig, code, (void __user *)FAULT_ADDRESS (*fi), + current); + }else { +printk (KERN_ERR "Attempted to relay unknown signal %d (si_code = %d) with errno %d\n" , + sig, code, err); +force_sig (sig, current); } - -force_sig_info (sig, &clean_si, current); }void bus_handler (int sig,struct siginfo *si,struct uml_pt_regs *regs)
Signature · 1 line
2.14.1
PATCH 20/22 signal/um: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/um/kernel/ptrace.c | 13 +++---------- arch/um/kernel/trap.c | 26 ++++++++------------------ 2 files changed, 11 insertions(+), 28 deletions(-)
arch/um/kernel/ptrace.c +3 -10
@@ -115,17 +115,10 @@ long arch_ptrace(struct task_struct *child, long request,static void send_sigtrap (struct task_struct *tsk,struct uml_pt_regs *regs,int error_code) { -struct siginfo info; - -memset (&info,0 ,sizeof (info)); - info.si_signo =SIGTRAP ; - info.si_code =TRAP_BRKPT ; - -/* User-mode eip? */ - info.si_addr =UPT_IS_USER (regs) ? (void __user *)UPT_IP (regs) :NULL ; -/* Send us the fake SIGTRAP */ -force_sig_info (SIGTRAP , &info, tsk); +force_sig_fault (SIGTRAP ,TRAP_BRKPT , +/* User-mode eip? */ +UPT_IS_USER (regs) ? (void __user *)UPT_IP (regs) :NULL , tsk); }/*
arch/um/kernel/trap.c +8 -18
@@ -162,14 +162,9 @@ static void show_segv_info(struct uml_pt_regs *regs)static void bad_segv (struct faultinfo fi,unsigned long ip) { -struct siginfo si; - -clear_siginfo (&si); - si.si_signo =SIGSEGV ; - si.si_code =SEGV_ACCERR ; - si.si_addr = (void __user *)FAULT_ADDRESS (fi); current->thread.arch.faultinfo = fi; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV ,SEGV_ACCERR , (void __user *)FAULT_ADDRESS (fi), + current); }void fatal_sigsegv (void )
@@ -215,13 +210,12 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)unsigned long segv (struct faultinfo fi,unsigned long ip,int is_user,struct uml_pt_regs *regs) { -struct siginfo si;jmp_buf *catcher; +int si_code;int err;int is_write =FAULT_WRITE (fi);unsigned long address =FAULT_ADDRESS (fi); -clear_siginfo (&si);if (!is_user && regs) current->thread.segv_regs = container_of(regs, struct pt_regs, regs);
@@ -241,7 +235,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,if (SEGV_IS_FIXABLE (&fi)) err =handle_page_fault (address, ip, is_write, is_user, - &si.si_code); + &si_code);else { err = -EFAULT ;/*
@@ -273,18 +267,14 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,show_segv_info (regs);if (err == -EACCES ) { - si.si_signo =SIGBUS ; - si.si_errno =0 ; - si.si_code =BUS_ADRERR ; - si.si_addr = (void __user *)address; current->thread.arch.faultinfo = fi; -force_sig_info (SIGBUS , &si, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void __user *)address, + current); }else {BUG_ON (err != -EFAULT ); - si.si_signo =SIGSEGV ; - si.si_addr = (void __user *) address; current->thread.arch.faultinfo = fi; -force_sig_info (SIGSEGV , &si, current); +force_sig_fault (SIGSEGV , si_code, (void __user *) address, + current); } out:
Signature · 1 line
2.14.1
PATCH 21/22 signal/xtensa: Consistenly use SIGBUS in do_unaligned_user
In reply to Eric W. BiedermanWhile working on changing this code to use force_sig_fault I discovered that do_unaliged_user is sets si_signo to SIGBUS and passes SIGSEGV to force_sig_info. Which is just b0rked.
The code is reporting a SIGBUS error so replace the SIGSEGV with SIGBUS.
--- arch/xtensa/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/xtensa/kernel/traps.c +1 -1
@@ -339,7 +339,7 @@ do_unaligned_user (struct pt_regs *regs) info.si_errno =0 ; info.si_code =BUS_ADRALN ; info.si_addr = (void *) regs->excvaddr; - force_sig_info(SIGSEGV, &info, current); + force_sig_info(SIGBUS, &info, current); }#endif
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 21/22] signal/xtensa: Consistenly use SIGBUS in do_unaligned_user
Quoted 12 lines · Eric W. Biederman
While working on changing this code to use
force_sig_faultI discovered thatdo_unaliged_useris setssi_signoto SIGBUS and passes SIGSEGV toforce_sig_info. Which is just b0rked.The code is reporting a SIGBUS error so replace the SIGSEGV with SIGBUS.
Cc Chris Zankel <[email protected]>Cc Max Filippov <[email protected]>Fixes 5a0015d62668 ("[PATCH] xtensa: Architecture support for Tensilica Xtensa Part 3")Signed-off-by "Eric W. Biederman" <[email protected]>
Quoted 3 lines
--- arch/xtensa/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Signature · 2 lines
Thanks. -- Max
PATCH 22/22 signal/xtensa: Use force_sig_fault where appropriate
In reply to Eric W. BiedermanFilling 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.
--- arch/xtensa/kernel/traps.c | 10 +--------- arch/xtensa/mm/fault.c | 19 +++++-------------- 2 files changed, 6 insertions(+), 23 deletions(-)
arch/xtensa/kernel/traps.c +1 -9
@@ -323,8 +323,6 @@ do_illegal_instruction(struct pt_regs *regs)void do_unaligned_user (struct pt_regs *regs) { -siginfo_t info; -__die_if_kernel ("Unhandled unaligned exception in kernel" , regs,SIGKILL );
@@ -334,13 +332,7 @@ do_unaligned_user (struct pt_regs *regs)"(pid = %d, pc = %#010lx)\n" , regs->excvaddr, current->comm, task_pid_nr(current), regs->pc); -clear_siginfo (&info); - info.si_signo =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRALN ; - info.si_addr = (void *) regs->excvaddr; - force_sig_info(SIGBUS, &info, current); - + force_sig_fault(SIGBUS, BUS_ADRALN, (void *) regs->excvaddr, current); }#endif
arch/xtensa/mm/fault.c +5 -14
@@ -39,14 +39,13 @@ void do_page_fault(struct pt_regs *regs)struct mm_struct *mm = current->mm;unsigned int exccause = regs->exccause;unsigned int address = regs->excvaddr; -siginfo_t info; +int code;int is_write, is_exec;int fault;unsigned int flags =FAULT_FLAG_ALLOW_RETRY |FAULT_FLAG_KILLABLE ; -clear_siginfo (&info); - info.si_code =SEGV_MAPERR ; + code =SEGV_MAPERR ;/* We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd.
@@ -92,7 +91,7 @@ void do_page_fault(struct pt_regs *regs)*/ good_area: - info.si_code =SEGV_ACCERR ; + code =SEGV_ACCERR ;if (is_write) {if (!(vma->vm_flags &VM_WRITE ))
@@ -158,11 +157,7 @@ void do_page_fault(struct pt_regs *regs)if (user_mode (regs)) { current->thread.bad_vaddr = address; current->thread.error_code = is_write; - info.si_signo =SIGSEGV ; - info.si_errno =0 ; -/* info.si_code has been set above */ - info.si_addr = (void *) address; -force_sig_info (SIGSEGV , &info, current); +force_sig_fault (SIGSEGV , code, (void *) address, current);return ; }bad_page_fault (regs, address,SIGSEGV );
@@ -187,11 +182,7 @@ void do_page_fault(struct pt_regs *regs)* or user mode. */ current->thread.bad_vaddr = address; - info.si_code =SIGBUS ; - info.si_errno =0 ; - info.si_code =BUS_ADRERR ; - info.si_addr = (void *) address; -force_sig_info (SIGBUS , &info, current); +force_sig_fault (SIGBUS ,BUS_ADRERR , (void *) address, current);/* Kernel mode? Handle exceptions or die */ if (!user_mode (regs))
Signature · 1 line
2.14.1
Re: [REVIEW][PATCH 22/22] signal/xtensa: Use force_sig_fault where appropriate
Quoted 17 lines · Eric W. Biederman
Filling in struct siginfo before calling
force_sig_infoa 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 callsforce_sig_info.In short about a 5 line reduction in code for every time
force_sig_infois called, which makes the calling function clearer.Cc Max Filippov <[email protected]>Cc Chris Zankel <[email protected]>Signed-off-by "Eric W. Biederman" <[email protected]>
Quoted 4 lines
--- arch/xtensa/kernel/traps.c | 10 +--------- arch/xtensa/mm/fault.c | 19 +++++-------------- 2 files changed, 6 insertions(+), 23 deletions(-)
Signature · 2 lines
Thanks. -- Max