aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2013-09-28 17:10:59 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-01 00:59:38 -0400
commit0bbf87d852d243680ed7074110ccc1dea003b61a (patch)
tree016273c3e3e097096a94b10f590437acbb61ece7
parent56d7b53f47e7c9a0ab1c6289f2669a8d3a65cf17 (diff)
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: Samya <samya@twitter.com> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/core/cma.c2
-rw-r--r--drivers/net/vxlan.c2
-rw-r--r--include/net/ip.h6
-rw-r--r--include/net/netns/ipv4.h6
-rw-r--r--net/ipv4/inet_connection_sock.c20
-rw-r--r--net/ipv4/inet_hashtables.c2
-rw-r--r--net/ipv4/ping.c4
-rw-r--r--net/ipv4/sysctl_net_ipv4.c52
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/openvswitch/vport-vxlan.c2
-rw-r--r--net/sctp/socket.c2
-rw-r--r--security/selinux/hooks.c2
12 files changed, 56 insertions, 46 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index dab4b41f1715..a082fd9e7ebe 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2294,7 +2294,7 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
2294 int low, high, remaining; 2294 int low, high, remaining;
2295 unsigned int rover; 2295 unsigned int rover;
2296 2296
2297 inet_get_local_port_range(&low, &high); 2297 inet_get_local_port_range(&init_net, &low, &high);
2298 remaining = (high - low) + 1; 2298 remaining = (high - low) + 1;
2299 rover = net_random() % remaining + low; 2299 rover = net_random() % remaining + low;
2300retry: 2300retry:
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index d1292fe746bc..c376be7b528a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2089,7 +2089,7 @@ static void vxlan_setup(struct net_device *dev)
2089 vxlan->age_timer.function = vxlan_cleanup; 2089 vxlan->age_timer.function = vxlan_cleanup;
2090 vxlan->age_timer.data = (unsigned long) vxlan; 2090 vxlan->age_timer.data = (unsigned long) vxlan;
2091 2091
2092 inet_get_local_port_range(&low, &high); 2092 inet_get_local_port_range(dev_net(dev), &low, &high);
2093 vxlan->port_min = low; 2093 vxlan->port_min = low;
2094 vxlan->port_max = high; 2094 vxlan->port_max = high;
2095 vxlan->dst_port = htons(vxlan_port); 2095 vxlan->dst_port = htons(vxlan_port);
diff --git a/include/net/ip.h b/include/net/ip.h
index 77b4f9b57c28..16078f422397 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -217,11 +217,7 @@ static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
217 } 217 }
218} 218}
219 219
220extern struct local_ports { 220void inet_get_local_port_range(struct net *net, int *low, int *high);
221 seqlock_t lock;
222 int range[2];
223} sysctl_local_ports;
224void inet_get_local_port_range(int *low, int *high);
225 221
226extern unsigned long *sysctl_local_reserved_ports; 222extern unsigned long *sysctl_local_reserved_ports;
227static inline int inet_is_reserved_local_port(int port) 223static inline int inet_is_reserved_local_port(int port)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index bf2ec2202c56..5dbd232e12ff 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -15,6 +15,10 @@ struct fib_rules_ops;
15struct hlist_head; 15struct hlist_head;
16struct fib_table; 16struct fib_table;
17struct sock; 17struct sock;
18struct local_ports {
19 seqlock_t lock;
20 int range[2];
21};
18 22
19struct netns_ipv4 { 23struct netns_ipv4 {
20#ifdef CONFIG_SYSCTL 24#ifdef CONFIG_SYSCTL
@@ -62,6 +66,8 @@ struct netns_ipv4 {
62 int sysctl_icmp_ratemask; 66 int sysctl_icmp_ratemask;
63 int sysctl_icmp_errors_use_inbound_ifaddr; 67 int sysctl_icmp_errors_use_inbound_ifaddr;
64 68
69 struct local_ports sysctl_local_ports;
70
65 int sysctl_tcp_ecn; 71 int sysctl_tcp_ecn;
66 72
67 kgid_t sysctl_ping_group_range[2]; 73 kgid_t sysctl_ping_group_range[2];
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6acb541c9091..7ac7aa11130e 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -29,27 +29,19 @@ const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
29EXPORT_SYMBOL(inet_csk_timer_bug_msg); 29EXPORT_SYMBOL(inet_csk_timer_bug_msg);
30#endif 30#endif
31 31
32/*
33 * This struct holds the first and last local port number.
34 */
35struct local_ports sysctl_local_ports __read_mostly = {
36 .lock = __SEQLOCK_UNLOCKED(sysctl_local_ports.lock),
37 .range = { 32768, 61000 },
38};
39
40unsigned long *sysctl_local_reserved_ports; 32unsigned long *sysctl_local_reserved_ports;
41EXPORT_SYMBOL(sysctl_local_reserved_ports); 33EXPORT_SYMBOL(sysctl_local_reserved_ports);
42 34
43void inet_get_local_port_range(int *low, int *high) 35void inet_get_local_port_range(struct net *net, int *low, int *high)
44{ 36{
45 unsigned int seq; 37 unsigned int seq;
46 38
47 do { 39 do {
48 seq = read_seqbegin(&sysctl_local_ports.lock); 40 seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
49 41
50 *low = sysctl_local_ports.range[0]; 42 *low = net->ipv4.sysctl_local_ports.range[0];
51 *high = sysctl_local_ports.range[1]; 43 *high = net->ipv4.sysctl_local_ports.range[1];
52 } while (read_seqretry(&sysctl_local_ports.lock, seq)); 44 } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
53} 45}
54EXPORT_SYMBOL(inet_get_local_port_range); 46EXPORT_SYMBOL(inet_get_local_port_range);
55 47
@@ -116,7 +108,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
116 int remaining, rover, low, high; 108 int remaining, rover, low, high;
117 109
118again: 110again:
119 inet_get_local_port_range(&low, &high); 111 inet_get_local_port_range(net, &low, &high);
120 remaining = (high - low) + 1; 112 remaining = (high - low) + 1;
121 smallest_rover = rover = net_random() % remaining + low; 113 smallest_rover = rover = net_random() % remaining + low;
122 114
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7bd8983dbfcf..2779037bd113 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -494,7 +494,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
494 u32 offset = hint + port_offset; 494 u32 offset = hint + port_offset;
495 struct inet_timewait_sock *tw = NULL; 495 struct inet_timewait_sock *tw = NULL;
496 496
497 inet_get_local_port_range(&low, &high); 497 inet_get_local_port_range(net, &low, &high);
498 remaining = (high - low) + 1; 498 remaining = (high - low) + 1;
499 499
500 local_bh_disable(); 500 local_bh_disable();
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 706d108e128c..a62610443152 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -237,11 +237,11 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
237 unsigned int seq; 237 unsigned int seq;
238 238
239 do { 239 do {
240 seq = read_seqbegin(&sysctl_local_ports.lock); 240 seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
241 241
242 *low = data[0]; 242 *low = data[0];
243 *high = data[1]; 243 *high = data[1];
244 } while (read_seqretry(&sysctl_local_ports.lock, seq)); 244 } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
245} 245}
246 246
247 247
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 540279f4c531..c08f096d46b5 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 };
43static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; 43static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
44 44
45/* Update system visible IP port range */ 45/* Update system visible IP port range */
46static void set_local_port_range(int range[2]) 46static void set_local_port_range(struct net *net, int range[2])
47{ 47{
48 write_seqlock(&sysctl_local_ports.lock); 48 write_seqlock(&net->ipv4.sysctl_local_ports.lock);
49 sysctl_local_ports.range[0] = range[0]; 49 net->ipv4.sysctl_local_ports.range[0] = range[0];
50 sysctl_local_ports.range[1] = range[1]; 50 net->ipv4.sysctl_local_ports.range[1] = range[1];
51 write_sequnlock(&sysctl_local_ports.lock); 51 write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
52} 52}
53 53
54/* Validate changes from /proc interface. */ 54/* Validate changes from /proc interface. */
@@ -56,6 +56,8 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
56 void __user *buffer, 56 void __user *buffer,
57 size_t *lenp, loff_t *ppos) 57 size_t *lenp, loff_t *ppos)
58{ 58{
59 struct net *net =
60 container_of(table->data, struct net, ipv4.sysctl_local_ports.range);
59 int ret; 61 int ret;
60 int range[2]; 62 int range[2];
61 struct ctl_table tmp = { 63 struct ctl_table tmp = {
@@ -66,14 +68,15 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
66 .extra2 = &ip_local_port_range_max, 68 .extra2 = &ip_local_port_range_max,
67 }; 69 };
68 70
69 inet_get_local_port_range(range, range + 1); 71 inet_get_local_port_range(net, &range[0], &range[1]);
72
70 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); 73 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
71 74
72 if (write && ret == 0) { 75 if (write && ret == 0) {
73 if (range[1] < range[0]) 76 if (range[1] < range[0])
74 ret = -EINVAL; 77 ret = -EINVAL;
75 else 78 else
76 set_local_port_range(range); 79 set_local_port_range(net, range);
77 } 80 }
78 81
79 return ret; 82 return ret;
@@ -83,23 +86,27 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
83static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) 86static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)
84{ 87{
85 kgid_t *data = table->data; 88 kgid_t *data = table->data;
89 struct net *net =
90 container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
86 unsigned int seq; 91 unsigned int seq;
87 do { 92 do {
88 seq = read_seqbegin(&sysctl_local_ports.lock); 93 seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
89 94
90 *low = data[0]; 95 *low = data[0];
91 *high = data[1]; 96 *high = data[1];
92 } while (read_seqretry(&sysctl_local_ports.lock, seq)); 97 } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
93} 98}
94 99
95/* Update system visible IP port range */ 100/* Update system visible IP port range */
96static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) 101static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
97{ 102{
98 kgid_t *data = table->data; 103 kgid_t *data = table->data;
99 write_seqlock(&sysctl_local_ports.lock); 104 struct net *net =
105 container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
106 write_seqlock(&net->ipv4.sysctl_local_ports.lock);
100 data[0] = low; 107 data[0] = low;
101 data[1] = high; 108 data[1] = high;
102 write_sequnlock(&sysctl_local_ports.lock); 109 write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
103} 110}
104 111
105/* Validate changes from /proc interface. */ 112/* Validate changes from /proc interface. */
@@ -475,13 +482,6 @@ static struct ctl_table ipv4_table[] = {
475 .proc_handler = proc_dointvec 482 .proc_handler = proc_dointvec
476 }, 483 },
477 { 484 {
478 .procname = "ip_local_port_range",
479 .data = &sysctl_local_ports.range,
480 .maxlen = sizeof(sysctl_local_ports.range),
481 .mode = 0644,
482 .proc_handler = ipv4_local_port_range,
483 },
484 {
485 .procname = "ip_local_reserved_ports", 485 .procname = "ip_local_reserved_ports",
486 .data = NULL, /* initialized in sysctl_ipv4_init */ 486 .data = NULL, /* initialized in sysctl_ipv4_init */
487 .maxlen = 65536, 487 .maxlen = 65536,
@@ -854,6 +854,13 @@ static struct ctl_table ipv4_net_table[] = {
854 .proc_handler = proc_dointvec 854 .proc_handler = proc_dointvec
855 }, 855 },
856 { 856 {
857 .procname = "ip_local_port_range",
858 .maxlen = sizeof(init_net.ipv4.sysctl_local_ports.range),
859 .data = &init_net.ipv4.sysctl_local_ports.range,
860 .mode = 0644,
861 .proc_handler = ipv4_local_port_range,
862 },
863 {
857 .procname = "tcp_mem", 864 .procname = "tcp_mem",
858 .maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem), 865 .maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem),
859 .mode = 0644, 866 .mode = 0644,
@@ -888,6 +895,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
888 &net->ipv4.sysctl_ping_group_range; 895 &net->ipv4.sysctl_ping_group_range;
889 table[7].data = 896 table[7].data =
890 &net->ipv4.sysctl_tcp_ecn; 897 &net->ipv4.sysctl_tcp_ecn;
898 table[8].data =
899 &net->ipv4.sysctl_local_ports.range;
891 900
892 /* Don't export sysctls to unprivileged users */ 901 /* Don't export sysctls to unprivileged users */
893 if (net->user_ns != &init_user_ns) 902 if (net->user_ns != &init_user_ns)
@@ -901,6 +910,13 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
901 net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); 910 net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1);
902 net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); 911 net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0);
903 912
913 /*
914 * Set defaults for local port range
915 */
916 seqlock_init(&net->ipv4.sysctl_local_ports.lock);
917 net->ipv4.sysctl_local_ports.range[0] = 32768;
918 net->ipv4.sysctl_local_ports.range[1] = 61000;
919
904 tcp_init_mem(net); 920 tcp_init_mem(net);
905 921
906 net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); 922 net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 22462d947750..728ce9503a27 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -219,7 +219,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
219 unsigned short first, last; 219 unsigned short first, last;
220 DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); 220 DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);
221 221
222 inet_get_local_port_range(&low, &high); 222 inet_get_local_port_range(net, &low, &high);
223 remaining = (high - low) + 1; 223 remaining = (high - low) + 1;
224 224
225 rand = net_random(); 225 rand = net_random();
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index a481c03e2861..56e22b74cf96 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -173,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
173 173
174 skb->local_df = 1; 174 skb->local_df = 1;
175 175
176 inet_get_local_port_range(&port_min, &port_max); 176 inet_get_local_port_range(net, &port_min, &port_max);
177 src_port = vxlan_src_port(port_min, port_max, skb); 177 src_port = vxlan_src_port(port_min, port_max, skb);
178 178
179 err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, 179 err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 911b71b26b0e..72046b9729a8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5890,7 +5890,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
5890 int low, high, remaining, index; 5890 int low, high, remaining, index;
5891 unsigned int rover; 5891 unsigned int rover;
5892 5892
5893 inet_get_local_port_range(&low, &high); 5893 inet_get_local_port_range(sock_net(sk), &low, &high);
5894 remaining = (high - low) + 1; 5894 remaining = (high - low) + 1;
5895 rover = net_random() % remaining + low; 5895 rover = net_random() % remaining + low;
5896 5896
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a5091ec06aa6..568c7699abf1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3929,7 +3929,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3929 if (snum) { 3929 if (snum) {
3930 int low, high; 3930 int low, high;
3931 3931
3932 inet_get_local_port_range(&low, &high); 3932 inet_get_local_port_range(sock_net(sk), &low, &high);
3933 3933
3934 if (snum < max(PROT_SOCK, low) || snum > high) { 3934 if (snum < max(PROT_SOCK, low) || snum > high) {
3935 err = sel_netport_sid(sk->sk_protocol, 3935 err = sel_netport_sid(sk->sk_protocol,