aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 619b027e92b5..f2b96b08fb44 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -262,7 +262,7 @@ next_signal(struct sigpending *pending, sigset_t *mask)
262 return sig; 262 return sig;
263} 263}
264 264
265static struct sigqueue *__sigqueue_alloc(struct task_struct *t, unsigned int __nocast flags, 265static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
266 int override_rlimit) 266 int override_rlimit)
267{ 267{
268 struct sigqueue *q = NULL; 268 struct sigqueue *q = NULL;
@@ -397,20 +397,8 @@ void __exit_signal(struct task_struct *tsk)
397 flush_sigqueue(&tsk->pending); 397 flush_sigqueue(&tsk->pending);
398 if (sig) { 398 if (sig) {
399 /* 399 /*
400 * We are cleaning up the signal_struct here. We delayed 400 * We are cleaning up the signal_struct here.
401 * calling exit_itimers until after flush_sigqueue, just in
402 * case our thread-local pending queue contained a queued
403 * timer signal that would have been cleared in
404 * exit_itimers. When that called sigqueue_free, it would
405 * attempt to re-take the tasklist_lock and deadlock. This
406 * can never happen if we ensure that all queues the
407 * timer's signal might be queued on have been flushed
408 * first. The shared_pending queue, and our own pending
409 * queue are the only queues the timer could be on, since
410 * there are no other threads left in the group and timer
411 * signals are constrained to threads inside the group.
412 */ 401 */
413 exit_itimers(sig);
414 exit_thread_group_keys(sig); 402 exit_thread_group_keys(sig);
415 kmem_cache_free(signal_cachep, sig); 403 kmem_cache_free(signal_cachep, sig);
416 } 404 }
@@ -578,7 +566,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
578 * is to alert stop-signal processing code when another 566 * is to alert stop-signal processing code when another
579 * processor has come along and cleared the flag. 567 * processor has come along and cleared the flag.
580 */ 568 */
581 tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; 569 if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
570 tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
582 } 571 }
583 if ( signr && 572 if ( signr &&
584 ((info->si_code & __SI_MASK) == __SI_TIMER) && 573 ((info->si_code & __SI_MASK) == __SI_TIMER) &&
@@ -1192,6 +1181,40 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
1192 return error; 1181 return error;
1193} 1182}
1194 1183
1184/* like kill_proc_info(), but doesn't use uid/euid of "current" */
1185int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid,
1186 uid_t uid, uid_t euid)
1187{
1188 int ret = -EINVAL;
1189 struct task_struct *p;
1190
1191 if (!valid_signal(sig))
1192 return ret;
1193
1194 read_lock(&tasklist_lock);
1195 p = find_task_by_pid(pid);
1196 if (!p) {
1197 ret = -ESRCH;
1198 goto out_unlock;
1199 }
1200 if ((!info || ((unsigned long)info != 1 &&
1201 (unsigned long)info != 2 && SI_FROMUSER(info)))
1202 && (euid != p->suid) && (euid != p->uid)
1203 && (uid != p->suid) && (uid != p->uid)) {
1204 ret = -EPERM;
1205 goto out_unlock;
1206 }
1207 if (sig && p->sighand) {
1208 unsigned long flags;
1209 spin_lock_irqsave(&p->sighand->siglock, flags);
1210 ret = __group_send_sig_info(sig, info, p);
1211 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1212 }
1213out_unlock:
1214 read_unlock(&tasklist_lock);
1215 return ret;
1216}
1217EXPORT_SYMBOL_GPL(kill_proc_info_as_uid);
1195 1218
1196/* 1219/*
1197 * kill_something_info() interprets pid in interesting ways just like kill(2). 1220 * kill_something_info() interprets pid in interesting ways just like kill(2).