9
9
#include <linux/nsproxy.h>
10
10
#include <linux/slab.h>
11
11
#include <linux/user_namespace.h>
12
+ #include <linux/proc_fs.h>
12
13
#include <linux/highuid.h>
13
14
#include <linux/cred.h>
14
15
#include <linux/securebits.h>
@@ -26,6 +27,24 @@ static struct kmem_cache *user_ns_cachep __read_mostly;
26
27
static bool new_idmap_permitted (struct user_namespace * ns , int cap_setid ,
27
28
struct uid_gid_map * map );
28
29
30
+ static 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
49
* Create a new user namespace, deriving the creator from the user in the
31
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
72
return - ENOMEM ;
54
73
55
74
kref_init (& ns -> kref );
75
+ /* Leave the new->user_ns reference with the new user namespace. */
56
76
ns -> parent = parent_ns ;
57
77
ns -> owner = owner ;
58
78
ns -> group = group ;
59
79
60
- /* Start with the same capabilities as init but useless for doing
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 ;
80
+ set_cred_user_ns (new , ns );
77
81
78
82
return 0 ;
79
83
}
@@ -737,6 +741,58 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
737
741
return false;
738
742
}
739
743
744
+ static 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
+
755
+ static void userns_put (void * ns )
756
+ {
757
+ put_user_ns (ns );
758
+ }
759
+
760
+ static 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
+
788
+ const 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
+
740
796
static __init int user_namespaces_init (void )
741
797
{
742
798
user_ns_cachep = KMEM_CACHE (user_namespace , SLAB_PANIC );
0 commit comments