diff options
Diffstat (limited to 'net/ipv4/sysctl_net_ipv4.c')
| -rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 218 | 
1 files changed, 92 insertions, 126 deletions
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 540279f4c53..79a007c5255 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -43,12 +43,12 @@ static int ip_ping_group_range_min[] = { 0, 0 };  static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };  /* Update system visible IP port range */ -static void set_local_port_range(int range[2]) +static void set_local_port_range(struct net *net, int range[2])  { -	write_seqlock(&sysctl_local_ports.lock); -	sysctl_local_ports.range[0] = range[0]; -	sysctl_local_ports.range[1] = range[1]; -	write_sequnlock(&sysctl_local_ports.lock); +	write_seqlock(&net->ipv4.ip_local_ports.lock); +	net->ipv4.ip_local_ports.range[0] = range[0]; +	net->ipv4.ip_local_ports.range[1] = range[1]; +	write_sequnlock(&net->ipv4.ip_local_ports.lock);  }  /* Validate changes from /proc interface. */ @@ -56,6 +56,8 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,  				 void __user *buffer,  				 size_t *lenp, loff_t *ppos)  { +	struct net *net = +		container_of(table->data, struct net, ipv4.ip_local_ports.range);  	int ret;  	int range[2];  	struct ctl_table tmp = { @@ -66,14 +68,15 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,  		.extra2 = &ip_local_port_range_max,  	}; -	inet_get_local_port_range(range, range + 1); +	inet_get_local_port_range(net, &range[0], &range[1]); +  	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);  	if (write && ret == 0) {  		if (range[1] < range[0])  			ret = -EINVAL;  		else -			set_local_port_range(range); +			set_local_port_range(net, range);  	}  	return ret; @@ -83,23 +86,27 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,  static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)  {  	kgid_t *data = table->data; +	struct net *net = +		container_of(table->data, struct net, ipv4.ping_group_range.range);  	unsigned int seq;  	do { -		seq = read_seqbegin(&sysctl_local_ports.lock); +		seq = read_seqbegin(&net->ipv4.ip_local_ports.lock);  		*low = data[0];  		*high = data[1]; -	} while (read_seqretry(&sysctl_local_ports.lock, seq)); +	} while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));  }  /* Update system visible IP port range */  static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)  {  	kgid_t *data = table->data; -	write_seqlock(&sysctl_local_ports.lock); +	struct net *net = +		container_of(table->data, struct net, ipv4.ping_group_range.range); +	write_seqlock(&net->ipv4.ip_local_ports.lock);  	data[0] = low;  	data[1] = high; -	write_sequnlock(&sysctl_local_ports.lock); +	write_sequnlock(&net->ipv4.ip_local_ports.lock);  }  /* Validate changes from /proc interface. */ @@ -193,49 +200,6 @@ static int proc_allowed_congestion_control(struct ctl_table *ctl,  	return ret;  } -static int ipv4_tcp_mem(struct ctl_table *ctl, int write, -			   void __user *buffer, size_t *lenp, -			   loff_t *ppos) -{ -	int ret; -	unsigned long vec[3]; -	struct net *net = current->nsproxy->net_ns; -#ifdef CONFIG_MEMCG_KMEM -	struct mem_cgroup *memcg; -#endif - -	struct ctl_table tmp = { -		.data = &vec, -		.maxlen = sizeof(vec), -		.mode = ctl->mode, -	}; - -	if (!write) { -		ctl->data = &net->ipv4.sysctl_tcp_mem; -		return proc_doulongvec_minmax(ctl, write, buffer, lenp, ppos); -	} - -	ret = proc_doulongvec_minmax(&tmp, write, buffer, lenp, ppos); -	if (ret) -		return ret; - -#ifdef CONFIG_MEMCG_KMEM -	rcu_read_lock(); -	memcg = mem_cgroup_from_task(current); - -	tcp_prot_mem(memcg, vec[0], 0); -	tcp_prot_mem(memcg, vec[1], 1); -	tcp_prot_mem(memcg, vec[2], 2); -	rcu_read_unlock(); -#endif - -	net->ipv4.sysctl_tcp_mem[0] = vec[0]; -	net->ipv4.sysctl_tcp_mem[1] = vec[1]; -	net->ipv4.sysctl_tcp_mem[2] = vec[2]; - -	return 0; -} -  static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,  				 void __user *buffer, size_t *lenp,  				 loff_t *ppos) @@ -267,6 +231,11 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,  			ret = -EINVAL;  			goto bad_key;  		} +		/* Generate a dummy secret but don't publish it. This +		 * is needed so we don't regenerate a new key on the +		 * first invocation of tcp_fastopen_cookie_gen +		 */ +		tcp_fastopen_init_key_once(false);  		tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH);  	} @@ -317,13 +286,6 @@ static struct ctl_table ipv4_table[] = {  		.extra2		= &ip_ttl_max,  	},  	{ -		.procname	= "ip_no_pmtu_disc", -		.data		= &ipv4_config.no_pmtu_disc, -		.maxlen		= sizeof(int), -		.mode		= 0644, -		.proc_handler	= proc_dointvec -	}, -	{  		.procname	= "ip_nonlocal_bind",  		.data		= &sysctl_ip_nonlocal_bind,  		.maxlen		= sizeof(int), @@ -475,20 +437,6 @@ static struct ctl_table ipv4_table[] = {  		.proc_handler	= proc_dointvec  	},  	{ -		.procname	= "ip_local_port_range", -		.data		= &sysctl_local_ports.range, -		.maxlen		= sizeof(sysctl_local_ports.range), -		.mode		= 0644, -		.proc_handler	= ipv4_local_port_range, -	}, -	{ -		.procname	= "ip_local_reserved_ports", -		.data		= NULL, /* initialized in sysctl_ipv4_init */ -		.maxlen		= 65536, -		.mode		= 0644, -		.proc_handler	= proc_do_large_bitmap, -	}, -	{  		.procname	= "igmp_max_memberships",  		.data		= &sysctl_igmp_max_memberships,  		.maxlen		= sizeof(int), @@ -552,6 +500,13 @@ static struct ctl_table ipv4_table[] = {  		.proc_handler	= proc_dointvec  	},  	{ +		.procname	= "tcp_mem", +		.maxlen		= sizeof(sysctl_tcp_mem), +		.data		= &sysctl_tcp_mem, +		.mode		= 0644, +		.proc_handler	= proc_doulongvec_minmax, +	}, +	{  		.procname	= "tcp_wmem",  		.data		= &sysctl_tcp_wmem,  		.maxlen		= sizeof(sysctl_tcp_wmem), @@ -732,20 +687,13 @@ static struct ctl_table ipv4_table[] = {  		.proc_handler   = proc_allowed_congestion_control,  	},  	{ -		.procname	= "tcp_max_ssthresh", -		.data		= &sysctl_tcp_max_ssthresh, -		.maxlen		= sizeof(int), -		.mode		= 0644, -		.proc_handler	= proc_dointvec, -	}, -	{  		.procname       = "tcp_thin_linear_timeouts",  		.data           = &sysctl_tcp_thin_linear_timeouts,  		.maxlen         = sizeof(int),  		.mode           = 0644,  		.proc_handler   = proc_dointvec  	}, -        { +	{  		.procname       = "tcp_thin_dupack",  		.data           = &sysctl_tcp_thin_dupack,  		.maxlen         = sizeof(int), @@ -771,6 +719,15 @@ static struct ctl_table ipv4_table[] = {  		.extra2		= &gso_max_segs,  	},  	{ +		.procname	= "tcp_autocorking", +		.data		= &sysctl_tcp_autocorking, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &zero, +		.extra2		= &one, +	}, +	{  		.procname	= "udp_mem",  		.data		= &sysctl_udp_mem,  		.maxlen		= sizeof(sysctl_udp_mem), @@ -841,7 +798,7 @@ static struct ctl_table ipv4_net_table[] = {  	},  	{  		.procname	= "ping_group_range", -		.data		= &init_net.ipv4.sysctl_ping_group_range, +		.data		= &init_net.ipv4.ping_group_range.range,  		.maxlen		= sizeof(gid_t)*2,  		.mode		= 0644,  		.proc_handler	= ipv4_ping_group_range, @@ -854,10 +811,46 @@ static struct ctl_table ipv4_net_table[] = {  		.proc_handler	= proc_dointvec  	},  	{ -		.procname	= "tcp_mem", -		.maxlen		= sizeof(init_net.ipv4.sysctl_tcp_mem), +		.procname	= "ip_local_port_range", +		.maxlen		= sizeof(init_net.ipv4.ip_local_ports.range), +		.data		= &init_net.ipv4.ip_local_ports.range, +		.mode		= 0644, +		.proc_handler	= ipv4_local_port_range, +	}, +	{ +		.procname	= "ip_local_reserved_ports", +		.data		= &init_net.ipv4.sysctl_local_reserved_ports, +		.maxlen		= 65536, +		.mode		= 0644, +		.proc_handler	= proc_do_large_bitmap, +	}, +	{ +		.procname	= "ip_no_pmtu_disc", +		.data		= &init_net.ipv4.sysctl_ip_no_pmtu_disc, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec +	}, +	{ +		.procname	= "ip_forward_use_pmtu", +		.data		= &init_net.ipv4.sysctl_ip_fwd_use_pmtu, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec, +	}, +	{ +		.procname	= "fwmark_reflect", +		.data		= &init_net.ipv4.sysctl_fwmark_reflect, +		.maxlen		= sizeof(int),  		.mode		= 0644, -		.proc_handler	= ipv4_tcp_mem, +		.proc_handler	= proc_dointvec, +	}, +	{ +		.procname	= "tcp_fwmark_accept", +		.data		= &init_net.ipv4.sysctl_tcp_fwmark_accept, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec,  	},  	{ }  }; @@ -868,47 +861,29 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)  	table = ipv4_net_table;  	if (!net_eq(net, &init_net)) { +		int i; +  		table = kmemdup(table, sizeof(ipv4_net_table), GFP_KERNEL);  		if (table == NULL)  			goto err_alloc; -		table[0].data = -			&net->ipv4.sysctl_icmp_echo_ignore_all; -		table[1].data = -			&net->ipv4.sysctl_icmp_echo_ignore_broadcasts; -		table[2].data = -			&net->ipv4.sysctl_icmp_ignore_bogus_error_responses; -		table[3].data = -			&net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr; -		table[4].data = -			&net->ipv4.sysctl_icmp_ratelimit; -		table[5].data = -			&net->ipv4.sysctl_icmp_ratemask; -		table[6].data = -			&net->ipv4.sysctl_ping_group_range; -		table[7].data = -			&net->ipv4.sysctl_tcp_ecn; - -		/* Don't export sysctls to unprivileged users */ -		if (net->user_ns != &init_user_ns) -			table[0].procname = NULL; +		/* Update the variables to point into the current struct net */ +		for (i = 0; i < ARRAY_SIZE(ipv4_net_table) - 1; i++) +			table[i].data += (void *)net - (void *)&init_net;  	} -	/* -	 * Sane defaults - nobody may create ping sockets. -	 * Boot scripts should set this to distro-specific group. -	 */ -	net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); -	net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); - -	tcp_init_mem(net); -  	net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table);  	if (net->ipv4.ipv4_hdr == NULL)  		goto err_reg; +	net->ipv4.sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); +	if (!net->ipv4.sysctl_local_reserved_ports) +		goto err_ports; +  	return 0; +err_ports: +	unregister_net_sysctl_table(net->ipv4.ipv4_hdr);  err_reg:  	if (!net_eq(net, &init_net))  		kfree(table); @@ -920,6 +895,7 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)  {  	struct ctl_table *table; +	kfree(net->ipv4.sysctl_local_reserved_ports);  	table = net->ipv4.ipv4_hdr->ctl_table_arg;  	unregister_net_sysctl_table(net->ipv4.ipv4_hdr);  	kfree(table); @@ -933,16 +909,6 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {  static __init int sysctl_ipv4_init(void)  {  	struct ctl_table_header *hdr; -	struct ctl_table *i; - -	for (i = ipv4_table; i->procname; i++) { -		if (strcmp(i->procname, "ip_local_reserved_ports") == 0) { -			i->data = sysctl_local_reserved_ports; -			break; -		} -	} -	if (!i->procname) -		return -EINVAL;  	hdr = register_net_sysctl(&init_net, "net/ipv4", ipv4_table);  	if (hdr == NULL)  | 
