diff options
-rw-r--r-- | kernel/exit.c | 25 | ||||
-rw-r--r-- | security/selinux/hooks.c | 2 |
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 | ||
1574 | static 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 | |||
1573 | void __wake_up_parent(struct task_struct *p, struct task_struct *parent) | 1587 | void __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 | ||
1578 | static long do_wait(struct wait_opts *wo) | 1593 | static 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(¤t->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(¤t->signal->wait_chldexit, &wo->child_wait); | ||
1587 | repeat: | 1603 | repeat: |
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 | } |
1625 | end: | 1641 | end: |
1626 | __set_current_state(TASK_RUNNING); | 1642 | __set_current_state(TASK_RUNNING); |
1627 | remove_wait_queue(¤t->signal->wait_chldexit,&wait); | 1643 | remove_wait_queue(¤t->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(¤t->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 | ||