diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2013-09-28 17:10:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-01 00:59:38 -0400 |
commit | 0bbf87d852d243680ed7074110ccc1dea003b61a (patch) | |
tree | 016273c3e3e097096a94b10f590437acbb61ece7 | |
parent | 56d7b53f47e7c9a0ab1c6289f2669a8d3a65cf17 (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.c | 2 | ||||
-rw-r--r-- | drivers/net/vxlan.c | 2 | ||||
-rw-r--r-- | include/net/ip.h | 6 | ||||
-rw-r--r-- | include/net/netns/ipv4.h | 6 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 20 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 2 | ||||
-rw-r--r-- | net/ipv4/ping.c | 4 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 52 | ||||
-rw-r--r-- | net/ipv4/udp.c | 2 | ||||
-rw-r--r-- | net/openvswitch/vport-vxlan.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 2 |
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; |
2300 | retry: | 2300 | retry: |
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 | ||
220 | extern struct local_ports { | 220 | void inet_get_local_port_range(struct net *net, int *low, int *high); |
221 | seqlock_t lock; | ||
222 | int range[2]; | ||
223 | } sysctl_local_ports; | ||
224 | void inet_get_local_port_range(int *low, int *high); | ||
225 | 221 | ||
226 | extern unsigned long *sysctl_local_reserved_ports; | 222 | extern unsigned long *sysctl_local_reserved_ports; |
227 | static inline int inet_is_reserved_local_port(int port) | 223 | static 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; | |||
15 | struct hlist_head; | 15 | struct hlist_head; |
16 | struct fib_table; | 16 | struct fib_table; |
17 | struct sock; | 17 | struct sock; |
18 | struct local_ports { | ||
19 | seqlock_t lock; | ||
20 | int range[2]; | ||
21 | }; | ||
18 | 22 | ||
19 | struct netns_ipv4 { | 23 | struct 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"; | |||
29 | EXPORT_SYMBOL(inet_csk_timer_bug_msg); | 29 | EXPORT_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 | */ | ||
35 | struct local_ports sysctl_local_ports __read_mostly = { | ||
36 | .lock = __SEQLOCK_UNLOCKED(sysctl_local_ports.lock), | ||
37 | .range = { 32768, 61000 }, | ||
38 | }; | ||
39 | |||
40 | unsigned long *sysctl_local_reserved_ports; | 32 | unsigned long *sysctl_local_reserved_ports; |
41 | EXPORT_SYMBOL(sysctl_local_reserved_ports); | 33 | EXPORT_SYMBOL(sysctl_local_reserved_ports); |
42 | 34 | ||
43 | void inet_get_local_port_range(int *low, int *high) | 35 | void 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 | } |
54 | EXPORT_SYMBOL(inet_get_local_port_range); | 46 | EXPORT_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 | ||
118 | again: | 110 | again: |
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 }; | |||
43 | static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; | 43 | static 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 */ |
46 | static void set_local_port_range(int range[2]) | 46 | static 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, | |||
83 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) | 86 | static 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 */ |
96 | static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) | 101 | static 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, |