Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70328660 authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

netns: Add a limit on the number of net namespaces

parent d08311dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ enum ucount_type {
	UCOUNT_PID_NAMESPACES,
	UCOUNT_UTS_NAMESPACES,
	UCOUNT_IPC_NAMESPACES,
	UCOUNT_NET_NAMESPACES,
	UCOUNT_CGROUP_NAMESPACES,
	UCOUNT_COUNTS,
};
+1 −0
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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"),
	{ }
};
+21 −1
Original line number Diff line number Diff line
@@ -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);
	}