net: Fail explicit bind to local reserved ports

Reserved ports may have some special use cases which are not suitable
for use by general userspace applications. Currently, ports specified
in ip_local_reserved_ports will not be returned only in case of
automatic port assignment.

Add a boolean sysctl flag 'reserved_port_bind'. Default value is 1
which preserves the existing behavior. Setting the value to 0 will
prevent userspace applications from binding to these ports even when
they are explicitly requested.

BUG=20663075
Change-Id: Ib1071ca5bd437cd3c4f71b56147e4858f3b9ebec
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
Subash Abhinov Kasiviswanathan 2015-09-08 16:06:41 -06:00 committed by David Keitel
parent 63bb8bb2cc
commit d04abc1ab2
6 changed files with 28 additions and 0 deletions

View file

@ -829,6 +829,11 @@ ip_local_reserved_ports - list of comma separated ranges
Default: Empty
reserved_port_bind - BOOLEAN
If set, allows explicit bind requests to applications requesting
any port within the range of ip_local_reserved_ports.
Default: 1
ip_nonlocal_bind - BOOLEAN
If set, allows processes to bind() to non-local IP addresses,
which can be quite useful - but may break some applications.

View file

@ -241,6 +241,8 @@ static inline int inet_is_local_reserved_port(struct net *net, int port)
}
#endif
extern int sysctl_reserved_port_bind;
/* From inetpeer.c */
extern int inet_peer_threshold;
extern int inet_peer_minttl;

View file

@ -135,6 +135,8 @@ static inline int current_has_network(void)
}
#endif
int sysctl_reserved_port_bind __read_mostly = 1;
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
*/

View file

@ -179,6 +179,13 @@ have_snum:
head = &hashinfo->bhash[inet_bhashfn(net, snum,
hashinfo->bhash_size)];
spin_lock(&head->lock);
if (inet_is_local_reserved_port(net, snum) &&
!sysctl_reserved_port_bind) {
ret = 1;
goto fail_unlock;
}
inet_bind_bucket_for_each(tb, &head->chain)
if (net_eq(ib_net(tb), net) && tb->port == snum)
goto tb_found;

View file

@ -902,6 +902,13 @@ static struct ctl_table ipv4_net_table[] = {
.mode = 0644,
.proc_handler = proc_do_large_bitmap,
},
{
.procname = "reserved_port_bind",
.data = &sysctl_reserved_port_bind,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec
},
{
.procname = "ip_no_pmtu_disc",
.data = &init_net.ipv4.sysctl_ip_no_pmtu_disc,

View file

@ -257,6 +257,11 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
} else {
hslot = udp_hashslot(udptable, net, snum);
spin_lock_bh(&hslot->lock);
if (inet_is_local_reserved_port(net, snum) &&
!sysctl_reserved_port_bind)
goto fail_unlock;
if (hslot->count > 10) {
int exist;
unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum;