aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2017-08-19 16:26:01 -0400
committerEric W. Biederman <ebiederm@xmission.com>2018-01-12 15:21:04 -0500
commitcf4674c46c66e45f238f8f7e81af2a444b970c0a (patch)
tree8742792c826b15a8fe7d673524d3a99415b682b6
parentb80328be53c215346b153769267b38f531d89b4f (diff)
signal/powerpc: Document conflicts with SI_USER and SIGFPE and SIGTRAP
Setting si_code to 0 results in a userspace seeing an si_code of 0. 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. Further use of si_code == 0 guaranteed that copy_siginfo_to_user saw a value of __SI_KILL and now sees a value of SIL_KILL with the result that uid and pid fields are copied and which might copying the si_addr field by accident but certainly not by design. Making this a very flakey implementation. Utilizing FPE_FIXME and TRAP_FIXME, siginfo_layout() will now return SIL_FAULT and the appropriate fields will be reliably copied. Possible ABI fixes includee: - Send the signal without siginfo - Don't generate a signal - Possibly assign and use an appropriate si_code - Don't handle cases which can't happen Cc: Paul Mackerras <paulus@samba.org> Cc: Kumar Gala <kumar.gala@freescale.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: linuxppc-dev@lists.ozlabs.org Ref: 9bad068c24d7 ("[PATCH] ppc32: support for e500 and 85xx") Ref: 0ed70f6105ef ("PPC32: Provide proper siginfo information on various exceptions.") History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--arch/powerpc/include/uapi/asm/siginfo.h15
-rw-r--r--arch/powerpc/kernel/traps.c10
2 files changed, 20 insertions, 5 deletions
diff --git a/arch/powerpc/include/uapi/asm/siginfo.h b/arch/powerpc/include/uapi/asm/siginfo.h
index 1a691141e49f..444ca6c9989a 100644
--- a/arch/powerpc/include/uapi/asm/siginfo.h
+++ b/arch/powerpc/include/uapi/asm/siginfo.h
@@ -18,4 +18,19 @@
18#undef NSIGTRAP 18#undef NSIGTRAP
19#define NSIGTRAP 4 19#define NSIGTRAP 4
20 20
21/*
22 * SIGFPE si_codes
23 */
24#ifdef __KERNEL__
25#define FPE_FIXME 0 /* Broken dup of SI_USER */
26#endif /* __KERNEL__ */
27
28/*
29 * SIGTRAP si_codes
30 */
31#ifdef __KERNEL__
32#define TRAP_FIXME 0 /* Broken dup of SI_USER */
33#endif /* __KERNEL__ */
34
35
21#endif /* _ASM_POWERPC_SIGINFO_H */ 36#endif /* _ASM_POWERPC_SIGINFO_H */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index f3eb61be0d30..f2e6e1838952 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -917,7 +917,7 @@ void unknown_exception(struct pt_regs *regs)
917 printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", 917 printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
918 regs->nip, regs->msr, regs->trap); 918 regs->nip, regs->msr, regs->trap);
919 919
920 _exception(SIGTRAP, regs, 0, 0); 920 _exception(SIGTRAP, regs, TRAP_FIXME, 0);
921 921
922 exception_exit(prev_state); 922 exception_exit(prev_state);
923} 923}
@@ -939,7 +939,7 @@ bail:
939 939
940void RunModeException(struct pt_regs *regs) 940void RunModeException(struct pt_regs *regs)
941{ 941{
942 _exception(SIGTRAP, regs, 0, 0); 942 _exception(SIGTRAP, regs, TRAP_FIXME, 0);
943} 943}
944 944
945void single_step_exception(struct pt_regs *regs) 945void single_step_exception(struct pt_regs *regs)
@@ -978,7 +978,7 @@ static void emulate_single_step(struct pt_regs *regs)
978 978
979static inline int __parse_fpscr(unsigned long fpscr) 979static inline int __parse_fpscr(unsigned long fpscr)
980{ 980{
981 int ret = 0; 981 int ret = FPE_FIXME;
982 982
983 /* Invalid operation */ 983 /* Invalid operation */
984 if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) 984 if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
@@ -1929,7 +1929,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
1929 extern int do_spe_mathemu(struct pt_regs *regs); 1929 extern int do_spe_mathemu(struct pt_regs *regs);
1930 unsigned long spefscr; 1930 unsigned long spefscr;
1931 int fpexc_mode; 1931 int fpexc_mode;
1932 int code = 0; 1932 int code = FPE_FIXME;
1933 int err; 1933 int err;
1934 1934
1935 flush_spe_to_thread(current); 1935 flush_spe_to_thread(current);
@@ -1998,7 +1998,7 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
1998 printk(KERN_ERR "unrecognized spe instruction " 1998 printk(KERN_ERR "unrecognized spe instruction "
1999 "in %s at %lx\n", current->comm, regs->nip); 1999 "in %s at %lx\n", current->comm, regs->nip);
2000 } else { 2000 } else {
2001 _exception(SIGFPE, regs, 0, regs->nip); 2001 _exception(SIGFPE, regs, FPE_FIXME, regs->nip);
2002 return; 2002 return;
2003 } 2003 }
2004} 2004}