Skip to content

Commit 4c44aaa

Browse files
committed
userns: Kill task_user_ns
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]>
1 parent bcf58e7 commit 4c44aaa

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

include/linux/cred.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,8 @@ static inline void put_cred(const struct cred *_cred)
357357
extern struct user_namespace init_user_ns;
358358
#ifdef CONFIG_USER_NS
359359
#define current_user_ns() (current_cred_xxx(user_ns))
360-
#define task_user_ns(task) (task_cred_xxx((task), user_ns))
361360
#else
362361
#define current_user_ns() (&init_user_ns)
363-
#define task_user_ns(task) (&init_user_ns)
364362
#endif
365363

366364

kernel/ptrace.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,12 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
215215
smp_rmb();
216216
if (task->mm)
217217
dumpable = get_dumpable(task->mm);
218-
if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
218+
rcu_read_lock();
219+
if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
220+
rcu_read_unlock();
219221
return -EPERM;
222+
}
223+
rcu_read_unlock();
220224

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

281285
if (seize)
282286
flags |= PT_SEIZED;
283-
if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
287+
rcu_read_lock();
288+
if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
284289
flags |= PT_PTRACE_CAP;
290+
rcu_read_unlock();
285291
task->ptrace = flags;
286292

287293
__ptrace_link(task, current);

kernel/sched/core.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4029,8 +4029,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
40294029
goto out_free_cpus_allowed;
40304030
}
40314031
retval = -EPERM;
4032-
if (!check_same_owner(p) && !ns_capable(task_user_ns(p), CAP_SYS_NICE))
4033-
goto out_unlock;
4032+
if (!check_same_owner(p)) {
4033+
rcu_read_lock();
4034+
if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) {
4035+
rcu_read_unlock();
4036+
goto out_unlock;
4037+
}
4038+
rcu_read_unlock();
4039+
}
40344040

40354041
retval = security_task_setscheduler(p);
40364042
if (retval)

security/yama/yama_lsm.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,18 @@ int yama_ptrace_access_check(struct task_struct *child,
262262
/* No additional restrictions. */
263263
break;
264264
case YAMA_SCOPE_RELATIONAL:
265+
rcu_read_lock();
265266
if (!task_is_descendant(current, child) &&
266267
!ptracer_exception_found(current, child) &&
267-
!ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
268+
!ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
268269
rc = -EPERM;
270+
rcu_read_unlock();
269271
break;
270272
case YAMA_SCOPE_CAPABILITY:
271-
if (!ns_capable(task_user_ns(child), CAP_SYS_PTRACE))
273+
rcu_read_lock();
274+
if (!ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
272275
rc = -EPERM;
276+
rcu_read_unlock();
273277
break;
274278
case YAMA_SCOPE_NO_ATTACH:
275279
default:
@@ -307,8 +311,10 @@ int yama_ptrace_traceme(struct task_struct *parent)
307311
/* Only disallow PTRACE_TRACEME on more aggressive settings. */
308312
switch (ptrace_scope) {
309313
case YAMA_SCOPE_CAPABILITY:
310-
if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE))
314+
rcu_read_lock();
315+
if (!ns_capable(__task_cred(parent)->user_ns, CAP_SYS_PTRACE))
311316
rc = -EPERM;
317+
rcu_read_unlock();
312318
break;
313319
case YAMA_SCOPE_NO_ATTACH:
314320
rc = -EPERM;

0 commit comments

Comments
 (0)