diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-07-27 15:49:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-27 15:53:36 -0400 |
commit | c1095c6da518b0b64e724f629051fa67655cd8d9 (patch) | |
tree | 8c2e33ca6c8e3caa71437c3b69b36a8cf03b4f08 /kernel | |
parent | 678624e401b0b7747762b5223fb23f86dcdacc93 (diff) |
signals: sys_ssetmask/sys_rt_sigsuspend should use set_current_blocked()
sys_ssetmask(), sys_rt_sigsuspend() and compat_sys_rt_sigsuspend()
change ->blocked directly. This is not correct, see the changelog in
e6fa16ab "signal: sigprocmask() should do retarget_shared_pending()"
Change them to use set_current_blocked().
Another change is that now we are doing ->saved_sigmask = ->blocked
lockless, it doesn't make any sense to do this under ->siglock.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Matt Fleming <matt.fleming@linux.intel.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/compat.c | 5 | ||||
-rw-r--r-- | kernel/signal.c | 17 |
2 files changed, 6 insertions, 16 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 18197ae2d465..616c78197cca 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -992,11 +992,8 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat | |||
992 | sigset_from_compat(&newset, &newset32); | 992 | sigset_from_compat(&newset, &newset32); |
993 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 993 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
994 | 994 | ||
995 | spin_lock_irq(¤t->sighand->siglock); | ||
996 | current->saved_sigmask = current->blocked; | 995 | current->saved_sigmask = current->blocked; |
997 | current->blocked = newset; | 996 | set_current_blocked(&newset); |
998 | recalc_sigpending(); | ||
999 | spin_unlock_irq(¤t->sighand->siglock); | ||
1000 | 997 | ||
1001 | current->state = TASK_INTERRUPTIBLE; | 998 | current->state = TASK_INTERRUPTIBLE; |
1002 | schedule(); | 999 | schedule(); |
diff --git a/kernel/signal.c b/kernel/signal.c index d7f70aed1cc0..291c9700be75 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -3102,15 +3102,11 @@ SYSCALL_DEFINE0(sgetmask) | |||
3102 | 3102 | ||
3103 | SYSCALL_DEFINE1(ssetmask, int, newmask) | 3103 | SYSCALL_DEFINE1(ssetmask, int, newmask) |
3104 | { | 3104 | { |
3105 | int old; | 3105 | int old = current->blocked.sig[0]; |
3106 | 3106 | sigset_t newset; | |
3107 | spin_lock_irq(¤t->sighand->siglock); | ||
3108 | old = current->blocked.sig[0]; | ||
3109 | 3107 | ||
3110 | siginitset(¤t->blocked, newmask & ~(sigmask(SIGKILL)| | 3108 | siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP))); |
3111 | sigmask(SIGSTOP))); | 3109 | set_current_blocked(&newset); |
3112 | recalc_sigpending(); | ||
3113 | spin_unlock_irq(¤t->sighand->siglock); | ||
3114 | 3110 | ||
3115 | return old; | 3111 | return old; |
3116 | } | 3112 | } |
@@ -3167,11 +3163,8 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) | |||
3167 | return -EFAULT; | 3163 | return -EFAULT; |
3168 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 3164 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
3169 | 3165 | ||
3170 | spin_lock_irq(¤t->sighand->siglock); | ||
3171 | current->saved_sigmask = current->blocked; | 3166 | current->saved_sigmask = current->blocked; |
3172 | current->blocked = newset; | 3167 | set_current_blocked(&newset); |
3173 | recalc_sigpending(); | ||
3174 | spin_unlock_irq(¤t->sighand->siglock); | ||
3175 | 3168 | ||
3176 | current->state = TASK_INTERRUPTIBLE; | 3169 | current->state = TASK_INTERRUPTIBLE; |
3177 | schedule(); | 3170 | schedule(); |