aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-06-24 05:24:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-06-24 05:24:53 -0400
commitf65013d655ac9639f37d3b54189f6468f672e60b (patch)
tree395f8f44cada4613934e309491421b0701e03613
parent94a6df251dd08c6436ebd6d10c68f03659148ce1 (diff)
parent57db7e4a2d92c2d3dfbca4ef8057849b2682436b (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull timer fix from Eric Biederman: "This fixes an issue of confusing injected signals with the signals from posix timers that has existed since posix timers have been in the kernel. This patch is slightly simpler than my earlier version of this patch as I discovered in testing that I had misspelled "#ifdef CONFIG_POSIX_TIMERS". So I deleted that unnecessary test and made setting of resched_timer uncondtional. I have tested this and verified that without this patch there is a nasty hang that is easy to trigger, and with this patch everything works properly" Thomas Gleixner dixit: "It fixes the problem at hand and covers the ptrace case as well, which I missed. Reviewed-and-tested-by: Thomas Gleixner <tglx@linutronix.de>" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: signal: Only reschedule timers on signals timers have sent
-rw-r--r--kernel/signal.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index ca92bcfeb322..45b4c1ffe14e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -510,7 +510,8 @@ int unhandled_signal(struct task_struct *tsk, int sig)
510 return !tsk->ptrace; 510 return !tsk->ptrace;
511} 511}
512 512
513static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) 513static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
514 bool *resched_timer)
514{ 515{
515 struct sigqueue *q, *first = NULL; 516 struct sigqueue *q, *first = NULL;
516 517
@@ -532,6 +533,12 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
532still_pending: 533still_pending:
533 list_del_init(&first->list); 534 list_del_init(&first->list);
534 copy_siginfo(info, &first->info); 535 copy_siginfo(info, &first->info);
536
537 *resched_timer =
538 (first->flags & SIGQUEUE_PREALLOC) &&
539 (info->si_code == SI_TIMER) &&
540 (info->si_sys_private);
541
535 __sigqueue_free(first); 542 __sigqueue_free(first);
536 } else { 543 } else {
537 /* 544 /*
@@ -548,12 +555,12 @@ still_pending:
548} 555}
549 556
550static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, 557static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
551 siginfo_t *info) 558 siginfo_t *info, bool *resched_timer)
552{ 559{
553 int sig = next_signal(pending, mask); 560 int sig = next_signal(pending, mask);
554 561
555 if (sig) 562 if (sig)
556 collect_signal(sig, pending, info); 563 collect_signal(sig, pending, info, resched_timer);
557 return sig; 564 return sig;
558} 565}
559 566
@@ -565,15 +572,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
565 */ 572 */
566int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) 573int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
567{ 574{
575 bool resched_timer = false;
568 int signr; 576 int signr;
569 577
570 /* We only dequeue private signals from ourselves, we don't let 578 /* We only dequeue private signals from ourselves, we don't let
571 * signalfd steal them 579 * signalfd steal them
572 */ 580 */
573 signr = __dequeue_signal(&tsk->pending, mask, info); 581 signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
574 if (!signr) { 582 if (!signr) {
575 signr = __dequeue_signal(&tsk->signal->shared_pending, 583 signr = __dequeue_signal(&tsk->signal->shared_pending,
576 mask, info); 584 mask, info, &resched_timer);
577#ifdef CONFIG_POSIX_TIMERS 585#ifdef CONFIG_POSIX_TIMERS
578 /* 586 /*
579 * itimer signal ? 587 * itimer signal ?
@@ -621,7 +629,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
621 current->jobctl |= JOBCTL_STOP_DEQUEUED; 629 current->jobctl |= JOBCTL_STOP_DEQUEUED;
622 } 630 }
623#ifdef CONFIG_POSIX_TIMERS 631#ifdef CONFIG_POSIX_TIMERS
624 if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { 632 if (resched_timer) {
625 /* 633 /*
626 * Release the siglock to ensure proper locking order 634 * Release the siglock to ensure proper locking order
627 * of timer locks outside of siglocks. Note, we leave 635 * of timer locks outside of siglocks. Note, we leave