userns: Add a limit on the number of user namespaces
[cascardo/linux.git] / kernel / ucount.c
1 /*
2  *  This program is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU General Public License as
4  *  published by the Free Software Foundation, version 2 of the
5  *  License.
6  */
7
8 #include <linux/stat.h>
9 #include <linux/sysctl.h>
10 #include <linux/slab.h>
11 #include <linux/user_namespace.h>
12
13 #ifdef CONFIG_SYSCTL
14 static struct ctl_table_set *
15 set_lookup(struct ctl_table_root *root)
16 {
17         return &current_user_ns()->set;
18 }
19
20 static int set_is_seen(struct ctl_table_set *set)
21 {
22         return &current_user_ns()->set == set;
23 }
24
25 static int set_permissions(struct ctl_table_header *head,
26                                   struct ctl_table *table)
27 {
28         struct user_namespace *user_ns =
29                 container_of(head->set, struct user_namespace, set);
30         int mode;
31
32         /* Allow users with CAP_SYS_RESOURCE unrestrained access */
33         if (ns_capable(user_ns, CAP_SYS_RESOURCE))
34                 mode = (table->mode & S_IRWXU) >> 6;
35         else
36         /* Allow all others at most read-only access */
37                 mode = table->mode & S_IROTH;
38         return (mode << 6) | (mode << 3) | mode;
39 }
40
41 static struct ctl_table_root set_root = {
42         .lookup = set_lookup,
43         .permissions = set_permissions,
44 };
45
46 static int zero = 0;
47 static int int_max = INT_MAX;
48 static struct ctl_table userns_table[] = {
49         {
50                 .procname       = "max_user_namespaces",
51                 .data           = &init_user_ns.max_user_namespaces,
52                 .maxlen         = sizeof(init_user_ns.max_user_namespaces),
53                 .mode           = 0644,
54                 .proc_handler   = proc_dointvec_minmax,
55                 .extra1         = &zero,
56                 .extra2         = &int_max,
57         },
58         { }
59 };
60 #endif /* CONFIG_SYSCTL */
61
62 bool setup_userns_sysctls(struct user_namespace *ns)
63 {
64 #ifdef CONFIG_SYSCTL
65         struct ctl_table *tbl;
66         setup_sysctl_set(&ns->set, &set_root, set_is_seen);
67         tbl = kmemdup(userns_table, sizeof(userns_table), GFP_KERNEL);
68         if (tbl) {
69                 tbl[0].data = &ns->max_user_namespaces;
70
71                 ns->sysctls = __register_sysctl_table(&ns->set, "userns", tbl);
72         }
73         if (!ns->sysctls) {
74                 kfree(tbl);
75                 retire_sysctl_set(&ns->set);
76                 return false;
77         }
78 #endif
79         return true;
80 }
81
82 void retire_userns_sysctls(struct user_namespace *ns)
83 {
84 #ifdef CONFIG_SYSCTL
85         struct ctl_table *tbl;
86
87         tbl = ns->sysctls->ctl_table_arg;
88         unregister_sysctl_table(ns->sysctls);
89         retire_sysctl_set(&ns->set);
90         kfree(tbl);
91 #endif
92 }
93
94 static inline bool atomic_inc_below(atomic_t *v, int u)
95 {
96         int c, old;
97         c = atomic_read(v);
98         for (;;) {
99                 if (unlikely(c >= u))
100                         return false;
101                 old = atomic_cmpxchg(v, c, c+1);
102                 if (likely(old == c))
103                         return true;
104                 c = old;
105         }
106 }
107
108 bool inc_user_namespaces(struct user_namespace *ns)
109 {
110         struct user_namespace *pos, *bad;
111         for (pos = ns; pos; pos = pos->parent) {
112                 int max = READ_ONCE(pos->max_user_namespaces);
113                 if (!atomic_inc_below(&pos->user_namespaces, max))
114                         goto fail;
115         }
116         return true;
117 fail:
118         bad = pos;
119         for (pos = ns; pos != bad; pos = pos->parent)
120                 atomic_dec(&pos->user_namespaces);
121
122         return false;
123 }
124
125 void dec_user_namespaces(struct user_namespace *ns)
126 {
127         struct user_namespace *pos;
128         for (pos = ns; pos; pos = pos->parent) {
129                 int dec = atomic_dec_if_positive(&pos->user_namespaces);
130                 WARN_ON_ONCE(dec < 0);
131         }
132 }
133
134 static __init int user_namespace_sysctl_init(void)
135 {
136 #ifdef CONFIG_SYSCTL
137         static struct ctl_table_header *userns_header;
138         static struct ctl_table empty[1];
139         /*
140          * It is necessary to register the userns directory in the
141          * default set so that registrations in the child sets work
142          * properly.
143          */
144         userns_header = register_sysctl("userns", empty);
145         BUG_ON(!userns_header);
146         BUG_ON(!setup_userns_sysctls(&init_user_ns));
147 #endif
148         return 0;
149 }
150 subsys_initcall(user_namespace_sysctl_init);
151
152