Skip to content

Commit

Permalink
userns: Kill task_user_ns
Browse files Browse the repository at this point in the history
The task_user_ns function hides the fact that it is getting the user
namespace from struct cred on the task.  struct cred may go away as
soon as the rcu lock is released.  This leads to a race where we
can dereference a stale user namespace pointer.

To make it obvious a struct cred is involved kill task_user_ns.

To kill the race modify the users of task_user_ns to only
reference the user namespace while the rcu lock is held.

Cc: Kees Cook <[email protected]>
Cc: James Morris <[email protected]>
Acked-by: Kees Cook <[email protected]>
Acked-by: Serge Hallyn <[email protected]>
Signed-off-by: "Eric W. Biederman" <[email protected]>
  • Loading branch information
ebiederm committed Nov 20, 2012
1 parent bcf58e7 commit 4c44aaa
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 9 deletions.
2 changes: 0 additions & 2 deletions include/linux/cred.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,8 @@ static inline void put_cred(const struct cred *_cred)
extern struct user_namespace init_user_ns;
#ifdef CONFIG_USER_NS
#define current_user_ns() (current_cred_xxx(user_ns))
#define task_user_ns(task) (task_cred_xxx((task), user_ns))
#else
#define current_user_ns() (&init_user_ns)
#define task_user_ns(task) (&init_user_ns)
#endif


Expand Down
10 changes: 8 additions & 2 deletions kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,12 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
smp_rmb();
if (task->mm)
dumpable = get_dumpable(task->mm);
if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
rcu_read_lock();
if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
rcu_read_unlock();
return -EPERM;
}
rcu_read_unlock();

return security_ptrace_access_check(task, mode);
}
Expand Down Expand Up @@ -280,8 +284,10 @@ static int ptrace_attach(struct task_struct *task, long request,

if (seize)
flags |= PT_SEIZED;
if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
rcu_read_lock();
if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
flags |= PT_PTRACE_CAP;
rcu_read_unlock();
task->ptrace = flags;

__ptrace_link(task, current);
Expand Down
10 changes: 8 additions & 2 deletions kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4029,8 +4029,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
goto out_free_cpus_allowed;
}
retval = -EPERM;
if (!check_same_owner(p) && !ns_capable(task_user_ns(p), CAP_SYS_NICE))
goto out_unlock;
if (!check_same_owner(p)) {
rcu_read_lock();
if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) {
rcu_read_unlock();
goto out_unlock;
}
rcu_read_unlock();
}

retval = security_task_setscheduler(p);
if (retval)
Expand Down
12 changes: 9 additions & 3 deletions security/yama/yama_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,18 @@ int yama_ptrace_access_check(struct task_struct *child,
/* No additional restrictions. */
break;
case YAMA_SCOPE_RELATIONAL:
rcu_read_lock();
if (!task_is_descendant(current, child) &&
!ptracer_exception_found(current, child) &&
!ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
!ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
rc = -EPERM;
rcu_read_unlock();
break;
case YAMA_SCOPE_CAPABILITY:
if (!ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
rcu_read_lock();
if (!ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
rc = -EPERM;
rcu_read_unlock();
break;
case YAMA_SCOPE_NO_ATTACH:
default:
Expand Down Expand Up @@ -307,8 +311,10 @@ int yama_ptrace_traceme(struct task_struct *parent)
/* Only disallow PTRACE_TRACEME on more aggressive settings. */
switch (ptrace_scope) {
case YAMA_SCOPE_CAPABILITY:
if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE))
rcu_read_lock();
if (!ns_capable(__task_cred(parent)->user_ns, CAP_SYS_PTRACE))
rc = -EPERM;
rcu_read_unlock();
break;
case YAMA_SCOPE_NO_ATTACH:
rc = -EPERM;
Expand Down

0 comments on commit 4c44aaa

Please sign in to comment.