aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-07-26 08:05:21 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-11-20 07:17:44 -0500
commit4c44aaafa8108f584831850ab48a975e971db2de (patch)
treec86f225e8256d28271acf3ea8926e70358f3e5c1
parentbcf58e725ddc45d31addbc6627d4f0edccc824c1 (diff)
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 <keescook@chromium.org> Cc: James Morris <james.l.morris@oracle.com> Acked-by: Kees Cook <keescook@chromium.org> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--include/linux/cred.h2
-rw-r--r--kernel/ptrace.c10
-rw-r--r--kernel/sched/core.c10
-rw-r--r--security/yama/yama_lsm.c12
4 files changed, 25 insertions, 9 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ebbed2ce6637..856d2622d832 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -357,10 +357,8 @@ static inline void put_cred(const struct cred *_cred)
357extern struct user_namespace init_user_ns; 357extern struct user_namespace init_user_ns;
358#ifdef CONFIG_USER_NS 358#ifdef CONFIG_USER_NS
359#define current_user_ns() (current_cred_xxx(user_ns)) 359#define current_user_ns() (current_cred_xxx(user_ns))
360#define task_user_ns(task) (task_cred_xxx((task), user_ns))
361#else 360#else
362#define current_user_ns() (&init_user_ns) 361#define current_user_ns() (&init_user_ns)
363#define task_user_ns(task) (&init_user_ns)
364#endif 362#endif
365 363
366 364
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1f5e55dda955..7b09b88862cc 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -215,8 +215,12 @@ ok:
215 smp_rmb(); 215 smp_rmb();
216 if (task->mm) 216 if (task->mm)
217 dumpable = get_dumpable(task->mm); 217 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();
219 return -EPERM; 221 return -EPERM;
222 }
223 rcu_read_unlock();
220 224
221 return security_ptrace_access_check(task, mode); 225 return security_ptrace_access_check(task, mode);
222} 226}
@@ -280,8 +284,10 @@ static int ptrace_attach(struct task_struct *task, long request,
280 284
281 if (seize) 285 if (seize)
282 flags |= PT_SEIZED; 286 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))
284 flags |= PT_PTRACE_CAP; 289 flags |= PT_PTRACE_CAP;
290 rcu_read_unlock();
285 task->ptrace = flags; 291 task->ptrace = flags;
286 292
287 __ptrace_link(task, current); 293 __ptrace_link(task, current);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 2d8927fda712..2f5eb1838b3e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4029,8 +4029,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
4029 goto out_free_cpus_allowed; 4029 goto out_free_cpus_allowed;
4030 } 4030 }
4031 retval = -EPERM; 4031 retval = -EPERM;
4032 if (!check_same_owner(p) && !ns_capable(task_user_ns(p), CAP_SYS_NICE)) 4032 if (!check_same_owner(p)) {
4033 goto out_unlock; 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 }
4034 4040
4035 retval = security_task_setscheduler(p); 4041 retval = security_task_setscheduler(p);
4036 if (retval) 4042 if (retval)
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index b4c29848b49d..0e72239aeb05 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -262,14 +262,18 @@ int yama_ptrace_access_check(struct task_struct *child,
262 /* No additional restrictions. */ 262 /* No additional restrictions. */
263 break; 263 break;
264 case YAMA_SCOPE_RELATIONAL: 264 case YAMA_SCOPE_RELATIONAL:
265 rcu_read_lock();
265 if (!task_is_descendant(current, child) && 266 if (!task_is_descendant(current, child) &&
266 !ptracer_exception_found(current, child) && 267 !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))
268 rc = -EPERM; 269 rc = -EPERM;
270 rcu_read_unlock();
269 break; 271 break;
270 case YAMA_SCOPE_CAPABILITY: 272 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))
272 rc = -EPERM; 275 rc = -EPERM;
276 rcu_read_unlock();
273 break; 277 break;
274 case YAMA_SCOPE_NO_ATTACH: 278 case YAMA_SCOPE_NO_ATTACH:
275 default: 279 default:
@@ -307,8 +311,10 @@ int yama_ptrace_traceme(struct task_struct *parent)
307 /* Only disallow PTRACE_TRACEME on more aggressive settings. */ 311 /* Only disallow PTRACE_TRACEME on more aggressive settings. */
308 switch (ptrace_scope) { 312 switch (ptrace_scope) {
309 case YAMA_SCOPE_CAPABILITY: 313 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))
311 rc = -EPERM; 316 rc = -EPERM;
317 rcu_read_unlock();
312 break; 318 break;
313 case YAMA_SCOPE_NO_ATTACH: 319 case YAMA_SCOPE_NO_ATTACH:
314 rc = -EPERM; 320 rc = -EPERM;