Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: make ip_local_reserved_ports per netns

ip_local_port_range is already per netns, so should ip_local_reserved_ports
be. And since it is none by default we don't actually need it when we don't
enable CONFIG_SYSCTL.

By the way, rename inet_is_reserved_local_port() to inet_is_local_reserved_port()

Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

WANG Cong and committed by
David S. Miller
122ff243 9cc5e36d

+38 -37
+11 -3
include/net/ip.h
··· 208 208 209 209 void inet_get_local_port_range(struct net *net, int *low, int *high); 210 210 211 - extern unsigned long *sysctl_local_reserved_ports; 212 - static inline int inet_is_reserved_local_port(int port) 211 + #if CONFIG_SYSCTL 212 + static inline int inet_is_local_reserved_port(struct net *net, int port) 213 213 { 214 - return test_bit(port, sysctl_local_reserved_ports); 214 + if (!net->ipv4.sysctl_local_reserved_ports) 215 + return 0; 216 + return test_bit(port, net->ipv4.sysctl_local_reserved_ports); 215 217 } 218 + #else 219 + static inline int inet_is_local_reserved_port(struct net *net, int port) 220 + { 221 + return 0; 222 + } 223 + #endif 216 224 217 225 extern int sysctl_ip_nonlocal_bind; 218 226
+4
include/net/netns/ipv4.h
··· 84 84 85 85 atomic_t dev_addr_genid; 86 86 87 + #ifdef CONFIG_SYSCTL 88 + unsigned long *sysctl_local_reserved_ports; 89 + #endif 90 + 87 91 #ifdef CONFIG_IP_MROUTE 88 92 #ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES 89 93 struct mr_table *mrt;
+2 -2
kernel/sysctl.c
··· 2501 2501 bool first = 1; 2502 2502 size_t left = *lenp; 2503 2503 unsigned long bitmap_len = table->maxlen; 2504 - unsigned long *bitmap = (unsigned long *) table->data; 2504 + unsigned long *bitmap = *(unsigned long **) table->data; 2505 2505 unsigned long *tmp_bitmap = NULL; 2506 2506 char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c; 2507 2507 2508 - if (!bitmap_len || !left || (*ppos && !write)) { 2508 + if (!bitmap || !bitmap_len || !left || (*ppos && !write)) { 2509 2509 *lenp = 0; 2510 2510 return 0; 2511 2511 }
+1 -7
net/ipv4/af_inet.c
··· 1705 1705 1706 1706 BUILD_BUG_ON(sizeof(struct inet_skb_parm) > FIELD_SIZEOF(struct sk_buff, cb)); 1707 1707 1708 - sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); 1709 - if (!sysctl_local_reserved_ports) 1710 - goto out; 1711 - 1712 1708 rc = proto_register(&tcp_prot, 1); 1713 1709 if (rc) 1714 - goto out_free_reserved_ports; 1710 + goto out; 1715 1711 1716 1712 rc = proto_register(&udp_prot, 1); 1717 1713 if (rc) ··· 1817 1821 proto_unregister(&udp_prot); 1818 1822 out_unregister_tcp_proto: 1819 1823 proto_unregister(&tcp_prot); 1820 - out_free_reserved_ports: 1821 - kfree(sysctl_local_reserved_ports); 1822 1824 goto out; 1823 1825 } 1824 1826
+1 -4
net/ipv4/inet_connection_sock.c
··· 29 29 EXPORT_SYMBOL(inet_csk_timer_bug_msg); 30 30 #endif 31 31 32 - unsigned long *sysctl_local_reserved_ports; 33 - EXPORT_SYMBOL(sysctl_local_reserved_ports); 34 - 35 32 void inet_get_local_port_range(struct net *net, int *low, int *high) 36 33 { 37 34 unsigned int seq; ··· 110 113 111 114 smallest_size = -1; 112 115 do { 113 - if (inet_is_reserved_local_port(rover)) 116 + if (inet_is_local_reserved_port(net, rover)) 114 117 goto next_nolock; 115 118 head = &hashinfo->bhash[inet_bhashfn(net, rover, 116 119 hashinfo->bhash_size)];
+1 -1
net/ipv4/inet_hashtables.c
··· 500 500 local_bh_disable(); 501 501 for (i = 1; i <= remaining; i++) { 502 502 port = low + (i + offset) % remaining; 503 - if (inet_is_reserved_local_port(port)) 503 + if (inet_is_local_reserved_port(net, port)) 504 504 continue; 505 505 head = &hinfo->bhash[inet_bhashfn(net, port, 506 506 hinfo->bhash_size)];
+14 -17
net/ipv4/sysctl_net_ipv4.c
··· 437 437 .proc_handler = proc_dointvec 438 438 }, 439 439 { 440 - .procname = "ip_local_reserved_ports", 441 - .data = NULL, /* initialized in sysctl_ipv4_init */ 442 - .maxlen = 65536, 443 - .mode = 0644, 444 - .proc_handler = proc_do_large_bitmap, 445 - }, 446 - { 447 440 .procname = "igmp_max_memberships", 448 441 .data = &sysctl_igmp_max_memberships, 449 442 .maxlen = sizeof(int), ··· 818 825 .proc_handler = ipv4_local_port_range, 819 826 }, 820 827 { 828 + .procname = "ip_local_reserved_ports", 829 + .data = &init_net.ipv4.sysctl_local_reserved_ports, 830 + .maxlen = 65536, 831 + .mode = 0644, 832 + .proc_handler = proc_do_large_bitmap, 833 + }, 834 + { 821 835 .procname = "ip_no_pmtu_disc", 822 836 .data = &init_net.ipv4.sysctl_ip_no_pmtu_disc, 823 837 .maxlen = sizeof(int), ··· 876 876 if (net->ipv4.ipv4_hdr == NULL) 877 877 goto err_reg; 878 878 879 + net->ipv4.sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); 880 + if (!net->ipv4.sysctl_local_reserved_ports) 881 + goto err_ports; 882 + 879 883 return 0; 880 884 885 + err_ports: 886 + unregister_net_sysctl_table(net->ipv4.ipv4_hdr); 881 887 err_reg: 882 888 if (!net_eq(net, &init_net)) 883 889 kfree(table); ··· 895 889 { 896 890 struct ctl_table *table; 897 891 892 + kfree(net->ipv4.sysctl_local_reserved_ports); 898 893 table = net->ipv4.ipv4_hdr->ctl_table_arg; 899 894 unregister_net_sysctl_table(net->ipv4.ipv4_hdr); 900 895 kfree(table); ··· 909 902 static __init int sysctl_ipv4_init(void) 910 903 { 911 904 struct ctl_table_header *hdr; 912 - struct ctl_table *i; 913 - 914 - for (i = ipv4_table; i->procname; i++) { 915 - if (strcmp(i->procname, "ip_local_reserved_ports") == 0) { 916 - i->data = sysctl_local_reserved_ports; 917 - break; 918 - } 919 - } 920 - if (!i->procname) 921 - return -EINVAL; 922 905 923 906 hdr = register_net_sysctl(&init_net, "net/ipv4", ipv4_table); 924 907 if (hdr == NULL)
+1 -1
net/ipv4/udp.c
··· 246 246 do { 247 247 if (low <= snum && snum <= high && 248 248 !test_bit(snum >> udptable->log, bitmap) && 249 - !inet_is_reserved_local_port(snum)) 249 + !inet_is_local_reserved_port(net, snum)) 250 250 goto found; 251 251 snum += rand; 252 252 } while (snum != first);
+3 -2
net/sctp/socket.c
··· 5946 5946 /* Search for an available port. */ 5947 5947 int low, high, remaining, index; 5948 5948 unsigned int rover; 5949 + struct net *net = sock_net(sk); 5949 5950 5950 - inet_get_local_port_range(sock_net(sk), &low, &high); 5951 + inet_get_local_port_range(net, &low, &high); 5951 5952 remaining = (high - low) + 1; 5952 5953 rover = prandom_u32() % remaining + low; 5953 5954 ··· 5956 5955 rover++; 5957 5956 if ((rover < low) || (rover > high)) 5958 5957 rover = low; 5959 - if (inet_is_reserved_local_port(rover)) 5958 + if (inet_is_local_reserved_port(net, rover)) 5960 5959 continue; 5961 5960 index = sctp_phashfn(sock_net(sk), rover); 5962 5961 head = &sctp_port_hashtable[index];