aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/user_namespace.h14
-rw-r--r--kernel/fork.c5
-rw-r--r--kernel/ucount.c39
-rw-r--r--kernel/user_namespace.c16
4 files changed, 49 insertions, 25 deletions
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 826de7a12a20..9b676ead35c3 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -23,6 +23,12 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
23#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED 23#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED
24 24
25struct ucounts; 25struct ucounts;
26
27enum ucount_type {
28 UCOUNT_USER_NAMESPACES,
29 UCOUNT_COUNTS,
30};
31
26struct user_namespace { 32struct user_namespace {
27 struct uid_gid_map uid_map; 33 struct uid_gid_map uid_map;
28 struct uid_gid_map gid_map; 34 struct uid_gid_map gid_map;
@@ -46,7 +52,7 @@ struct user_namespace {
46 struct ctl_table_header *sysctls; 52 struct ctl_table_header *sysctls;
47#endif 53#endif
48 struct ucounts *ucounts; 54 struct ucounts *ucounts;
49 int max_user_namespaces; 55 int ucount_max[UCOUNT_COUNTS];
50}; 56};
51 57
52struct ucounts { 58struct ucounts {
@@ -54,15 +60,15 @@ struct ucounts {
54 struct user_namespace *ns; 60 struct user_namespace *ns;
55 kuid_t uid; 61 kuid_t uid;
56 atomic_t count; 62 atomic_t count;
57 atomic_t user_namespaces; 63 atomic_t ucount[UCOUNT_COUNTS];
58}; 64};
59 65
60extern struct user_namespace init_user_ns; 66extern struct user_namespace init_user_ns;
61 67
62bool setup_userns_sysctls(struct user_namespace *ns); 68bool setup_userns_sysctls(struct user_namespace *ns);
63void retire_userns_sysctls(struct user_namespace *ns); 69void retire_userns_sysctls(struct user_namespace *ns);
64struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid); 70struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
65void dec_user_namespaces(struct ucounts *ucounts); 71void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
66 72
67#ifdef CONFIG_USER_NS 73#ifdef CONFIG_USER_NS
68 74
diff --git a/kernel/fork.c b/kernel/fork.c
index d8cde533ace3..3cb4853a59aa 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -302,6 +302,7 @@ int arch_task_struct_size __read_mostly;
302 302
303void __init fork_init(void) 303void __init fork_init(void)
304{ 304{
305 int i;
305#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR 306#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
306#ifndef ARCH_MIN_TASKALIGN 307#ifndef ARCH_MIN_TASKALIGN
307#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES 308#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
@@ -322,7 +323,9 @@ void __init fork_init(void)
322 init_task.signal->rlim[RLIMIT_SIGPENDING] = 323 init_task.signal->rlim[RLIMIT_SIGPENDING] =
323 init_task.signal->rlim[RLIMIT_NPROC]; 324 init_task.signal->rlim[RLIMIT_NPROC];
324 325
325 init_user_ns.max_user_namespaces = max_threads/2; 326 for (i = 0; i < UCOUNT_COUNTS; i++) {
327 init_user_ns.ucount_max[i] = max_threads/2;
328 }
326} 329}
327 330
328int __weak arch_dup_task_struct(struct task_struct *dst, 331int __weak arch_dup_task_struct(struct task_struct *dst,
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 33c418718304..0f9ab3b26185 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -57,16 +57,17 @@ static struct ctl_table_root set_root = {
57 57
58static int zero = 0; 58static int zero = 0;
59static int int_max = INT_MAX; 59static int int_max = INT_MAX;
60#define UCOUNT_ENTRY(name) \
61 { \
62 .procname = name, \
63 .maxlen = sizeof(int), \
64 .mode = 0644, \
65 .proc_handler = proc_dointvec_minmax, \
66 .extra1 = &zero, \
67 .extra2 = &int_max, \
68 }
60static struct ctl_table user_table[] = { 69static struct ctl_table user_table[] = {
61 { 70 UCOUNT_ENTRY("max_user_namespaces"),
62 .procname = "max_user_namespaces",
63 .data = &init_user_ns.max_user_namespaces,
64 .maxlen = sizeof(init_user_ns.max_user_namespaces),
65 .mode = 0644,
66 .proc_handler = proc_dointvec_minmax,
67 .extra1 = &zero,
68 .extra2 = &int_max,
69 },
70 { } 71 { }
71}; 72};
72#endif /* CONFIG_SYSCTL */ 73#endif /* CONFIG_SYSCTL */
@@ -78,8 +79,10 @@ bool setup_userns_sysctls(struct user_namespace *ns)
78 setup_sysctl_set(&ns->set, &set_root, set_is_seen); 79 setup_sysctl_set(&ns->set, &set_root, set_is_seen);
79 tbl = kmemdup(user_table, sizeof(user_table), GFP_KERNEL); 80 tbl = kmemdup(user_table, sizeof(user_table), GFP_KERNEL);
80 if (tbl) { 81 if (tbl) {
81 tbl[0].data = &ns->max_user_namespaces; 82 int i;
82 83 for (i = 0; i < UCOUNT_COUNTS; i++) {
84 tbl[i].data = &ns->ucount_max[i];
85 }
83 ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl); 86 ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl);
84 } 87 }
85 if (!ns->sysctls) { 88 if (!ns->sysctls) {
@@ -172,7 +175,8 @@ static inline bool atomic_inc_below(atomic_t *v, int u)
172 } 175 }
173} 176}
174 177
175struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid) 178struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
179 enum ucount_type type)
176{ 180{
177 struct ucounts *ucounts, *iter, *bad; 181 struct ucounts *ucounts, *iter, *bad;
178 struct user_namespace *tns; 182 struct user_namespace *tns;
@@ -180,31 +184,30 @@ struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid)
180 for (iter = ucounts; iter; iter = tns->ucounts) { 184 for (iter = ucounts; iter; iter = tns->ucounts) {
181 int max; 185 int max;
182 tns = iter->ns; 186 tns = iter->ns;
183 max = READ_ONCE(tns->max_user_namespaces); 187 max = READ_ONCE(tns->ucount_max[type]);
184 if (!atomic_inc_below(&iter->user_namespaces, max)) 188 if (!atomic_inc_below(&iter->ucount[type], max))
185 goto fail; 189 goto fail;
186 } 190 }
187 return ucounts; 191 return ucounts;
188fail: 192fail:
189 bad = iter; 193 bad = iter;
190 for (iter = ucounts; iter != bad; iter = iter->ns->ucounts) 194 for (iter = ucounts; iter != bad; iter = iter->ns->ucounts)
191 atomic_dec(&iter->user_namespaces); 195 atomic_dec(&iter->ucount[type]);
192 196
193 put_ucounts(ucounts); 197 put_ucounts(ucounts);
194 return NULL; 198 return NULL;
195} 199}
196 200
197void dec_user_namespaces(struct ucounts *ucounts) 201void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
198{ 202{
199 struct ucounts *iter; 203 struct ucounts *iter;
200 for (iter = ucounts; iter; iter = iter->ns->ucounts) { 204 for (iter = ucounts; iter; iter = iter->ns->ucounts) {
201 int dec = atomic_dec_if_positive(&iter->user_namespaces); 205 int dec = atomic_dec_if_positive(&iter->ucount[type]);
202 WARN_ON_ONCE(dec < 0); 206 WARN_ON_ONCE(dec < 0);
203 } 207 }
204 put_ucounts(ucounts); 208 put_ucounts(ucounts);
205} 209}
206 210
207
208static __init int user_namespace_sysctl_init(void) 211static __init int user_namespace_sysctl_init(void)
209{ 212{
210#ifdef CONFIG_SYSCTL 213#ifdef CONFIG_SYSCTL
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 58c67e5f851c..0edafe305861 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -31,6 +31,16 @@ static bool new_idmap_permitted(const struct file *file,
31 struct uid_gid_map *map); 31 struct uid_gid_map *map);
32static void free_user_ns(struct work_struct *work); 32static void free_user_ns(struct work_struct *work);
33 33
34static struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid)
35{
36 return inc_ucount(ns, uid, UCOUNT_USER_NAMESPACES);
37}
38
39static void dec_user_namespaces(struct ucounts *ucounts)
40{
41 return dec_ucount(ucounts, UCOUNT_USER_NAMESPACES);
42}
43
34static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) 44static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
35{ 45{
36 /* Start with the same capabilities as init but useless for doing 46 /* Start with the same capabilities as init but useless for doing
@@ -64,7 +74,7 @@ int create_user_ns(struct cred *new)
64 kuid_t owner = new->euid; 74 kuid_t owner = new->euid;
65 kgid_t group = new->egid; 75 kgid_t group = new->egid;
66 struct ucounts *ucounts; 76 struct ucounts *ucounts;
67 int ret; 77 int ret, i;
68 78
69 ret = -EUSERS; 79 ret = -EUSERS;
70 if (parent_ns->level > 32) 80 if (parent_ns->level > 32)
@@ -110,7 +120,9 @@ int create_user_ns(struct cred *new)
110 ns->owner = owner; 120 ns->owner = owner;
111 ns->group = group; 121 ns->group = group;
112 INIT_WORK(&ns->work, free_user_ns); 122 INIT_WORK(&ns->work, free_user_ns);
113 ns->max_user_namespaces = INT_MAX; 123 for (i = 0; i < UCOUNT_COUNTS; i++) {
124 ns->ucount_max[i] = INT_MAX;
125 }
114 ns->ucounts = ucounts; 126 ns->ucounts = ucounts;
115 127
116 /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ 128 /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */