aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/user_namespace.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-07-26 09:24:06 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-11-20 07:18:13 -0500
commitcde1975bc242f3e1072bde623ef378e547b73f91 (patch)
tree2c40083144c71d2aa2be39ed65f610570261f647 /kernel/user_namespace.c
parent4c44aaafa8108f584831850ab48a975e971db2de (diff)
userns: Implent proc namespace operations
This allows entering a user namespace, and the ability to store a reference to a user namespace with a bind mount. Addition of missing userns_ns_put in userns_install from Gao feng <gaofeng@cn.fujitsu.com> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r--kernel/user_namespace.c90
1 files changed, 73 insertions, 17 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 49096d559e08..a9460774e77d 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -9,6 +9,7 @@
9#include <linux/nsproxy.h> 9#include <linux/nsproxy.h>
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/user_namespace.h> 11#include <linux/user_namespace.h>
12#include <linux/proc_fs.h>
12#include <linux/highuid.h> 13#include <linux/highuid.h>
13#include <linux/cred.h> 14#include <linux/cred.h>
14#include <linux/securebits.h> 15#include <linux/securebits.h>
@@ -26,6 +27,24 @@ static struct kmem_cache *user_ns_cachep __read_mostly;
26static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, 27static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
27 struct uid_gid_map *map); 28 struct uid_gid_map *map);
28 29
30static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
31{
32 /* Start with the same capabilities as init but useless for doing
33 * anything as the capabilities are bound to the new user namespace.
34 */
35 cred->securebits = SECUREBITS_DEFAULT;
36 cred->cap_inheritable = CAP_EMPTY_SET;
37 cred->cap_permitted = CAP_FULL_SET;
38 cred->cap_effective = CAP_FULL_SET;
39 cred->cap_bset = CAP_FULL_SET;
40#ifdef CONFIG_KEYS
41 key_put(cred->request_key_auth);
42 cred->request_key_auth = NULL;
43#endif
44 /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
45 cred->user_ns = user_ns;
46}
47
29/* 48/*
30 * Create a new user namespace, deriving the creator from the user in the 49 * Create a new user namespace, deriving the creator from the user in the
31 * passed credentials, and replacing that user with the new root user for the 50 * passed credentials, and replacing that user with the new root user for the
@@ -53,27 +72,12 @@ int create_user_ns(struct cred *new)
53 return -ENOMEM; 72 return -ENOMEM;
54 73
55 kref_init(&ns->kref); 74 kref_init(&ns->kref);
75 /* Leave the new->user_ns reference with the new user namespace. */
56 ns->parent = parent_ns; 76 ns->parent = parent_ns;
57 ns->owner = owner; 77 ns->owner = owner;
58 ns->group = group; 78 ns->group = group;
59 79
60 /* Start with the same capabilities as init but useless for doing 80 set_cred_user_ns(new, ns);
61 * anything as the capabilities are bound to the new user namespace.
62 */
63 new->securebits = SECUREBITS_DEFAULT;
64 new->cap_inheritable = CAP_EMPTY_SET;
65 new->cap_permitted = CAP_FULL_SET;
66 new->cap_effective = CAP_FULL_SET;
67 new->cap_bset = CAP_FULL_SET;
68#ifdef CONFIG_KEYS
69 key_put(new->request_key_auth);
70 new->request_key_auth = NULL;
71#endif
72 /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
73
74 /* Leave the new->user_ns reference with the new user namespace. */
75 /* Leave the reference to our user_ns with the new cred. */
76 new->user_ns = ns;
77 81
78 return 0; 82 return 0;
79} 83}
@@ -737,6 +741,58 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
737 return false; 741 return false;
738} 742}
739 743
744static void *userns_get(struct task_struct *task)
745{
746 struct user_namespace *user_ns;
747
748 rcu_read_lock();
749 user_ns = get_user_ns(__task_cred(task)->user_ns);
750 rcu_read_unlock();
751
752 return user_ns;
753}
754
755static void userns_put(void *ns)
756{
757 put_user_ns(ns);
758}
759
760static int userns_install(struct nsproxy *nsproxy, void *ns)
761{
762 struct user_namespace *user_ns = ns;
763 struct cred *cred;
764
765 /* Don't allow gaining capabilities by reentering
766 * the same user namespace.
767 */
768 if (user_ns == current_user_ns())
769 return -EINVAL;
770
771 /* Threaded many not enter a different user namespace */
772 if (atomic_read(&current->mm->mm_users) > 1)
773 return -EINVAL;
774
775 if (!ns_capable(user_ns, CAP_SYS_ADMIN))
776 return -EPERM;
777
778 cred = prepare_creds();
779 if (!cred)
780 return -ENOMEM;
781
782 put_user_ns(cred->user_ns);
783 set_cred_user_ns(cred, get_user_ns(user_ns));
784
785 return commit_creds(cred);
786}
787
788const struct proc_ns_operations userns_operations = {
789 .name = "user",
790 .type = CLONE_NEWUSER,
791 .get = userns_get,
792 .put = userns_put,
793 .install = userns_install,
794};
795
740static __init int user_namespaces_init(void) 796static __init int user_namespaces_init(void)
741{ 797{
742 user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC); 798 user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC);