aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-18 13:55:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-18 13:55:28 -0500
commita2faf2fc534f57ba26bc4d613795236ed4f5fb1c (patch)
treed75c4daadb469c8f08c498532fbf1fff68879e69 /kernel
parent4351654e3ddf86a04966163dce4def586303e5cc (diff)
parent5155040ed349950e16c093ba8e65ad534994df2a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull (again) user namespace infrastructure changes from Eric Biederman: "Those bugs, those darn embarrasing bugs just want don't want to get fixed. Linus I just updated my mirror of your kernel.org tree and it appears you successfully pulled everything except the last 4 commits that fix those embarrasing bugs. When you get a chance can you please repull my branch" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: userns: Fix typo in description of the limitation of userns_install userns: Add a more complete capability subset test to commit_creds userns: Require CAP_SYS_ADMIN for most uses of setns. Fix cap_capable to only allow owners in the parent user namespace to have caps.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cred.c27
-rw-r--r--kernel/pid_namespace.c3
-rw-r--r--kernel/user_namespace.c2
-rw-r--r--kernel/utsname.c3
4 files changed, 31 insertions, 4 deletions
diff --git a/kernel/cred.c b/kernel/cred.c
index 8888afb846e9..e0573a43c7df 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -372,6 +372,31 @@ error_put:
372 return ret; 372 return ret;
373} 373}
374 374
375static bool cred_cap_issubset(const struct cred *set, const struct cred *subset)
376{
377 const struct user_namespace *set_ns = set->user_ns;
378 const struct user_namespace *subset_ns = subset->user_ns;
379
380 /* If the two credentials are in the same user namespace see if
381 * the capabilities of subset are a subset of set.
382 */
383 if (set_ns == subset_ns)
384 return cap_issubset(subset->cap_permitted, set->cap_permitted);
385
386 /* The credentials are in a different user namespaces
387 * therefore one is a subset of the other only if a set is an
388 * ancestor of subset and set->euid is owner of subset or one
389 * of subsets ancestors.
390 */
391 for (;subset_ns != &init_user_ns; subset_ns = subset_ns->parent) {
392 if ((set_ns == subset_ns->parent) &&
393 uid_eq(subset_ns->owner, set->euid))
394 return true;
395 }
396
397 return false;
398}
399
375/** 400/**
376 * commit_creds - Install new credentials upon the current task 401 * commit_creds - Install new credentials upon the current task
377 * @new: The credentials to be assigned 402 * @new: The credentials to be assigned
@@ -410,7 +435,7 @@ int commit_creds(struct cred *new)
410 !gid_eq(old->egid, new->egid) || 435 !gid_eq(old->egid, new->egid) ||
411 !uid_eq(old->fsuid, new->fsuid) || 436 !uid_eq(old->fsuid, new->fsuid) ||
412 !gid_eq(old->fsgid, new->fsgid) || 437 !gid_eq(old->fsgid, new->fsgid) ||
413 !cap_issubset(new->cap_permitted, old->cap_permitted)) { 438 !cred_cap_issubset(old, new)) {
414 if (task->mm) 439 if (task->mm)
415 set_dumpable(task->mm, suid_dumpable); 440 set_dumpable(task->mm, suid_dumpable);
416 task->pdeath_signal = 0; 441 task->pdeath_signal = 0;
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 560da0dab230..fdbd0cdf271a 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -325,7 +325,8 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
325 struct pid_namespace *active = task_active_pid_ns(current); 325 struct pid_namespace *active = task_active_pid_ns(current);
326 struct pid_namespace *ancestor, *new = ns; 326 struct pid_namespace *ancestor, *new = ns;
327 327
328 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN)) 328 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
329 !nsown_capable(CAP_SYS_ADMIN))
329 return -EPERM; 330 return -EPERM;
330 331
331 /* 332 /*
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index f5975ccf9348..2b042c42fbc4 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -799,7 +799,7 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)
799 if (user_ns == current_user_ns()) 799 if (user_ns == current_user_ns())
800 return -EINVAL; 800 return -EINVAL;
801 801
802 /* Threaded many not enter a different user namespace */ 802 /* Threaded processes may not enter a different user namespace */
803 if (atomic_read(&current->mm->mm_users) > 1) 803 if (atomic_read(&current->mm->mm_users) > 1)
804 return -EINVAL; 804 return -EINVAL;
805 805
diff --git a/kernel/utsname.c b/kernel/utsname.c
index f6336d51d64c..08b197e8c485 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -113,7 +113,8 @@ static int utsns_install(struct nsproxy *nsproxy, void *new)
113{ 113{
114 struct uts_namespace *ns = new; 114 struct uts_namespace *ns = new;
115 115
116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) 116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
117 !nsown_capable(CAP_SYS_ADMIN))
117 return -EPERM; 118 return -EPERM;
118 119
119 get_uts_ns(ns); 120 get_uts_ns(ns);