Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 84666
b: refs/heads/master
c: 161550d
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman authored and Linus Torvalds committed Feb 8, 2008
1 parent 338e29f commit 21e9150
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 25 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5dee1707dfbfc55eb7569b9ae5abaf932bd4c377
refs/heads/master: 161550d74c07303ffa6187ba776f62df5a906a21
80 changes: 56 additions & 24 deletions trunk/kernel/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,20 +1090,23 @@ asmlinkage void sys_exit_group(int error_code)
do_group_exit((error_code & 0xff) << 8);
}

static int eligible_child(pid_t pid, int options, struct task_struct *p)
static struct pid *task_pid_type(struct task_struct *task, enum pid_type type)
{
struct pid *pid = NULL;
if (type == PIDTYPE_PID)
pid = task->pids[type].pid;
else if (type < PIDTYPE_MAX)
pid = task->group_leader->pids[type].pid;
return pid;
}

static int eligible_child(enum pid_type type, struct pid *pid, int options,
struct task_struct *p)
{
int err;
struct pid_namespace *ns;

ns = current->nsproxy->pid_ns;
if (pid > 0) {
if (task_pid_nr_ns(p, ns) != pid)
return 0;
} else if (!pid) {
if (task_pgrp_nr_ns(p, ns) != task_pgrp_vnr(current))
return 0;
} else if (pid != -1) {
if (task_pgrp_nr_ns(p, ns) != -pid)
if (type < PIDTYPE_MAX) {
if (task_pid_type(p, type) != pid)
return 0;
}

Expand All @@ -1127,7 +1130,7 @@ static int eligible_child(pid_t pid, int options, struct task_struct *p)
if (likely(!err))
return 1;

if (pid <= 0)
if (type != PIDTYPE_PID)
return 0;
/* This child was explicitly requested, abort */
read_unlock(&tasklist_lock);
Expand Down Expand Up @@ -1447,15 +1450,21 @@ static int wait_task_continued(struct task_struct *p, int noreap,
return retval;
}

static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
int __user *stat_addr, struct rusage __user *ru)
static long do_wait(enum pid_type type, struct pid *pid, int options,
struct siginfo __user *infop, int __user *stat_addr,
struct rusage __user *ru)
{
DECLARE_WAITQUEUE(wait, current);
struct task_struct *tsk;
int flag, retval;

add_wait_queue(&current->signal->wait_chldexit,&wait);
repeat:
/* If there is nothing that can match our critier just get out */
retval = -ECHILD;
if ((type < PIDTYPE_MAX) && (!pid || hlist_empty(&pid->tasks[type])))
goto end;

/*
* We will set this flag if we see any child that might later
* match our criteria, even if we are not able to reap it yet.
Expand All @@ -1468,7 +1477,7 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
struct task_struct *p;

list_for_each_entry(p, &tsk->children, sibling) {
int ret = eligible_child(pid, options, p);
int ret = eligible_child(type, pid, options, p);
if (!ret)
continue;

Expand Down Expand Up @@ -1515,7 +1524,7 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
if (!flag) {
list_for_each_entry(p, &tsk->ptrace_children,
ptrace_list) {
flag = eligible_child(pid, options, p);
flag = eligible_child(type, pid, options, p);
if (!flag)
continue;
if (likely(flag > 0))
Expand Down Expand Up @@ -1570,10 +1579,12 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
return retval;
}

asmlinkage long sys_waitid(int which, pid_t pid,
asmlinkage long sys_waitid(int which, pid_t upid,
struct siginfo __user *infop, int options,
struct rusage __user *ru)
{
struct pid *pid = NULL;
enum pid_type type;
long ret;

if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED))
Expand All @@ -1583,37 +1594,58 @@ asmlinkage long sys_waitid(int which, pid_t pid,

switch (which) {
case P_ALL:
pid = -1;
type = PIDTYPE_MAX;
break;
case P_PID:
if (pid <= 0)
type = PIDTYPE_PID;
if (upid <= 0)
return -EINVAL;
break;
case P_PGID:
if (pid <= 0)
type = PIDTYPE_PGID;
if (upid <= 0)
return -EINVAL;
pid = -pid;
break;
default:
return -EINVAL;
}

ret = do_wait(pid, options, infop, NULL, ru);
if (type < PIDTYPE_MAX)
pid = find_get_pid(upid);
ret = do_wait(type, pid, options, infop, NULL, ru);
put_pid(pid);

/* avoid REGPARM breakage on x86: */
prevent_tail_call(ret);
return ret;
}

asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
asmlinkage long sys_wait4(pid_t upid, int __user *stat_addr,
int options, struct rusage __user *ru)
{
struct pid *pid = NULL;
enum pid_type type;
long ret;

if (options & ~(WNOHANG|WUNTRACED|WCONTINUED|
__WNOTHREAD|__WCLONE|__WALL))
return -EINVAL;
ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru);

if (upid == -1)
type = PIDTYPE_MAX;
else if (upid < 0) {
type = PIDTYPE_PGID;
pid = find_get_pid(-upid);
} else if (upid == 0) {
type = PIDTYPE_PGID;
pid = get_pid(task_pgrp(current));
} else /* upid > 0 */ {
type = PIDTYPE_PID;
pid = find_get_pid(upid);
}

ret = do_wait(type, pid, options | WEXITED, NULL, stat_addr, ru);
put_pid(pid);

/* avoid REGPARM breakage on x86: */
prevent_tail_call(ret);
Expand Down

0 comments on commit 21e9150

Please sign in to comment.