diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2017-08-19 16:26:01 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-01-12 15:21:04 -0500 |
commit | cf4674c46c66e45f238f8f7e81af2a444b970c0a (patch) | |
tree | 8742792c826b15a8fe7d673524d3a99415b682b6 | |
parent | b80328be53c215346b153769267b38f531d89b4f (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.h | 15 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 10 |
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 | ||
940 | void RunModeException(struct pt_regs *regs) | 940 | void RunModeException(struct pt_regs *regs) |
941 | { | 941 | { |
942 | _exception(SIGTRAP, regs, 0, 0); | 942 | _exception(SIGTRAP, regs, TRAP_FIXME, 0); |
943 | } | 943 | } |
944 | 944 | ||
945 | void single_step_exception(struct pt_regs *regs) | 945 | void single_step_exception(struct pt_regs *regs) |
@@ -978,7 +978,7 @@ static void emulate_single_step(struct pt_regs *regs) | |||
978 | 978 | ||
979 | static inline int __parse_fpscr(unsigned long fpscr) | 979 | static 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 | } |