aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:11:25 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:42:02 -0400
commitf7af3d1c03136275b876f58644599b120cf4ffdd (patch)
treeca152c99d9a25b1bad1ddf1b1ea4026e8da6e7cb
parentf333c700c6100b53050980986be922bb21466e29 (diff)
utsns: Add a limit on the number of uts namespaces
Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--include/linux/user_namespace.h1
-rw-r--r--include/linux/utsname.h1
-rw-r--r--kernel/ucount.c1
-rw-r--r--kernel/utsname.c34
4 files changed, 32 insertions, 5 deletions
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 9ee94827728d..f9df7dd2609a 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -27,6 +27,7 @@ struct ucounts;
27enum ucount_type { 27enum ucount_type {
28 UCOUNT_USER_NAMESPACES, 28 UCOUNT_USER_NAMESPACES,
29 UCOUNT_PID_NAMESPACES, 29 UCOUNT_PID_NAMESPACES,
30 UCOUNT_UTS_NAMESPACES,
30 UCOUNT_COUNTS, 31 UCOUNT_COUNTS,
31}; 32};
32 33
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 5093f58ae192..60f0bb83b313 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -24,6 +24,7 @@ struct uts_namespace {
24 struct kref kref; 24 struct kref kref;
25 struct new_utsname name; 25 struct new_utsname name;
26 struct user_namespace *user_ns; 26 struct user_namespace *user_ns;
27 struct ucounts *ucounts;
27 struct ns_common ns; 28 struct ns_common ns;
28}; 29};
29extern struct uts_namespace init_uts_ns; 30extern struct uts_namespace init_uts_ns;
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 66eca94e4ada..866850e2eb92 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -69,6 +69,7 @@ static int int_max = INT_MAX;
69static struct ctl_table user_table[] = { 69static struct ctl_table user_table[] = {
70 UCOUNT_ENTRY("max_user_namespaces"), 70 UCOUNT_ENTRY("max_user_namespaces"),
71 UCOUNT_ENTRY("max_pid_namespaces"), 71 UCOUNT_ENTRY("max_pid_namespaces"),
72 UCOUNT_ENTRY("max_uts_namespaces"),
72 { } 73 { }
73}; 74};
74#endif /* CONFIG_SYSCTL */ 75#endif /* CONFIG_SYSCTL */
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 831ea7108232..f3b0bb4ac3ba 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -17,6 +17,16 @@
17#include <linux/user_namespace.h> 17#include <linux/user_namespace.h>
18#include <linux/proc_ns.h> 18#include <linux/proc_ns.h>
19 19
20static struct ucounts *inc_uts_namespaces(struct user_namespace *ns)
21{
22 return inc_ucount(ns, current_euid(), UCOUNT_UTS_NAMESPACES);
23}
24
25static void dec_uts_namespaces(struct ucounts *ucounts)
26{
27 dec_ucount(ucounts, UCOUNT_UTS_NAMESPACES);
28}
29
20static struct uts_namespace *create_uts_ns(void) 30static struct uts_namespace *create_uts_ns(void)
21{ 31{
22 struct uts_namespace *uts_ns; 32 struct uts_namespace *uts_ns;
@@ -36,18 +46,24 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
36 struct uts_namespace *old_ns) 46 struct uts_namespace *old_ns)
37{ 47{
38 struct uts_namespace *ns; 48 struct uts_namespace *ns;
49 struct ucounts *ucounts;
39 int err; 50 int err;
40 51
52 err = -ENFILE;
53 ucounts = inc_uts_namespaces(user_ns);
54 if (!ucounts)
55 goto fail;
56
57 err = -ENOMEM;
41 ns = create_uts_ns(); 58 ns = create_uts_ns();
42 if (!ns) 59 if (!ns)
43 return ERR_PTR(-ENOMEM); 60 goto fail_dec;
44 61
45 err = ns_alloc_inum(&ns->ns); 62 err = ns_alloc_inum(&ns->ns);
46 if (err) { 63 if (err)
47 kfree(ns); 64 goto fail_free;
48 return ERR_PTR(err);
49 }
50 65
66 ns->ucounts = ucounts;
51 ns->ns.ops = &utsns_operations; 67 ns->ns.ops = &utsns_operations;
52 68
53 down_read(&uts_sem); 69 down_read(&uts_sem);
@@ -55,6 +71,13 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
55 ns->user_ns = get_user_ns(user_ns); 71 ns->user_ns = get_user_ns(user_ns);
56 up_read(&uts_sem); 72 up_read(&uts_sem);
57 return ns; 73 return ns;
74
75fail_free:
76 kfree(ns);
77fail_dec:
78 dec_uts_namespaces(ucounts);
79fail:
80 return ERR_PTR(err);
58} 81}
59 82
60/* 83/*
@@ -85,6 +108,7 @@ void free_uts_ns(struct kref *kref)
85 struct uts_namespace *ns; 108 struct uts_namespace *ns;
86 109
87 ns = container_of(kref, struct uts_namespace, kref); 110 ns = container_of(kref, struct uts_namespace, kref);
111 dec_uts_namespaces(ns->ucounts);
88 put_user_ns(ns->user_ns); 112 put_user_ns(ns->user_ns);
89 ns_free_inum(&ns->ns); 113 ns_free_inum(&ns->ns);
90 kfree(ns); 114 kfree(ns);