aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:41:52 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:41:52 -0400
commit25f9c0817c535a728c1088542230fa327c577c9e (patch)
tree50e60f8d962702d92b94392d536a1c71d77c851c
parentf6b2db1a3e8d141dd144df58900fb0444d5d7c53 (diff)
userns: Generalize the user namespace count into ucount
The same kind of recursive sane default limit and policy countrol that has been implemented for the user namespace is desirable for the other namespaces, so generalize the user namespace refernce count into a ucount. Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-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 */