diff options
Diffstat (limited to 'arch/m32r/kernel/signal.c')
-rw-r--r-- | arch/m32r/kernel/signal.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index 6e3c26a1607..a08697f0886 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/unistd.h> | 20 | #include <linux/unistd.h> |
21 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
22 | #include <linux/personality.h> | 22 | #include <linux/personality.h> |
23 | #include <linux/freezer.h> | ||
23 | #include <linux/tracehook.h> | 24 | #include <linux/tracehook.h> |
24 | #include <asm/cacheflush.h> | 25 | #include <asm/cacheflush.h> |
25 | #include <asm/ucontext.h> | 26 | #include <asm/ucontext.h> |
@@ -27,6 +28,8 @@ | |||
27 | 28 | ||
28 | #define DEBUG_SIG 0 | 29 | #define DEBUG_SIG 0 |
29 | 30 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
32 | |||
30 | asmlinkage int | 33 | asmlinkage int |
31 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 34 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
32 | unsigned long r2, unsigned long r3, unsigned long r4, | 35 | unsigned long r2, unsigned long r3, unsigned long r4, |
@@ -108,7 +111,11 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1, | |||
108 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 111 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
109 | goto badframe; | 112 | goto badframe; |
110 | 113 | ||
111 | set_current_blocked(&set); | 114 | sigdelsetmask(&set, ~_BLOCKABLE); |
115 | spin_lock_irq(¤t->sighand->siglock); | ||
116 | current->blocked = set; | ||
117 | recalc_sigpending(); | ||
118 | spin_unlock_irq(¤t->sighand->siglock); | ||
112 | 119 | ||
113 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) | 120 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) |
114 | goto badframe; | 121 | goto badframe; |
@@ -263,9 +270,9 @@ static int prev_insn(struct pt_regs *regs) | |||
263 | * OK, we're invoking a handler | 270 | * OK, we're invoking a handler |
264 | */ | 271 | */ |
265 | 272 | ||
266 | static void | 273 | static int |
267 | handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | 274 | handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, |
268 | struct pt_regs *regs) | 275 | sigset_t *oldset, struct pt_regs *regs) |
269 | { | 276 | { |
270 | /* Are we from a system call? */ | 277 | /* Are we from a system call? */ |
271 | if (regs->syscall_nr >= 0) { | 278 | if (regs->syscall_nr >= 0) { |
@@ -285,15 +292,21 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
285 | case -ERESTARTNOINTR: | 292 | case -ERESTARTNOINTR: |
286 | regs->r0 = regs->orig_r0; | 293 | regs->r0 = regs->orig_r0; |
287 | if (prev_insn(regs) < 0) | 294 | if (prev_insn(regs) < 0) |
288 | return; | 295 | return -EFAULT; |
289 | } | 296 | } |
290 | } | 297 | } |
291 | 298 | ||
292 | /* Set up the stack frame */ | 299 | /* Set up the stack frame */ |
293 | if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs)) | 300 | if (setup_rt_frame(sig, ka, info, oldset, regs)) |
294 | return; | 301 | return -EFAULT; |
295 | 302 | ||
296 | signal_delivered(sig, info, ka, regs, 0); | 303 | spin_lock_irq(¤t->sighand->siglock); |
304 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
305 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
306 | sigaddset(¤t->blocked,sig); | ||
307 | recalc_sigpending(); | ||
308 | spin_unlock_irq(¤t->sighand->siglock); | ||
309 | return 0; | ||
297 | } | 310 | } |
298 | 311 | ||
299 | /* | 312 | /* |
@@ -306,6 +319,7 @@ static void do_signal(struct pt_regs *regs) | |||
306 | siginfo_t info; | 319 | siginfo_t info; |
307 | int signr; | 320 | int signr; |
308 | struct k_sigaction ka; | 321 | struct k_sigaction ka; |
322 | sigset_t *oldset; | ||
309 | 323 | ||
310 | /* | 324 | /* |
311 | * We want the common case to go fast, which | 325 | * We want the common case to go fast, which |
@@ -316,6 +330,14 @@ static void do_signal(struct pt_regs *regs) | |||
316 | if (!user_mode(regs)) | 330 | if (!user_mode(regs)) |
317 | return; | 331 | return; |
318 | 332 | ||
333 | if (try_to_freeze()) | ||
334 | goto no_signal; | ||
335 | |||
336 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
337 | oldset = ¤t->saved_sigmask; | ||
338 | else | ||
339 | oldset = ¤t->blocked; | ||
340 | |||
319 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 341 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
320 | if (signr > 0) { | 342 | if (signr > 0) { |
321 | /* Re-enable any watchpoints before delivering the | 343 | /* Re-enable any watchpoints before delivering the |
@@ -325,11 +347,13 @@ static void do_signal(struct pt_regs *regs) | |||
325 | */ | 347 | */ |
326 | 348 | ||
327 | /* Whee! Actually deliver the signal. */ | 349 | /* Whee! Actually deliver the signal. */ |
328 | handle_signal(signr, &ka, &info, regs); | 350 | if (handle_signal(signr, &ka, &info, oldset, regs) == 0) |
351 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
329 | 352 | ||
330 | return; | 353 | return; |
331 | } | 354 | } |
332 | 355 | ||
356 | no_signal: | ||
333 | /* Did we come from a system call? */ | 357 | /* Did we come from a system call? */ |
334 | if (regs->syscall_nr >= 0) { | 358 | if (regs->syscall_nr >= 0) { |
335 | /* Restart the system call - no handlers present */ | 359 | /* Restart the system call - no handlers present */ |
@@ -344,7 +368,10 @@ static void do_signal(struct pt_regs *regs) | |||
344 | prev_insn(regs); | 368 | prev_insn(regs); |
345 | } | 369 | } |
346 | } | 370 | } |
347 | restore_saved_sigmask(); | 371 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { |
372 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
373 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
374 | } | ||
348 | } | 375 | } |
349 | 376 | ||
350 | /* | 377 | /* |
@@ -364,5 +391,9 @@ void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) | |||
364 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 391 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
365 | clear_thread_flag(TIF_NOTIFY_RESUME); | 392 | clear_thread_flag(TIF_NOTIFY_RESUME); |
366 | tracehook_notify_resume(regs); | 393 | tracehook_notify_resume(regs); |
394 | if (current->replacement_session_keyring) | ||
395 | key_replace_session_keyring(); | ||
367 | } | 396 | } |
397 | |||
398 | clear_thread_flag(TIF_IRET); | ||
368 | } | 399 | } |