do_wait: return security_task_wait() error code in place of -ECHILD
This reverts the effect of commitf2cc3eb133
"do_wait: fix security checks". That change reverted the effect of commit7324328446
. The rationale for the original commit still stands. The inconsistent treatment of children hidden by ptrace was an unintended omission in the original change and in no way invalidates its purpose. This makes do_wait return the error returned by security_task_wait() (usually -EACCES) in place of -ECHILD when there are some children the caller would be able to wait for if not for the permission failure. A permission error will give the user a clue to look for security policy problems, rather than for mysterious wait bugs. Signed-off-by: Roland McGrath <roland@redhat.com>
This commit is contained in:
parent
f470021adb
commit
14dd0b8141
|
@ -1199,14 +1199,10 @@ static int eligible_child(enum pid_type type, struct pid *pid, int options,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = security_task_wait(p);
|
err = security_task_wait(p);
|
||||||
if (likely(!err))
|
if (err)
|
||||||
return 1;
|
return err;
|
||||||
|
|
||||||
if (type != PIDTYPE_PID)
|
return 1;
|
||||||
return 0;
|
|
||||||
/* This child was explicitly requested, abort */
|
|
||||||
read_unlock(&tasklist_lock);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wait_noreap_copyout(struct task_struct *p, pid_t pid, uid_t uid,
|
static int wait_noreap_copyout(struct task_struct *p, pid_t pid, uid_t uid,
|
||||||
|
@ -1536,7 +1532,8 @@ static int wait_task_continued(struct task_struct *p, int options,
|
||||||
* -ECHILD should be in *@notask_error before the first call.
|
* -ECHILD should be in *@notask_error before the first call.
|
||||||
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
|
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
|
||||||
* Returns zero if the search for a child should continue;
|
* Returns zero if the search for a child should continue;
|
||||||
* then *@notask_error is 0 if @p is an eligible child, or still -ECHILD.
|
* then *@notask_error is 0 if @p is an eligible child,
|
||||||
|
* or another error from security_task_wait(), or still -ECHILD.
|
||||||
*/
|
*/
|
||||||
static int wait_consider_task(struct task_struct *parent, int ptrace,
|
static int wait_consider_task(struct task_struct *parent, int ptrace,
|
||||||
struct task_struct *p, int *notask_error,
|
struct task_struct *p, int *notask_error,
|
||||||
|
@ -1545,9 +1542,21 @@ static int wait_consider_task(struct task_struct *parent, int ptrace,
|
||||||
int __user *stat_addr, struct rusage __user *ru)
|
int __user *stat_addr, struct rusage __user *ru)
|
||||||
{
|
{
|
||||||
int ret = eligible_child(type, pid, options, p);
|
int ret = eligible_child(type, pid, options, p);
|
||||||
if (ret <= 0)
|
if (!ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (unlikely(ret < 0)) {
|
||||||
|
/*
|
||||||
|
* If we have not yet seen any eligible child,
|
||||||
|
* then let this error code replace -ECHILD.
|
||||||
|
* A permission error will give the user a clue
|
||||||
|
* to look for security policy problems, rather
|
||||||
|
* than for mysterious wait bugs.
|
||||||
|
*/
|
||||||
|
if (*notask_error)
|
||||||
|
*notask_error = ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (likely(!ptrace) && unlikely(p->ptrace)) {
|
if (likely(!ptrace) && unlikely(p->ptrace)) {
|
||||||
/*
|
/*
|
||||||
* This child is hidden by ptrace.
|
* This child is hidden by ptrace.
|
||||||
|
@ -1585,7 +1594,8 @@ static int wait_consider_task(struct task_struct *parent, int ptrace,
|
||||||
* -ECHILD should be in *@notask_error before the first call.
|
* -ECHILD should be in *@notask_error before the first call.
|
||||||
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
|
* Returns nonzero for a final return, when we have unlocked tasklist_lock.
|
||||||
* Returns zero if the search for a child should continue; then
|
* Returns zero if the search for a child should continue; then
|
||||||
* *@notask_error is 0 if there were any eligible children, or still -ECHILD.
|
* *@notask_error is 0 if there were any eligible children,
|
||||||
|
* or another error from security_task_wait(), or still -ECHILD.
|
||||||
*/
|
*/
|
||||||
static int do_wait_thread(struct task_struct *tsk, int *notask_error,
|
static int do_wait_thread(struct task_struct *tsk, int *notask_error,
|
||||||
enum pid_type type, struct pid *pid, int options,
|
enum pid_type type, struct pid *pid, int options,
|
||||||
|
|
Loading…
Reference in New Issue