aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index b27c01a66448..792952381092 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -378,8 +378,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
378 /* We only dequeue private signals from ourselves, we don't let 378 /* We only dequeue private signals from ourselves, we don't let
379 * signalfd steal them 379 * signalfd steal them
380 */ 380 */
381 if (tsk == current) 381 signr = __dequeue_signal(&tsk->pending, mask, info);
382 signr = __dequeue_signal(&tsk->pending, mask, info);
383 if (!signr) { 382 if (!signr) {
384 signr = __dequeue_signal(&tsk->signal->shared_pending, 383 signr = __dequeue_signal(&tsk->signal->shared_pending,
385 mask, info); 384 mask, info);
@@ -407,8 +406,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
407 } 406 }
408 } 407 }
409 } 408 }
410 if (likely(tsk == current)) 409 recalc_sigpending();
411 recalc_sigpending();
412 if (signr && unlikely(sig_kernel_stop(signr))) { 410 if (signr && unlikely(sig_kernel_stop(signr))) {
413 /* 411 /*
414 * Set a marker that we have dequeued a stop signal. Our 412 * Set a marker that we have dequeued a stop signal. Our
@@ -425,7 +423,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
425 if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) 423 if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
426 tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; 424 tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
427 } 425 }
428 if ( signr && 426 if (signr &&
429 ((info->si_code & __SI_MASK) == __SI_TIMER) && 427 ((info->si_code & __SI_MASK) == __SI_TIMER) &&
430 info->si_sys_private){ 428 info->si_sys_private){
431 /* 429 /*
@@ -533,18 +531,18 @@ static int check_kill_permission(int sig, struct siginfo *info,
533 if (!valid_signal(sig)) 531 if (!valid_signal(sig))
534 return error; 532 return error;
535 533
536 error = audit_signal_info(sig, t); /* Let audit system see the signal */ 534 if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) {
537 if (error) 535 error = audit_signal_info(sig, t); /* Let audit system see the signal */
538 return error; 536 if (error)
539 537 return error;
540 error = -EPERM; 538 error = -EPERM;
541 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) 539 if (((sig != SIGCONT) ||
542 && ((sig != SIGCONT) || 540 (process_session(current) != process_session(t)))
543 (process_session(current) != process_session(t))) 541 && (current->euid ^ t->suid) && (current->euid ^ t->uid)
544 && (current->euid ^ t->suid) && (current->euid ^ t->uid) 542 && (current->uid ^ t->suid) && (current->uid ^ t->uid)
545 && (current->uid ^ t->suid) && (current->uid ^ t->uid) 543 && !capable(CAP_KILL))
546 && !capable(CAP_KILL))
547 return error; 544 return error;
545 }
548 546
549 return security_task_kill(t, info, sig, 0); 547 return security_task_kill(t, info, sig, 0);
550} 548}
@@ -1300,20 +1298,19 @@ struct sigqueue *sigqueue_alloc(void)
1300void sigqueue_free(struct sigqueue *q) 1298void sigqueue_free(struct sigqueue *q)
1301{ 1299{
1302 unsigned long flags; 1300 unsigned long flags;
1301 spinlock_t *lock = &current->sighand->siglock;
1302
1303 BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); 1303 BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
1304 /* 1304 /*
1305 * If the signal is still pending remove it from the 1305 * If the signal is still pending remove it from the
1306 * pending queue. 1306 * pending queue. We must hold ->siglock while testing
1307 * q->list to serialize with collect_signal().
1307 */ 1308 */
1308 if (unlikely(!list_empty(&q->list))) { 1309 spin_lock_irqsave(lock, flags);
1309 spinlock_t *lock = &current->sighand->siglock; 1310 if (!list_empty(&q->list))
1310 read_lock(&tasklist_lock); 1311 list_del_init(&q->list);
1311 spin_lock_irqsave(lock, flags); 1312 spin_unlock_irqrestore(lock, flags);
1312 if (!list_empty(&q->list)) 1313
1313 list_del_init(&q->list);
1314 spin_unlock_irqrestore(lock, flags);
1315 read_unlock(&tasklist_lock);
1316 }
1317 q->flags &= ~SIGQUEUE_PREALLOC; 1314 q->flags &= ~SIGQUEUE_PREALLOC;
1318 __sigqueue_free(q); 1315 __sigqueue_free(q);
1319} 1316}