aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/exit.c25
-rw-r--r--security/selinux/hooks.c2
2 files changed, 22 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index ef2dfa818bf1..7838b4d68774 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1097,6 +1097,7 @@ struct wait_opts {
1097 int __user *wo_stat; 1097 int __user *wo_stat;
1098 struct rusage __user *wo_rusage; 1098 struct rusage __user *wo_rusage;
1099 1099
1100 wait_queue_t child_wait;
1100 int notask_error; 1101 int notask_error;
1101}; 1102};
1102 1103
@@ -1570,20 +1571,35 @@ static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk)
1570 return 0; 1571 return 0;
1571} 1572}
1572 1573
1574static int child_wait_callback(wait_queue_t *wait, unsigned mode,
1575 int sync, void *key)
1576{
1577 struct wait_opts *wo = container_of(wait, struct wait_opts,
1578 child_wait);
1579 struct task_struct *p = key;
1580
1581 if (!eligible_child(wo, p))
1582 return 0;
1583
1584 return default_wake_function(wait, mode, sync, key);
1585}
1586
1573void __wake_up_parent(struct task_struct *p, struct task_struct *parent) 1587void __wake_up_parent(struct task_struct *p, struct task_struct *parent)
1574{ 1588{
1575 wake_up_interruptible_sync(&parent->signal->wait_chldexit); 1589 __wake_up_sync_key(&parent->signal->wait_chldexit,
1590 TASK_INTERRUPTIBLE, 1, p);
1576} 1591}
1577 1592
1578static long do_wait(struct wait_opts *wo) 1593static long do_wait(struct wait_opts *wo)
1579{ 1594{
1580 DECLARE_WAITQUEUE(wait, current);
1581 struct task_struct *tsk; 1595 struct task_struct *tsk;
1582 int retval; 1596 int retval;
1583 1597
1584 trace_sched_process_wait(wo->wo_pid); 1598 trace_sched_process_wait(wo->wo_pid);
1585 1599
1586 add_wait_queue(&current->signal->wait_chldexit,&wait); 1600 init_waitqueue_func_entry(&wo->child_wait, child_wait_callback);
1601 wo->child_wait.private = current;
1602 add_wait_queue(&current->signal->wait_chldexit, &wo->child_wait);
1587repeat: 1603repeat:
1588 /* 1604 /*
1589 * If there is nothing that can match our critiera just get out. 1605 * If there is nothing that can match our critiera just get out.
@@ -1624,7 +1640,8 @@ notask:
1624 } 1640 }
1625end: 1641end:
1626 __set_current_state(TASK_RUNNING); 1642 __set_current_state(TASK_RUNNING);
1627 remove_wait_queue(&current->signal->wait_chldexit,&wait); 1643 remove_wait_queue(&current->signal->wait_chldexit, &wo->child_wait);
1644
1628 if (wo->wo_info) { 1645 if (wo->wo_info) {
1629 struct siginfo __user *infop = wo->wo_info; 1646 struct siginfo __user *infop = wo->wo_info;
1630 1647
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 417f7c994522..bb230d5d7085 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2411,7 +2411,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2411 /* Wake up the parent if it is waiting so that it can recheck 2411 /* Wake up the parent if it is waiting so that it can recheck
2412 * wait permission to the new task SID. */ 2412 * wait permission to the new task SID. */
2413 read_lock(&tasklist_lock); 2413 read_lock(&tasklist_lock);
2414 wake_up_interruptible(&current->real_parent->signal->wait_chldexit); 2414 __wake_up_parent(current, current->real_parent);
2415 read_unlock(&tasklist_lock); 2415 read_unlock(&tasklist_lock);
2416} 2416}
2417 2417