Commit 0bbf87d8 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

net ipv4: Convert ipv4.ip_local_port_range to be per netns v3

- Move sysctl_local_ports from a global variable into struct netns_ipv4.
- Modify inet_get_local_port_range to take a struct net, and update all
  of the callers.
- Move the initialization of sysctl_local_ports into
   sysctl_net_ipv4.c:ipv4_sysctl_init_net from inet_connection_sock.c

v2:
- Ensure indentation used tabs
- Fixed ip.h so it applies cleanly to todays net-next

v3:
- Compile fixes of strange callers of inet_get_local_port_range.
  This patch now successfully passes an allmodconfig build.
  Removed manual inlining of inet_get_local_port_range in ipv4_local_port_range
Originally-by: default avatarSamya <samya@twitter.com>
Acked-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 56d7b53f
...@@ -2294,7 +2294,7 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) ...@@ -2294,7 +2294,7 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
int low, high, remaining; int low, high, remaining;
unsigned int rover; unsigned int rover;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&init_net, &low, &high);
remaining = (high - low) + 1; remaining = (high - low) + 1;
rover = net_random() % remaining + low; rover = net_random() % remaining + low;
retry: retry:
......
...@@ -2089,7 +2089,7 @@ static void vxlan_setup(struct net_device *dev) ...@@ -2089,7 +2089,7 @@ static void vxlan_setup(struct net_device *dev)
vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.function = vxlan_cleanup;
vxlan->age_timer.data = (unsigned long) vxlan; vxlan->age_timer.data = (unsigned long) vxlan;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(dev_net(dev), &low, &high);
vxlan->port_min = low; vxlan->port_min = low;
vxlan->port_max = high; vxlan->port_max = high;
vxlan->dst_port = htons(vxlan_port); vxlan->dst_port = htons(vxlan_port);
......
...@@ -217,11 +217,7 @@ static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ]) ...@@ -217,11 +217,7 @@ static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
} }
} }
extern struct local_ports { void inet_get_local_port_range(struct net *net, int *low, int *high);
seqlock_t lock;
int range[2];
} sysctl_local_ports;
void inet_get_local_port_range(int *low, int *high);
extern unsigned long *sysctl_local_reserved_ports; extern unsigned long *sysctl_local_reserved_ports;
static inline int inet_is_reserved_local_port(int port) static inline int inet_is_reserved_local_port(int port)
......
...@@ -15,6 +15,10 @@ struct fib_rules_ops; ...@@ -15,6 +15,10 @@ struct fib_rules_ops;
struct hlist_head; struct hlist_head;
struct fib_table; struct fib_table;
struct sock; struct sock;
struct local_ports {
seqlock_t lock;
int range[2];
};
struct netns_ipv4 { struct netns_ipv4 {
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
...@@ -62,6 +66,8 @@ struct netns_ipv4 { ...@@ -62,6 +66,8 @@ struct netns_ipv4 {
int sysctl_icmp_ratemask; int sysctl_icmp_ratemask;
int sysctl_icmp_errors_use_inbound_ifaddr; int sysctl_icmp_errors_use_inbound_ifaddr;
struct local_ports sysctl_local_ports;
int sysctl_tcp_ecn; int sysctl_tcp_ecn;
kgid_t sysctl_ping_group_range[2]; kgid_t sysctl_ping_group_range[2];
......
...@@ -29,27 +29,19 @@ const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n"; ...@@ -29,27 +29,19 @@ const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
EXPORT_SYMBOL(inet_csk_timer_bug_msg); EXPORT_SYMBOL(inet_csk_timer_bug_msg);
#endif #endif
/*
* This struct holds the first and last local port number.
*/
struct local_ports sysctl_local_ports __read_mostly = {
.lock = __SEQLOCK_UNLOCKED(sysctl_local_ports.lock),
.range = { 32768, 61000 },
};
unsigned long *sysctl_local_reserved_ports; unsigned long *sysctl_local_reserved_ports;
EXPORT_SYMBOL(sysctl_local_reserved_ports); EXPORT_SYMBOL(sysctl_local_reserved_ports);
void inet_get_local_port_range(int *low, int *high) void inet_get_local_port_range(struct net *net, int *low, int *high)
{ {
unsigned int seq; unsigned int seq;
do { do {
seq = read_seqbegin(&sysctl_local_ports.lock); seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
*low = sysctl_local_ports.range[0]; *low = net->ipv4.sysctl_local_ports.range[0];
*high = sysctl_local_ports.range[1]; *high = net->ipv4.sysctl_local_ports.range[1];
} while (read_seqretry(&sysctl_local_ports.lock, seq)); } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
} }
EXPORT_SYMBOL(inet_get_local_port_range); EXPORT_SYMBOL(inet_get_local_port_range);
...@@ -116,7 +108,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) ...@@ -116,7 +108,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
int remaining, rover, low, high; int remaining, rover, low, high;
again: again:
inet_get_local_port_range(&low, &high); inet_get_local_port_range(net, &low, &high);
remaining = (high - low) + 1; remaining = (high - low) + 1;
smallest_rover = rover = net_random() % remaining + low; smallest_rover = rover = net_random() % remaining + low;
......
...@@ -494,7 +494,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, ...@@ -494,7 +494,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
u32 offset = hint + port_offset; u32 offset = hint + port_offset;
struct inet_timewait_sock *tw = NULL; struct inet_timewait_sock *tw = NULL;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(net, &low, &high);
remaining = (high - low) + 1; remaining = (high - low) + 1;
local_bh_disable(); local_bh_disable();
......
...@@ -237,11 +237,11 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, ...@@ -237,11 +237,11 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
unsigned int seq; unsigned int seq;
do { do {
seq = read_seqbegin(&sysctl_local_ports.lock); seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
*low = data[0]; *low = data[0];
*high = data[1]; *high = data[1];
} while (read_seqretry(&sysctl_local_ports.lock, seq)); } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
} }
......
...@@ -43,12 +43,12 @@ static int ip_ping_group_range_min[] = { 0, 0 }; ...@@ -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 }; static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
/* Update system visible IP port range */ /* 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); write_seqlock(&net->ipv4.sysctl_local_ports.lock);
sysctl_local_ports.range[0] = range[0]; net->ipv4.sysctl_local_ports.range[0] = range[0];
sysctl_local_ports.range[1] = range[1]; net->ipv4.sysctl_local_ports.range[1] = range[1];
write_sequnlock(&sysctl_local_ports.lock); write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
} }
/* Validate changes from /proc interface. */ /* Validate changes from /proc interface. */
...@@ -56,6 +56,8 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, ...@@ -56,6 +56,8 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
void __user *buffer, void __user *buffer,
size_t *lenp, loff_t *ppos) size_t *lenp, loff_t *ppos)
{ {
struct net *net =
container_of(table->data, struct net, ipv4.sysctl_local_ports.range);
int ret; int ret;
int range[2]; int range[2];
struct ctl_table tmp = { struct ctl_table tmp = {
...@@ -66,14 +68,15 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, ...@@ -66,14 +68,15 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
.extra2 = &ip_local_port_range_max, .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); ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
if (write && ret == 0) { if (write && ret == 0) {
if (range[1] < range[0]) if (range[1] < range[0])
ret = -EINVAL; ret = -EINVAL;
else else
set_local_port_range(range); set_local_port_range(net, range);
} }
return ret; return ret;
...@@ -83,23 +86,27 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, ...@@ -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) static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)
{ {
kgid_t *data = table->data; kgid_t *data = table->data;
struct net *net =
container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
unsigned int seq; unsigned int seq;
do { do {
seq = read_seqbegin(&sysctl_local_ports.lock); seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
*low = data[0]; *low = data[0];
*high = data[1]; *high = data[1];
} while (read_seqretry(&sysctl_local_ports.lock, seq)); } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
} }
/* Update system visible IP port range */ /* Update system visible IP port range */
static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
{ {
kgid_t *data = table->data; kgid_t *data = table->data;
write_seqlock(&sysctl_local_ports.lock); struct net *net =
container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
write_seqlock(&net->ipv4.sysctl_local_ports.lock);
data[0] = low; data[0] = low;
data[1] = high; data[1] = high;
write_sequnlock(&sysctl_local_ports.lock); write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
} }
/* Validate changes from /proc interface. */ /* Validate changes from /proc interface. */
...@@ -474,13 +481,6 @@ static struct ctl_table ipv4_table[] = { ...@@ -474,13 +481,6 @@ static struct ctl_table ipv4_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec .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", .procname = "ip_local_reserved_ports",
.data = NULL, /* initialized in sysctl_ipv4_init */ .data = NULL, /* initialized in sysctl_ipv4_init */
...@@ -853,6 +853,13 @@ static struct ctl_table ipv4_net_table[] = { ...@@ -853,6 +853,13 @@ static struct ctl_table ipv4_net_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec .proc_handler = proc_dointvec
}, },
{
.procname = "ip_local_port_range",
.maxlen = sizeof(init_net.ipv4.sysctl_local_ports.range),
.data = &init_net.ipv4.sysctl_local_ports.range,
.mode = 0644,
.proc_handler = ipv4_local_port_range,
},
{ {
.procname = "tcp_mem", .procname = "tcp_mem",
.maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem), .maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem),
...@@ -888,6 +895,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) ...@@ -888,6 +895,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
&net->ipv4.sysctl_ping_group_range; &net->ipv4.sysctl_ping_group_range;
table[7].data = table[7].data =
&net->ipv4.sysctl_tcp_ecn; &net->ipv4.sysctl_tcp_ecn;
table[8].data =
&net->ipv4.sysctl_local_ports.range;
/* Don't export sysctls to unprivileged users */ /* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns) if (net->user_ns != &init_user_ns)
...@@ -901,6 +910,13 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) ...@@ -901,6 +910,13 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); 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); net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0);
/*
* Set defaults for local port range
*/
seqlock_init(&net->ipv4.sysctl_local_ports.lock);
net->ipv4.sysctl_local_ports.range[0] = 32768;
net->ipv4.sysctl_local_ports.range[1] = 61000;
tcp_init_mem(net); tcp_init_mem(net);
net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table);
......
...@@ -219,7 +219,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -219,7 +219,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
unsigned short first, last; unsigned short first, last;
DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);
inet_get_local_port_range(&low, &high); inet_get_local_port_range(net, &low, &high);
remaining = (high - low) + 1; remaining = (high - low) + 1;
rand = net_random(); rand = net_random();
......
...@@ -173,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) ...@@ -173,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
skb->local_df = 1; skb->local_df = 1;
inet_get_local_port_range(&port_min, &port_max); inet_get_local_port_range(net, &port_min, &port_max);
src_port = vxlan_src_port(port_min, port_max, skb); src_port = vxlan_src_port(port_min, port_max, skb);
err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
......
...@@ -5890,7 +5890,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) ...@@ -5890,7 +5890,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
int low, high, remaining, index; int low, high, remaining, index;
unsigned int rover; unsigned int rover;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(sock_net(sk), &low, &high);
remaining = (high - low) + 1; remaining = (high - low) + 1;
rover = net_random() % remaining + low; rover = net_random() % remaining + low;
......
...@@ -3929,7 +3929,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3929,7 +3929,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (snum) { if (snum) {
int low, high; int low, high;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(sock_net(sk), &low, &high);
if (snum < max(PROT_SOCK, low) || snum > high) { if (snum < max(PROT_SOCK, low) || snum > high) {
err = sel_netport_sid(sk->sk_protocol, err = sel_netport_sid(sk->sk_protocol,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment