aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/signal.h1
-rw-r--r--kernel/signal.c29
2 files changed, 25 insertions, 5 deletions
diff --git a/include/linux/signal.h b/include/linux/signal.h
index fcd2b14b1932..ba009c167275 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -243,6 +243,7 @@ extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
243 siginfo_t *info); 243 siginfo_t *info);
244extern long do_sigpending(void __user *, unsigned long); 244extern long do_sigpending(void __user *, unsigned long);
245extern int sigprocmask(int, sigset_t *, sigset_t *); 245extern int sigprocmask(int, sigset_t *, sigset_t *);
246extern void set_current_blocked(const sigset_t *);
246extern int show_unhandled_signals; 247extern int show_unhandled_signals;
247 248
248struct pt_regs; 249struct pt_regs;
diff --git a/kernel/signal.c b/kernel/signal.c
index e8308e3238c1..8aa3a2e226af 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2299,6 +2299,29 @@ long do_no_restart_syscall(struct restart_block *param)
2299 return -EINTR; 2299 return -EINTR;
2300} 2300}
2301 2301
2302/**
2303 * set_current_blocked - change current->blocked mask
2304 * @newset: new mask
2305 *
2306 * It is wrong to change ->blocked directly, this helper should be used
2307 * to ensure the process can't miss a shared signal we are going to block.
2308 */
2309void set_current_blocked(const sigset_t *newset)
2310{
2311 struct task_struct *tsk = current;
2312
2313 spin_lock_irq(&tsk->sighand->siglock);
2314 if (signal_pending(tsk) && !thread_group_empty(tsk)) {
2315 sigset_t newblocked;
2316 /* A set of now blocked but previously unblocked signals. */
2317 signandsets(&newblocked, newset, &current->blocked);
2318 retarget_shared_pending(tsk, &newblocked);
2319 }
2320 tsk->blocked = *newset;
2321 recalc_sigpending();
2322 spin_unlock_irq(&tsk->sighand->siglock);
2323}
2324
2302/* 2325/*
2303 * This is also useful for kernel threads that want to temporarily 2326 * This is also useful for kernel threads that want to temporarily
2304 * (or permanently) block certain signals. 2327 * (or permanently) block certain signals.
@@ -2330,11 +2353,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
2330 return -EINVAL; 2353 return -EINVAL;
2331 } 2354 }
2332 2355
2333 spin_lock_irq(&tsk->sighand->siglock); 2356 set_current_blocked(&newset);
2334 tsk->blocked = newset;
2335 recalc_sigpending();
2336 spin_unlock_irq(&tsk->sighand->siglock);
2337
2338 return 0; 2357 return 0;
2339} 2358}
2340 2359