aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>2015-08-19 16:33:59 -0600
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:32:19 +0200
commitb814a93adfaebe63094da43ca155a871ed5bfd5d (patch)
tree80fbe306cb71739bbbe02b991d567f3a1bd48a6e
parentdc47ce72d5c98c73145c362e7defd2445dd526c2 (diff)
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> Signed-off-by: Mekala Natarajan <mekalan@codeaurora.org>
-rw-r--r--Documentation/networking/ip-sysctl.txt5
-rw-r--r--include/net/ip.h1
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/inet_connection_sock.c7
-rw-r--r--net/ipv4/sysctl_net_ipv4.c7
-rw-r--r--net/ipv4/udp.c6
6 files changed, 28 insertions, 0 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 0b7bef45c..b1d0c4c2f 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -698,6 +698,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.
diff --git a/include/net/ip.h b/include/net/ip.h
index a04070b82..c02d09be8 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -211,6 +211,7 @@ static inline int inet_is_reserved_local_port(int port)
return test_bit(port, sysctl_local_reserved_ports);
}
+extern int sysctl_reserved_port_bind;
extern int sysctl_ip_nonlocal_bind;
/* From inetpeer.c */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d915b3575..07fb13440 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -133,6 +133,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.
*/
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index cff1b0fb7..acabb4d63 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -181,6 +181,13 @@ have_snum:
head = &hashinfo->bhash[inet_bhashfn(net, snum,
hashinfo->bhash_size)];
spin_lock(&head->lock);
+
+ if (inet_is_reserved_local_port(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;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index a3426bbab..04e53f049 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -517,6 +517,13 @@ static struct ctl_table ipv4_table[] = {
.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 = "igmp_max_memberships",
.data = &sysctl_igmp_max_memberships,
.maxlen = sizeof(int),
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8d23483f3..0c41e5b28 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -106,6 +106,7 @@
#include <net/route.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include <net/ip.h>
#include <trace/events/udp.h>
#include <linux/static_key.h>
#include <trace/events/skb.h>
@@ -266,6 +267,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_reserved_local_port(snum) &&
+ !sysctl_reserved_port_bind)
+ goto fail_unlock;
+
if (hslot->count > 10) {
int exist;
unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum;