diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-06-04 03:22:48 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-14 08:29:58 -0400 |
commit | a3f61dc0a5335334958ec3b97d0b1946b4ae5375 (patch) | |
tree | e7b151d724dca73220d8346c2a0c2a3525c5c91c /arch/powerpc/kernel/signal.c | |
parent | 5f9f375a62d3fd3d7f0d5adc23039ade523e62ba (diff) |
[POWERPC] Merge creation of signal frame
The code for creating signal frames was still duplicated and split
in strange ways between 32 and 64 bits, including the SA_ONSTACK
handling being in do_signal on 32 bits but inside handle_rt_signal
on 64 bits etc...
This moves the 64 bits get_sigframe() to the generic signal.c,
cleans it a bit, moves the access_ok() call done by all callers to
it as well, and adapts/cleanups the 3 different signal handling cases
to use that common function.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/signal.c')
-rw-r--r-- | arch/powerpc/kernel/signal.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index a9c148a09361..dee275014e00 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/ptrace.h> | 12 | #include <linux/ptrace.h> |
13 | #include <linux/signal.h> | 13 | #include <linux/signal.h> |
14 | #include <asm/uaccess.h> | ||
14 | #include <asm/unistd.h> | 15 | #include <asm/unistd.h> |
15 | 16 | ||
16 | #include "signal.h" | 17 | #include "signal.h" |
@@ -28,6 +29,32 @@ static inline int is_32bit_task(void) | |||
28 | } | 29 | } |
29 | #endif | 30 | #endif |
30 | 31 | ||
32 | /* | ||
33 | * Allocate space for the signal frame | ||
34 | */ | ||
35 | void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
36 | size_t frame_size) | ||
37 | { | ||
38 | unsigned long oldsp, newsp; | ||
39 | |||
40 | /* Default to using normal stack */ | ||
41 | oldsp = regs->gpr[1]; | ||
42 | |||
43 | /* Check for alt stack */ | ||
44 | if ((ka->sa.sa_flags & SA_ONSTACK) && | ||
45 | current->sas_ss_size && !on_sig_stack(oldsp)) | ||
46 | oldsp = (current->sas_ss_sp + current->sas_ss_size); | ||
47 | |||
48 | /* Get aligned frame */ | ||
49 | newsp = (oldsp - frame_size) & ~0xFUL; | ||
50 | |||
51 | /* Check access */ | ||
52 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp)) | ||
53 | return NULL; | ||
54 | |||
55 | return (void __user *)newsp; | ||
56 | } | ||
57 | |||
31 | 58 | ||
32 | /* | 59 | /* |
33 | * Restore the user process's signal mask | 60 | * Restore the user process's signal mask |
@@ -130,20 +157,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
130 | #endif | 157 | #endif |
131 | 158 | ||
132 | if (is32) { | 159 | if (is32) { |
133 | unsigned int newsp; | ||
134 | |||
135 | if ((ka.sa.sa_flags & SA_ONSTACK) && | ||
136 | current->sas_ss_size && !on_sig_stack(regs->gpr[1])) | ||
137 | newsp = current->sas_ss_sp + current->sas_ss_size; | ||
138 | else | ||
139 | newsp = regs->gpr[1]; | ||
140 | |||
141 | if (ka.sa.sa_flags & SA_SIGINFO) | 160 | if (ka.sa.sa_flags & SA_SIGINFO) |
142 | ret = handle_rt_signal32(signr, &ka, &info, oldset, | 161 | ret = handle_rt_signal32(signr, &ka, &info, oldset, |
143 | regs, newsp); | 162 | regs); |
144 | else | 163 | else |
145 | ret = handle_signal32(signr, &ka, &info, oldset, | 164 | ret = handle_signal32(signr, &ka, &info, oldset, |
146 | regs, newsp); | 165 | regs); |
147 | #ifdef CONFIG_PPC64 | 166 | #ifdef CONFIG_PPC64 |
148 | } else { | 167 | } else { |
149 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); | 168 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); |