diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-02-14 06:40:56 -0500 |
---|---|---|
committer | Jonas Bonn <jonas@southpole.se> | 2012-02-17 03:55:24 -0500 |
commit | e933c70de0e2590d41f5edd3133e7ee12b4e0bc6 (patch) | |
tree | 24269d0b02a250e4879be37629405263da5198dc /arch/openrisc | |
parent | b675eeb743abaa0b99a35c1fd32fea8e13a17d32 (diff) |
OpenRISC: Don't mask signals if we fail to setup signal stack
setup_rt_frame() needs to return an indication of whether it succeeded
or failed in setting up the signal stack frame. If setup_rt_frame()
fails then we must not modify current->blocked.
Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux@lists.openrisc.net
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Jonas Bonn <jonas@southpole.se>
Diffstat (limited to 'arch/openrisc')
-rw-r--r-- | arch/openrisc/kernel/signal.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 92d2218fcb97..14764e827a67 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c | |||
@@ -189,8 +189,8 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
189 | * trampoline which performs the syscall sigreturn, or a provided | 189 | * trampoline which performs the syscall sigreturn, or a provided |
190 | * user-mode trampoline. | 190 | * user-mode trampoline. |
191 | */ | 191 | */ |
192 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 192 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
193 | sigset_t *set, struct pt_regs *regs) | 193 | sigset_t *set, struct pt_regs *regs) |
194 | { | 194 | { |
195 | struct rt_sigframe *frame; | 195 | struct rt_sigframe *frame; |
196 | unsigned long return_ip; | 196 | unsigned long return_ip; |
@@ -247,18 +247,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
247 | /* actually move the usp to reflect the stacked frame */ | 247 | /* actually move the usp to reflect the stacked frame */ |
248 | regs->sp = (unsigned long)frame; | 248 | regs->sp = (unsigned long)frame; |
249 | 249 | ||
250 | return; | 250 | return 0; |
251 | 251 | ||
252 | give_sigsegv: | 252 | give_sigsegv: |
253 | force_sigsegv(sig, current); | 253 | force_sigsegv(sig, current); |
254 | return -EFAULT; | ||
254 | } | 255 | } |
255 | 256 | ||
256 | static inline void | 257 | static inline int |
257 | handle_signal(unsigned long sig, | 258 | handle_signal(unsigned long sig, |
258 | siginfo_t *info, struct k_sigaction *ka, | 259 | siginfo_t *info, struct k_sigaction *ka, |
259 | sigset_t *oldset, struct pt_regs *regs) | 260 | sigset_t *oldset, struct pt_regs *regs) |
260 | { | 261 | { |
261 | setup_rt_frame(sig, ka, info, oldset, regs); | 262 | int ret; |
263 | |||
264 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||
265 | if (ret) | ||
266 | return ret; | ||
262 | 267 | ||
263 | spin_lock_irq(¤t->sighand->siglock); | 268 | spin_lock_irq(¤t->sighand->siglock); |
264 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 269 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
@@ -267,6 +272,8 @@ handle_signal(unsigned long sig, | |||
267 | recalc_sigpending(); | 272 | recalc_sigpending(); |
268 | 273 | ||
269 | spin_unlock_irq(¤t->sighand->siglock); | 274 | spin_unlock_irq(¤t->sighand->siglock); |
275 | |||
276 | return 0; | ||
270 | } | 277 | } |
271 | 278 | ||
272 | /* | 279 | /* |
@@ -355,13 +362,13 @@ void do_signal(struct pt_regs *regs) | |||
355 | oldset = ¤t->blocked; | 362 | oldset = ¤t->blocked; |
356 | 363 | ||
357 | /* Whee! Actually deliver the signal. */ | 364 | /* Whee! Actually deliver the signal. */ |
358 | handle_signal(signr, &info, &ka, oldset, regs); | 365 | if (!handle_signal(signr, &info, &ka, oldset, regs)) { |
359 | /* a signal was successfully delivered; the saved | 366 | /* a signal was successfully delivered; the saved |
360 | * sigmask will have been stored in the signal frame, | 367 | * sigmask will have been stored in the signal frame, |
361 | * and will be restored by sigreturn, so we can simply | 368 | * and will be restored by sigreturn, so we can simply |
362 | * clear the TIF_RESTORE_SIGMASK flag */ | 369 | * clear the TIF_RESTORE_SIGMASK flag */ |
363 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
364 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 370 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
371 | } | ||
365 | 372 | ||
366 | tracehook_signal_handler(signr, &info, &ka, regs, | 373 | tracehook_signal_handler(signr, &info, &ka, regs, |
367 | test_thread_flag(TIF_SINGLESTEP)); | 374 | test_thread_flag(TIF_SINGLESTEP)); |