aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:33:23 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-08-08 15:42:04 -0400
commit703286608a220d53584cca5986aad5305eec75ed (patch)
tree2f0476d44dcd98e891697ef7aaef9653b06b1b4e
parentd08311dd6fd8444e39710dd2fb97562895aed8fa (diff)
netns: Add a limit on the number of net 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/net/net_namespace.h1
-rw-r--r--kernel/ucount.c1
-rw-r--r--net/core/net_namespace.c22
4 files changed, 24 insertions, 1 deletions
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index d067f0d3038e..c6bc980b06a9 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -29,6 +29,7 @@ enum ucount_type {
29 UCOUNT_PID_NAMESPACES, 29 UCOUNT_PID_NAMESPACES,
30 UCOUNT_UTS_NAMESPACES, 30 UCOUNT_UTS_NAMESPACES,
31 UCOUNT_IPC_NAMESPACES, 31 UCOUNT_IPC_NAMESPACES,
32 UCOUNT_NET_NAMESPACES,
32 UCOUNT_CGROUP_NAMESPACES, 33 UCOUNT_CGROUP_NAMESPACES,
33 UCOUNT_COUNTS, 34 UCOUNT_COUNTS,
34}; 35};
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 0933c7455a30..fc4f757107df 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -60,6 +60,7 @@ struct net {
60 struct list_head exit_list; /* Use only net_mutex */ 60 struct list_head exit_list; /* Use only net_mutex */
61 61
62 struct user_namespace *user_ns; /* Owning user namespace */ 62 struct user_namespace *user_ns; /* Owning user namespace */
63 struct ucounts *ucounts;
63 spinlock_t nsid_lock; 64 spinlock_t nsid_lock;
64 struct idr netns_ids; 65 struct idr netns_ids;
65 66
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 335cc5d2cdd7..205f1a07faac 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -71,6 +71,7 @@ static struct ctl_table user_table[] = {
71 UCOUNT_ENTRY("max_pid_namespaces"), 71 UCOUNT_ENTRY("max_pid_namespaces"),
72 UCOUNT_ENTRY("max_uts_namespaces"), 72 UCOUNT_ENTRY("max_uts_namespaces"),
73 UCOUNT_ENTRY("max_ipc_namespaces"), 73 UCOUNT_ENTRY("max_ipc_namespaces"),
74 UCOUNT_ENTRY("max_net_namespaces"),
74 UCOUNT_ENTRY("max_cgroup_namespaces"), 75 UCOUNT_ENTRY("max_cgroup_namespaces"),
75 { } 76 { }
76}; 77};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b629b1..3e2812aeceb7 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -266,6 +266,16 @@ struct net *get_net_ns_by_id(struct net *net, int id)
266 return peer; 266 return peer;
267} 267}
268 268
269static struct ucounts *inc_net_namespaces(struct user_namespace *ns)
270{
271 return inc_ucount(ns, current_euid(), UCOUNT_NET_NAMESPACES);
272}
273
274static void dec_net_namespaces(struct ucounts *ucounts)
275{
276 dec_ucount(ucounts, UCOUNT_NET_NAMESPACES);
277}
278
269/* 279/*
270 * setup_net runs the initializers for the network namespace object. 280 * setup_net runs the initializers for the network namespace object.
271 */ 281 */
@@ -351,19 +361,27 @@ void net_drop_ns(void *p)
351struct net *copy_net_ns(unsigned long flags, 361struct net *copy_net_ns(unsigned long flags,
352 struct user_namespace *user_ns, struct net *old_net) 362 struct user_namespace *user_ns, struct net *old_net)
353{ 363{
364 struct ucounts *ucounts;
354 struct net *net; 365 struct net *net;
355 int rv; 366 int rv;
356 367
357 if (!(flags & CLONE_NEWNET)) 368 if (!(flags & CLONE_NEWNET))
358 return get_net(old_net); 369 return get_net(old_net);
359 370
371 ucounts = inc_net_namespaces(user_ns);
372 if (!ucounts)
373 return ERR_PTR(-ENFILE);
374
360 net = net_alloc(); 375 net = net_alloc();
361 if (!net) 376 if (!net) {
377 dec_net_namespaces(ucounts);
362 return ERR_PTR(-ENOMEM); 378 return ERR_PTR(-ENOMEM);
379 }
363 380
364 get_user_ns(user_ns); 381 get_user_ns(user_ns);
365 382
366 mutex_lock(&net_mutex); 383 mutex_lock(&net_mutex);
384 net->ucounts = ucounts;
367 rv = setup_net(net, user_ns); 385 rv = setup_net(net, user_ns);
368 if (rv == 0) { 386 if (rv == 0) {
369 rtnl_lock(); 387 rtnl_lock();
@@ -372,6 +390,7 @@ struct net *copy_net_ns(unsigned long flags,
372 } 390 }
373 mutex_unlock(&net_mutex); 391 mutex_unlock(&net_mutex);
374 if (rv < 0) { 392 if (rv < 0) {
393 dec_net_namespaces(ucounts);
375 put_user_ns(user_ns); 394 put_user_ns(user_ns);
376 net_drop_ns(net); 395 net_drop_ns(net);
377 return ERR_PTR(rv); 396 return ERR_PTR(rv);
@@ -444,6 +463,7 @@ static void cleanup_net(struct work_struct *work)
444 /* Finally it is safe to free my network namespace structure */ 463 /* Finally it is safe to free my network namespace structure */
445 list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { 464 list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
446 list_del_init(&net->exit_list); 465 list_del_init(&net->exit_list);
466 dec_net_namespaces(net->ucounts);
447 put_user_ns(net->user_ns); 467 put_user_ns(net->user_ns);
448 net_drop_ns(net); 468 net_drop_ns(net);
449 } 469 }