aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namespace.c3
-rw-r--r--ipc/namespace.c3
-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
-rw-r--r--net/core/net_namespace.c3
-rw-r--r--security/commoncap.c25
8 files changed, 54 insertions, 15 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c1bbe86f4920..398a50ff2438 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2781,7 +2781,8 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns)
2781 struct path root; 2781 struct path root;
2782 2782
2783 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || 2783 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
2784 !nsown_capable(CAP_SYS_CHROOT)) 2784 !nsown_capable(CAP_SYS_CHROOT) ||
2785 !nsown_capable(CAP_SYS_ADMIN))
2785 return -EPERM; 2786 return -EPERM;
2786 2787
2787 if (fs->users != 1) 2788 if (fs->users != 1)
diff --git a/ipc/namespace.c b/ipc/namespace.c
index cf3386a51de2..7c1fa451b0b0 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -170,7 +170,8 @@ static void ipcns_put(void *ns)
170static int ipcns_install(struct nsproxy *nsproxy, void *new) 170static int ipcns_install(struct nsproxy *nsproxy, void *new)
171{ 171{
172 struct ipc_namespace *ns = new; 172 struct ipc_namespace *ns = new;
173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) 173 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
174 !nsown_capable(CAP_SYS_ADMIN))
174 return -EPERM; 175 return -EPERM;
175 176
176 /* Ditch state from the old ipc namespace */ 177 /* Ditch state from the old ipc namespace */
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);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2e9a3132b8dd..8acce01b6dab 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -649,7 +649,8 @@ static int netns_install(struct nsproxy *nsproxy, void *ns)
649{ 649{
650 struct net *net = ns; 650 struct net *net = ns;
651 651
652 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN)) 652 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||
653 !nsown_capable(CAP_SYS_ADMIN))
653 return -EPERM; 654 return -EPERM;
654 655
655 put_net(nsproxy->net_ns); 656 put_net(nsproxy->net_ns);
diff --git a/security/commoncap.c b/security/commoncap.c
index 6dbae4650abe..7ee08c756d6b 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -76,24 +76,33 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
76int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, 76int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
77 int cap, int audit) 77 int cap, int audit)
78{ 78{
79 for (;;) { 79 struct user_namespace *ns = targ_ns;
80 /* The owner of the user namespace has all caps. */
81 if (targ_ns != &init_user_ns && uid_eq(targ_ns->owner, cred->euid))
82 return 0;
83 80
81 /* See if cred has the capability in the target user namespace
82 * by examining the target user namespace and all of the target
83 * user namespace's parents.
84 */
85 for (;;) {
84 /* Do we have the necessary capabilities? */ 86 /* Do we have the necessary capabilities? */
85 if (targ_ns == cred->user_ns) 87 if (ns == cred->user_ns)
86 return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; 88 return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
87 89
88 /* Have we tried all of the parent namespaces? */ 90 /* Have we tried all of the parent namespaces? */
89 if (targ_ns == &init_user_ns) 91 if (ns == &init_user_ns)
90 return -EPERM; 92 return -EPERM;
91 93
94 /*
95 * The owner of the user namespace in the parent of the
96 * user namespace has all caps.
97 */
98 if ((ns->parent == cred->user_ns) && uid_eq(ns->owner, cred->euid))
99 return 0;
100
92 /* 101 /*
93 *If you have a capability in a parent user ns, then you have 102 * If you have a capability in a parent user ns, then you have
94 * it over all children user namespaces as well. 103 * it over all children user namespaces as well.
95 */ 104 */
96 targ_ns = targ_ns->parent; 105 ns = ns->parent;
97 } 106 }
98 107
99 /* We never get here */ 108 /* We never get here */