forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									d08311dd6f
								
							
						
					
					
						commit
						703286608a
					
				
					 4 changed files with 24 additions and 1 deletions
				
			
		|  | @ -29,6 +29,7 @@ enum ucount_type { | |||
| 	UCOUNT_PID_NAMESPACES, | ||||
| 	UCOUNT_UTS_NAMESPACES, | ||||
| 	UCOUNT_IPC_NAMESPACES, | ||||
| 	UCOUNT_NET_NAMESPACES, | ||||
| 	UCOUNT_CGROUP_NAMESPACES, | ||||
| 	UCOUNT_COUNTS, | ||||
| }; | ||||
|  |  | |||
|  | @ -60,6 +60,7 @@ struct net { | |||
| 	struct list_head	exit_list;	/* Use only net_mutex */ | ||||
| 
 | ||||
| 	struct user_namespace   *user_ns;	/* Owning user namespace */ | ||||
| 	struct ucounts		*ucounts; | ||||
| 	spinlock_t		nsid_lock; | ||||
| 	struct idr		netns_ids; | ||||
| 
 | ||||
|  |  | |||
|  | @ -71,6 +71,7 @@ static struct ctl_table user_table[] = { | |||
| 	UCOUNT_ENTRY("max_pid_namespaces"), | ||||
| 	UCOUNT_ENTRY("max_uts_namespaces"), | ||||
| 	UCOUNT_ENTRY("max_ipc_namespaces"), | ||||
| 	UCOUNT_ENTRY("max_net_namespaces"), | ||||
| 	UCOUNT_ENTRY("max_cgroup_namespaces"), | ||||
| 	{ } | ||||
| }; | ||||
|  |  | |||
|  | @ -266,6 +266,16 @@ struct net *get_net_ns_by_id(struct net *net, int id) | |||
| 	return peer; | ||||
| } | ||||
| 
 | ||||
| static struct ucounts *inc_net_namespaces(struct user_namespace *ns) | ||||
| { | ||||
| 	return inc_ucount(ns, current_euid(), UCOUNT_NET_NAMESPACES); | ||||
| } | ||||
| 
 | ||||
| static void dec_net_namespaces(struct ucounts *ucounts) | ||||
| { | ||||
| 	dec_ucount(ucounts, UCOUNT_NET_NAMESPACES); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * setup_net runs the initializers for the network namespace object. | ||||
|  */ | ||||
|  | @ -351,19 +361,27 @@ void net_drop_ns(void *p) | |||
| struct net *copy_net_ns(unsigned long flags, | ||||
| 			struct user_namespace *user_ns, struct net *old_net) | ||||
| { | ||||
| 	struct ucounts *ucounts; | ||||
| 	struct net *net; | ||||
| 	int rv; | ||||
| 
 | ||||
| 	if (!(flags & CLONE_NEWNET)) | ||||
| 		return get_net(old_net); | ||||
| 
 | ||||
| 	ucounts = inc_net_namespaces(user_ns); | ||||
| 	if (!ucounts) | ||||
| 		return ERR_PTR(-ENFILE); | ||||
| 
 | ||||
| 	net = net_alloc(); | ||||
| 	if (!net) | ||||
| 	if (!net) { | ||||
| 		dec_net_namespaces(ucounts); | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 	} | ||||
| 
 | ||||
| 	get_user_ns(user_ns); | ||||
| 
 | ||||
| 	mutex_lock(&net_mutex); | ||||
| 	net->ucounts = ucounts; | ||||
| 	rv = setup_net(net, user_ns); | ||||
| 	if (rv == 0) { | ||||
| 		rtnl_lock(); | ||||
|  | @ -372,6 +390,7 @@ struct net *copy_net_ns(unsigned long flags, | |||
| 	} | ||||
| 	mutex_unlock(&net_mutex); | ||||
| 	if (rv < 0) { | ||||
| 		dec_net_namespaces(ucounts); | ||||
| 		put_user_ns(user_ns); | ||||
| 		net_drop_ns(net); | ||||
| 		return ERR_PTR(rv); | ||||
|  | @ -444,6 +463,7 @@ static void cleanup_net(struct work_struct *work) | |||
| 	/* Finally it is safe to free my network namespace structure */ | ||||
| 	list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | ||||
| 		list_del_init(&net->exit_list); | ||||
| 		dec_net_namespaces(net->ucounts); | ||||
| 		put_user_ns(net->user_ns); | ||||
| 		net_drop_ns(net); | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Eric W. Biederman
						Eric W. Biederman