mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 00:48:50 +00:00
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>
This commit is contained in:
parent
9cc5e36d1c
commit
122ff243f5
9 changed files with 38 additions and 37 deletions
|
@ -208,11 +208,19 @@ static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_o
|
||||||
|
|
||||||
void inet_get_local_port_range(struct net *net, int *low, int *high);
|
void inet_get_local_port_range(struct net *net, int *low, int *high);
|
||||||
|
|
||||||
extern unsigned long *sysctl_local_reserved_ports;
|
#if CONFIG_SYSCTL
|
||||||
static inline int inet_is_reserved_local_port(int port)
|
static inline int inet_is_local_reserved_port(struct net *net, int port)
|
||||||
{
|
{
|
||||||
return test_bit(port, sysctl_local_reserved_ports);
|
if (!net->ipv4.sysctl_local_reserved_ports)
|
||||||
|
return 0;
|
||||||
|
return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline int inet_is_local_reserved_port(struct net *net, int port)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int sysctl_ip_nonlocal_bind;
|
extern int sysctl_ip_nonlocal_bind;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,10 @@ struct netns_ipv4 {
|
||||||
|
|
||||||
atomic_t dev_addr_genid;
|
atomic_t dev_addr_genid;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSCTL
|
||||||
|
unsigned long *sysctl_local_reserved_ports;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IP_MROUTE
|
#ifdef CONFIG_IP_MROUTE
|
||||||
#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
||||||
struct mr_table *mrt;
|
struct mr_table *mrt;
|
||||||
|
|
|
@ -2501,11 +2501,11 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
|
||||||
bool first = 1;
|
bool first = 1;
|
||||||
size_t left = *lenp;
|
size_t left = *lenp;
|
||||||
unsigned long bitmap_len = table->maxlen;
|
unsigned long bitmap_len = table->maxlen;
|
||||||
unsigned long *bitmap = (unsigned long *) table->data;
|
unsigned long *bitmap = *(unsigned long **) table->data;
|
||||||
unsigned long *tmp_bitmap = NULL;
|
unsigned long *tmp_bitmap = NULL;
|
||||||
char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
|
char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
|
||||||
|
|
||||||
if (!bitmap_len || !left || (*ppos && !write)) {
|
if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
|
||||||
*lenp = 0;
|
*lenp = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1705,13 +1705,9 @@ static int __init inet_init(void)
|
||||||
|
|
||||||
BUILD_BUG_ON(sizeof(struct inet_skb_parm) > FIELD_SIZEOF(struct sk_buff, cb));
|
BUILD_BUG_ON(sizeof(struct inet_skb_parm) > FIELD_SIZEOF(struct sk_buff, cb));
|
||||||
|
|
||||||
sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
|
|
||||||
if (!sysctl_local_reserved_ports)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
rc = proto_register(&tcp_prot, 1);
|
rc = proto_register(&tcp_prot, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free_reserved_ports;
|
goto out;
|
||||||
|
|
||||||
rc = proto_register(&udp_prot, 1);
|
rc = proto_register(&udp_prot, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -1821,8 +1817,6 @@ static int __init inet_init(void)
|
||||||
proto_unregister(&udp_prot);
|
proto_unregister(&udp_prot);
|
||||||
out_unregister_tcp_proto:
|
out_unregister_tcp_proto:
|
||||||
proto_unregister(&tcp_prot);
|
proto_unregister(&tcp_prot);
|
||||||
out_free_reserved_ports:
|
|
||||||
kfree(sysctl_local_reserved_ports);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,6 @@ 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
|
||||||
|
|
||||||
unsigned long *sysctl_local_reserved_ports;
|
|
||||||
EXPORT_SYMBOL(sysctl_local_reserved_ports);
|
|
||||||
|
|
||||||
void inet_get_local_port_range(struct net *net, int *low, int *high)
|
void inet_get_local_port_range(struct net *net, int *low, int *high)
|
||||||
{
|
{
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
|
@ -113,7 +110,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||||
|
|
||||||
smallest_size = -1;
|
smallest_size = -1;
|
||||||
do {
|
do {
|
||||||
if (inet_is_reserved_local_port(rover))
|
if (inet_is_local_reserved_port(net, rover))
|
||||||
goto next_nolock;
|
goto next_nolock;
|
||||||
head = &hashinfo->bhash[inet_bhashfn(net, rover,
|
head = &hashinfo->bhash[inet_bhashfn(net, rover,
|
||||||
hashinfo->bhash_size)];
|
hashinfo->bhash_size)];
|
||||||
|
|
|
@ -500,7 +500,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
for (i = 1; i <= remaining; i++) {
|
for (i = 1; i <= remaining; i++) {
|
||||||
port = low + (i + offset) % remaining;
|
port = low + (i + offset) % remaining;
|
||||||
if (inet_is_reserved_local_port(port))
|
if (inet_is_local_reserved_port(net, port))
|
||||||
continue;
|
continue;
|
||||||
head = &hinfo->bhash[inet_bhashfn(net, port,
|
head = &hinfo->bhash[inet_bhashfn(net, port,
|
||||||
hinfo->bhash_size)];
|
hinfo->bhash_size)];
|
||||||
|
|
|
@ -436,13 +436,6 @@ static struct ctl_table ipv4_table[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec
|
.proc_handler = proc_dointvec
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.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",
|
.procname = "igmp_max_memberships",
|
||||||
.data = &sysctl_igmp_max_memberships,
|
.data = &sysctl_igmp_max_memberships,
|
||||||
|
@ -824,6 +817,13 @@ static struct ctl_table ipv4_net_table[] = {
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = ipv4_local_port_range,
|
.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",
|
.procname = "ip_no_pmtu_disc",
|
||||||
.data = &init_net.ipv4.sysctl_ip_no_pmtu_disc,
|
.data = &init_net.ipv4.sysctl_ip_no_pmtu_disc,
|
||||||
|
@ -876,8 +876,14 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
|
||||||
if (net->ipv4.ipv4_hdr == NULL)
|
if (net->ipv4.ipv4_hdr == NULL)
|
||||||
goto err_reg;
|
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;
|
return 0;
|
||||||
|
|
||||||
|
err_ports:
|
||||||
|
unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
|
||||||
err_reg:
|
err_reg:
|
||||||
if (!net_eq(net, &init_net))
|
if (!net_eq(net, &init_net))
|
||||||
kfree(table);
|
kfree(table);
|
||||||
|
@ -889,6 +895,7 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct ctl_table *table;
|
struct ctl_table *table;
|
||||||
|
|
||||||
|
kfree(net->ipv4.sysctl_local_reserved_ports);
|
||||||
table = net->ipv4.ipv4_hdr->ctl_table_arg;
|
table = net->ipv4.ipv4_hdr->ctl_table_arg;
|
||||||
unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
|
unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
|
||||||
kfree(table);
|
kfree(table);
|
||||||
|
@ -902,16 +909,6 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
|
||||||
static __init int sysctl_ipv4_init(void)
|
static __init int sysctl_ipv4_init(void)
|
||||||
{
|
{
|
||||||
struct ctl_table_header *hdr;
|
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);
|
hdr = register_net_sysctl(&init_net, "net/ipv4", ipv4_table);
|
||||||
if (hdr == NULL)
|
if (hdr == NULL)
|
||||||
|
|
|
@ -246,7 +246,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
|
||||||
do {
|
do {
|
||||||
if (low <= snum && snum <= high &&
|
if (low <= snum && snum <= high &&
|
||||||
!test_bit(snum >> udptable->log, bitmap) &&
|
!test_bit(snum >> udptable->log, bitmap) &&
|
||||||
!inet_is_reserved_local_port(snum))
|
!inet_is_local_reserved_port(net, snum))
|
||||||
goto found;
|
goto found;
|
||||||
snum += rand;
|
snum += rand;
|
||||||
} while (snum != first);
|
} while (snum != first);
|
||||||
|
|
|
@ -5946,8 +5946,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
||||||
/* Search for an available port. */
|
/* Search for an available port. */
|
||||||
int low, high, remaining, index;
|
int low, high, remaining, index;
|
||||||
unsigned int rover;
|
unsigned int rover;
|
||||||
|
struct net *net = sock_net(sk);
|
||||||
|
|
||||||
inet_get_local_port_range(sock_net(sk), &low, &high);
|
inet_get_local_port_range(net, &low, &high);
|
||||||
remaining = (high - low) + 1;
|
remaining = (high - low) + 1;
|
||||||
rover = prandom_u32() % remaining + low;
|
rover = prandom_u32() % remaining + low;
|
||||||
|
|
||||||
|
@ -5955,7 +5956,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
||||||
rover++;
|
rover++;
|
||||||
if ((rover < low) || (rover > high))
|
if ((rover < low) || (rover > high))
|
||||||
rover = low;
|
rover = low;
|
||||||
if (inet_is_reserved_local_port(rover))
|
if (inet_is_local_reserved_port(net, rover))
|
||||||
continue;
|
continue;
|
||||||
index = sctp_phashfn(sock_net(sk), rover);
|
index = sctp_phashfn(sock_net(sk), rover);
|
||||||
head = &sctp_port_hashtable[index];
|
head = &sctp_port_hashtable[index];
|
||||||
|
|
Loading…
Reference in a new issue