diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 94ec0a4dde0f..d81f4952eebb 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -247,14 +247,19 @@ void flush_sigqueue(struct sigpending *queue) | |||
247 | /* | 247 | /* |
248 | * Flush all pending signals for a task. | 248 | * Flush all pending signals for a task. |
249 | */ | 249 | */ |
250 | void __flush_signals(struct task_struct *t) | ||
251 | { | ||
252 | clear_tsk_thread_flag(t, TIF_SIGPENDING); | ||
253 | flush_sigqueue(&t->pending); | ||
254 | flush_sigqueue(&t->signal->shared_pending); | ||
255 | } | ||
256 | |||
250 | void flush_signals(struct task_struct *t) | 257 | void flush_signals(struct task_struct *t) |
251 | { | 258 | { |
252 | unsigned long flags; | 259 | unsigned long flags; |
253 | 260 | ||
254 | spin_lock_irqsave(&t->sighand->siglock, flags); | 261 | spin_lock_irqsave(&t->sighand->siglock, flags); |
255 | clear_tsk_thread_flag(t, TIF_SIGPENDING); | 262 | __flush_signals(t); |
256 | flush_sigqueue(&t->pending); | ||
257 | flush_sigqueue(&t->signal->shared_pending); | ||
258 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 263 | spin_unlock_irqrestore(&t->sighand->siglock, flags); |
259 | } | 264 | } |
260 | 265 | ||
@@ -827,6 +832,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
827 | { | 832 | { |
828 | struct sigpending *pending; | 833 | struct sigpending *pending; |
829 | struct sigqueue *q; | 834 | struct sigqueue *q; |
835 | int override_rlimit; | ||
830 | 836 | ||
831 | trace_sched_signal_send(sig, t); | 837 | trace_sched_signal_send(sig, t); |
832 | 838 | ||
@@ -858,9 +864,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
858 | make sure at least one signal gets delivered and don't | 864 | make sure at least one signal gets delivered and don't |
859 | pass on the info struct. */ | 865 | pass on the info struct. */ |
860 | 866 | ||
861 | q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && | 867 | if (sig < SIGRTMIN) |
862 | (is_si_special(info) || | 868 | override_rlimit = (is_si_special(info) || info->si_code >= 0); |
863 | info->si_code >= 0))); | 869 | else |
870 | override_rlimit = 0; | ||
871 | |||
872 | q = __sigqueue_alloc(t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE, | ||
873 | override_rlimit); | ||
864 | if (q) { | 874 | if (q) { |
865 | list_add_tail(&q->list, &pending->list); | 875 | list_add_tail(&q->list, &pending->list); |
866 | switch ((unsigned long) info) { | 876 | switch ((unsigned long) info) { |
@@ -2276,24 +2286,17 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | |||
2276 | return kill_something_info(sig, &info, pid); | 2286 | return kill_something_info(sig, &info, pid); |
2277 | } | 2287 | } |
2278 | 2288 | ||
2279 | static int do_tkill(pid_t tgid, pid_t pid, int sig) | 2289 | static int |
2290 | do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) | ||
2280 | { | 2291 | { |
2281 | int error; | ||
2282 | struct siginfo info; | ||
2283 | struct task_struct *p; | 2292 | struct task_struct *p; |
2284 | unsigned long flags; | 2293 | unsigned long flags; |
2285 | 2294 | int error = -ESRCH; | |
2286 | error = -ESRCH; | ||
2287 | info.si_signo = sig; | ||
2288 | info.si_errno = 0; | ||
2289 | info.si_code = SI_TKILL; | ||
2290 | info.si_pid = task_tgid_vnr(current); | ||
2291 | info.si_uid = current_uid(); | ||
2292 | 2295 | ||
2293 | rcu_read_lock(); | 2296 | rcu_read_lock(); |
2294 | p = find_task_by_vpid(pid); | 2297 | p = find_task_by_vpid(pid); |
2295 | if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { | 2298 | if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { |
2296 | error = check_kill_permission(sig, &info, p); | 2299 | error = check_kill_permission(sig, info, p); |
2297 | /* | 2300 | /* |
2298 | * The null signal is a permissions and process existence | 2301 | * The null signal is a permissions and process existence |
2299 | * probe. No signal is actually delivered. | 2302 | * probe. No signal is actually delivered. |
@@ -2303,7 +2306,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | |||
2303 | * signal is private anyway. | 2306 | * signal is private anyway. |
2304 | */ | 2307 | */ |
2305 | if (!error && sig && lock_task_sighand(p, &flags)) { | 2308 | if (!error && sig && lock_task_sighand(p, &flags)) { |
2306 | error = specific_send_sig_info(sig, &info, p); | 2309 | error = specific_send_sig_info(sig, info, p); |
2307 | unlock_task_sighand(p, &flags); | 2310 | unlock_task_sighand(p, &flags); |
2308 | } | 2311 | } |
2309 | } | 2312 | } |
@@ -2312,6 +2315,19 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig) | |||
2312 | return error; | 2315 | return error; |
2313 | } | 2316 | } |
2314 | 2317 | ||
2318 | static int do_tkill(pid_t tgid, pid_t pid, int sig) | ||
2319 | { | ||
2320 | struct siginfo info; | ||
2321 | |||
2322 | info.si_signo = sig; | ||
2323 | info.si_errno = 0; | ||
2324 | info.si_code = SI_TKILL; | ||
2325 | info.si_pid = task_tgid_vnr(current); | ||
2326 | info.si_uid = current_uid(); | ||
2327 | |||
2328 | return do_send_specific(tgid, pid, sig, &info); | ||
2329 | } | ||
2330 | |||
2315 | /** | 2331 | /** |
2316 | * sys_tgkill - send signal to one specific thread | 2332 | * sys_tgkill - send signal to one specific thread |
2317 | * @tgid: the thread group ID of the thread | 2333 | * @tgid: the thread group ID of the thread |
@@ -2361,6 +2377,32 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, | |||
2361 | return kill_proc_info(sig, &info, pid); | 2377 | return kill_proc_info(sig, &info, pid); |
2362 | } | 2378 | } |
2363 | 2379 | ||
2380 | long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) | ||
2381 | { | ||
2382 | /* This is only valid for single tasks */ | ||
2383 | if (pid <= 0 || tgid <= 0) | ||
2384 | return -EINVAL; | ||
2385 | |||
2386 | /* Not even root can pretend to send signals from the kernel. | ||
2387 | Nor can they impersonate a kill(), which adds source info. */ | ||
2388 | if (info->si_code >= 0) | ||
2389 | return -EPERM; | ||
2390 | info->si_signo = sig; | ||
2391 | |||
2392 | return do_send_specific(tgid, pid, sig, info); | ||
2393 | } | ||
2394 | |||
2395 | SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig, | ||
2396 | siginfo_t __user *, uinfo) | ||
2397 | { | ||
2398 | siginfo_t info; | ||
2399 | |||
2400 | if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) | ||
2401 | return -EFAULT; | ||
2402 | |||
2403 | return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | ||
2404 | } | ||
2405 | |||
2364 | int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) | 2406 | int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) |
2365 | { | 2407 | { |
2366 | struct task_struct *t = current; | 2408 | struct task_struct *t = current; |