All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int
@ 2019-11-22  7:21 Maciej Żenczykowski
  2019-11-22  7:21 ` [PATCH 2/3] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-22  7:21 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller; +Cc: netdev, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index a2c61c36dc4a..cebf3e10def1 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -339,10 +339,10 @@ 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);
 
 #ifdef CONFIG_SYSCTL
-static inline int inet_is_local_reserved_port(struct net *net, int port)
+static inline bool inet_is_local_reserved_port(struct net *net, int port)
 {
 	if (!net->ipv4.sysctl_local_reserved_ports)
-		return 0;
+		return false;
 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
 }
 
@@ -357,9 +357,9 @@ static inline int inet_prot_sock(struct net *net)
 }
 
 #else
-static inline int inet_is_local_reserved_port(struct net *net, int port)
+static inline bool inet_is_local_reserved_port(struct net *net, int port)
 {
-	return 0;
+	return false;
 }
 
 static inline int inet_prot_sock(struct net *net)
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-22  7:21 [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int Maciej Żenczykowski
@ 2019-11-22  7:21 ` Maciej Żenczykowski
  2019-11-22  7:21 ` [PATCH 3/3] net: Fail explicit unprivileged bind to local reserved ports Maciej Żenczykowski
  2019-11-22 18:06 ` [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int David Miller
  2 siblings, 0 replies; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-22  7:21 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller; +Cc: netdev, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

Note that the sysctl write accessor functions guarantee that:
  net->ipv4.sysctl_ip_prot_sock <= net->ipv4.ip_local_ports.range[0]
invariant is maintained, and as such the max() in selinux hooks is actually spurious.

ie. even though
  if (snum < max(inet_prot_sock(sock_net(sk)), low) || snum > high) {
per logic is the same as
  if ((snum < inet_prot_sock(sock_net(sk)) && snum < low) || snum > high) {
it is actually functionally equivalent to:
  if (snum < low || snum > high) {
which is equivalent to:
  if (snum < inet_prot_sock(sock_net(sk)) || snum < low || snum > high) {
even though the first clause is spurious.

But we want to hold on to it for the following patch.

Test: builds, git 'grep inet_prot_sock' finds no other references
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h               | 8 ++++----
 net/ipv4/af_inet.c             | 2 +-
 net/ipv6/af_inet6.c            | 2 +-
 net/netfilter/ipvs/ip_vs_ctl.c | 2 +-
 net/sctp/socket.c              | 4 ++--
 security/selinux/hooks.c       | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index cebf3e10def1..a92f157bb115 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -351,9 +351,9 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
 	return strcmp(name, "default") != 0  && strcmp(name, "all") != 0;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, int port)
 {
-	return net->ipv4.sysctl_ip_prot_sock;
+	return port < net->ipv4.sysctl_ip_prot_sock;
 }
 
 #else
@@ -362,9 +362,9 @@ static inline bool inet_is_local_reserved_port(struct net *net, int port)
 	return false;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, int port)
 {
-	return PROT_SOCK;
+	return port < PROT_SOCK;
 }
 #endif
 
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 53de8e00990e..2fe295432c24 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -495,7 +495,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
 	snum = ntohs(addr->sin_port);
 	err = -EACCES;
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		goto out;
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ef37e0574f54..60e2ff91a5b3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -292,7 +292,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 		return -EINVAL;
 
 	snum = ntohs(addr->sin6_port);
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 3be7398901e0..8d14a1acbc37 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -423,7 +423,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
 
 	if (!svc && protocol == IPPROTO_TCP &&
 	    atomic_read(&ipvs->ftpsvc_counter) &&
-	    (vport == FTPDATA || ntohs(vport) >= inet_prot_sock(ipvs->net))) {
+	    (vport == FTPDATA || !inet_port_requires_bind_service(ipvs->net, ntohs(vport)))) {
 		/*
 		 * Check if ftp service entry exists, the packet
 		 * might belong to FTP data connections.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83e4ca1fabda..8797a38baf00 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -384,7 +384,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 		}
 	}
 
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
@@ -1061,7 +1061,7 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
 		if (sctp_autobind(sk))
 			return -EAGAIN;
 	} else {
-		if (ep->base.bind_addr.port < inet_prot_sock(net) &&
+		if (inet_port_requires_bind_service(net, ep->base.bind_addr.port) &&
 		    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 			return -EACCES;
 	}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9625b99e677f..753b327f4806 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4623,8 +4623,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 
 			inet_get_local_port_range(sock_net(sk), &low, &high);
 
-			if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
-			    snum > high) {
+			if (inet_port_requires_bind_service(sock_net(sk), snum) ||
+			    snum < low || snum > high) {
 				err = sel_netport_sid(sk->sk_protocol,
 						      snum, &sid);
 				if (err)
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] net: Fail explicit unprivileged bind to local reserved ports
  2019-11-22  7:21 [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int Maciej Żenczykowski
  2019-11-22  7:21 ` [PATCH 2/3] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
@ 2019-11-22  7:21 ` Maciej Żenczykowski
  2019-11-22 18:06 ` [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int David Miller
  2 siblings, 0 replies; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-22  7:21 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller
  Cc: netdev, Sean Tranchetti, Subash Abhinov Kasiviswanathan, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

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 sysctl will not be returned only in case of automatic
port assignment.

It is desirable to prevent the host from assigning the ports even in case
of explicit binds to processes without CAP_NET_BIND_SERVICE (which
hopefully know what they're doing).

Example use cases might be:
 - a port being stolen by the nic for remote serial console,
   or some other sort of debugging functionality (crash collection, gdb,
   direct access to some other microcontroller on the nic or motherboard).
 - a transparent proxy where packets are being redirected: in case a socket
   matches this connection, packets from this application would be incorrectly
   sent to one of the endpoints.

Cc: Sean Tranchetti <stranche@codeaurora.org>
Cc: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index a92f157bb115..f00e00d15155 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -353,7 +353,8 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
 
 static inline bool inet_port_requires_bind_service(struct net *net, int port)
 {
-	return port < net->ipv4.sysctl_ip_prot_sock;
+	return port < net->ipv4.sysctl_ip_prot_sock ||
+		inet_is_local_reserved_port(net, port);
 }
 
 #else
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int
  2019-11-22  7:21 [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int Maciej Żenczykowski
  2019-11-22  7:21 ` [PATCH 2/3] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
  2019-11-22  7:21 ` [PATCH 3/3] net: Fail explicit unprivileged bind to local reserved ports Maciej Żenczykowski
@ 2019-11-22 18:06 ` David Miller
  2019-11-22 21:48   ` Maciej Żenczykowski
  2 siblings, 1 reply; 14+ messages in thread
From: David Miller @ 2019-11-22 18:06 UTC (permalink / raw)
  To: zenczykowski; +Cc: maze, netdev, edumazet


Maciej, please repost this series with a proper introduction "[PATCH 0/3]" posting
so that I know what this series does at a high level, how it is doing it, and why
it is doing it that way.

That also gives me a single email to reply to when I apply your series instead of
having to respond to each and every one, which is more work, and error prone for
me.

Thanks.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int
  2019-11-22 18:06 ` [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int David Miller
@ 2019-11-22 21:48   ` Maciej Żenczykowski
  2019-11-22 21:50     ` [PATCH] " Maciej Żenczykowski
  2019-11-24  9:24     ` [PATCH 1/3] " Maciej Żenczykowski
  0 siblings, 2 replies; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-22 21:48 UTC (permalink / raw)
  To: David Miller; +Cc: Linux NetDev, Eric Dumazet

> Maciej, please repost this series with a proper introduction "[PATCH 0/3]" posting
> so that I know what this series does at a high level, how it is doing it, and why
> it is doing it that way.

That's because the first two patches were standalone refactors,
and only the third - one line - patch had a dependency on the 2nd.

> That also gives me a single email to reply to when I apply your series instead of
> having to respond to each and every one, which is more work, and error prone for
> me.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] net: inet_is_local_reserved_port() should return bool not int
  2019-11-22 21:48   ` Maciej Żenczykowski
@ 2019-11-22 21:50     ` Maciej Żenczykowski
  2019-11-23  0:55       ` Jakub Kicinski
  2019-11-24  9:24     ` [PATCH 1/3] " Maciej Żenczykowski
  1 sibling, 1 reply; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-22 21:50 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller; +Cc: netdev, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index a2c61c36dc4a..cebf3e10def1 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -339,10 +339,10 @@ 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);
 
 #ifdef CONFIG_SYSCTL
-static inline int inet_is_local_reserved_port(struct net *net, int port)
+static inline bool inet_is_local_reserved_port(struct net *net, int port)
 {
 	if (!net->ipv4.sysctl_local_reserved_ports)
-		return 0;
+		return false;
 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
 }
 
@@ -357,9 +357,9 @@ static inline int inet_prot_sock(struct net *net)
 }
 
 #else
-static inline int inet_is_local_reserved_port(struct net *net, int port)
+static inline bool inet_is_local_reserved_port(struct net *net, int port)
 {
-	return 0;
+	return false;
 }
 
 static inline int inet_prot_sock(struct net *net)
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] net: inet_is_local_reserved_port() should return bool not int
  2019-11-22 21:50     ` [PATCH] " Maciej Żenczykowski
@ 2019-11-23  0:55       ` Jakub Kicinski
  2019-11-23  3:31         ` Maciej Żenczykowski
  0 siblings, 1 reply; 14+ messages in thread
From: Jakub Kicinski @ 2019-11-23  0:55 UTC (permalink / raw)
  To: Maciej Żenczykowski
  Cc: Maciej Żenczykowski, David S . Miller, netdev, Eric Dumazet

On Fri, 22 Nov 2019 13:50:52 -0800, Maciej Żenczykowski wrote:
> From: Maciej Żenczykowski <maze@google.com>
> 
> Cc: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Maciej Żenczykowski <maze@google.com>

Applied.

It would had been nice to see net-next in the subject and a commit
message, you know :/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] net: inet_is_local_reserved_port() should return bool not int
  2019-11-23  0:55       ` Jakub Kicinski
@ 2019-11-23  3:31         ` Maciej Żenczykowski
  0 siblings, 0 replies; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-23  3:31 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: David S . Miller, Linux NetDev, Eric Dumazet

> On Fri, 22 Nov 2019 13:50:52 -0800, Maciej Żenczykowski wrote:
> > From: Maciej Żenczykowski <maze@google.com>
> >
> > Cc: Eric Dumazet <edumazet@google.com>
> > Signed-off-by: Maciej Żenczykowski <maze@google.com>
>
> Applied.
>
> It would had been nice to see net-next in the subject and a commit
> message, you know :/

Sorry, about that.  I'm never entirely certain what's going to
net-next, what isn't.
Should I just default to net-next?

As for the commit message, there simply didn't appear to be anything to write,
the commit title was pretty self explanatory I thought.

- Maciej

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int
  2019-11-22 21:48   ` Maciej Żenczykowski
  2019-11-22 21:50     ` [PATCH] " Maciej Żenczykowski
@ 2019-11-24  9:24     ` Maciej Żenczykowski
  2019-11-24  9:27       ` [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
  1 sibling, 1 reply; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-24  9:24 UTC (permalink / raw)
  To: David Miller; +Cc: Linux NetDev, Eric Dumazet

> > Maciej, please repost this series with a proper introduction "[PATCH 0/3]" posting
> > so that I know what this series does at a high level, how it is doing it, and why
> > it is doing it that way.
>
> That's because the first two patches were standalone refactors,
> and only the third - one line - patch had a dependency on the 2nd.

So I've been thinking about this, and I've come to the conclusion
you'd probably not be willing to accept the final one line patch (and
either way it should also be updating the sysctl docs) because it is
after all a change of behaviour for userspace (even if I imagine very
rarely utilized).

I'm still not sure what exactly to do about it.  Perhaps the easiest
thing is to carry it around as an Android common kernel only patch.
I'm not sure.
I'm kind of loathe to add another sysctl... but perhaps?

So for now I'll go with resubmitting just the refactor, which I *hope*
won't be controversial??

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-24  9:24     ` [PATCH 1/3] " Maciej Żenczykowski
@ 2019-11-24  9:27       ` Maciej Żenczykowski
  2019-11-25 22:45         ` David Miller
  0 siblings, 1 reply; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-24  9:27 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller; +Cc: netdev, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

Note that the sysctl write accessor functions guarantee that:
  net->ipv4.sysctl_ip_prot_sock <= net->ipv4.ip_local_ports.range[0]
invariant is maintained, and as such the max() in selinux hooks is actually spurious.

ie. even though
  if (snum < max(inet_prot_sock(sock_net(sk)), low) || snum > high) {
per logic is the same as
  if ((snum < inet_prot_sock(sock_net(sk)) && snum < low) || snum > high) {
it is actually functionally equivalent to:
  if (snum < low || snum > high) {
which is equivalent to:
  if (snum < inet_prot_sock(sock_net(sk)) || snum < low || snum > high) {
even though the first clause is spurious.

But we want to hold on to it in case we ever want to change what what
inet_port_requires_bind_service() means (for example by changing
it from a, by default, [0..1024) range to some sort of set).

Test: builds, git 'grep inet_prot_sock' finds no other references
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h               | 8 ++++----
 net/ipv4/af_inet.c             | 2 +-
 net/ipv6/af_inet6.c            | 2 +-
 net/netfilter/ipvs/ip_vs_ctl.c | 2 +-
 net/sctp/socket.c              | 4 ++--
 security/selinux/hooks.c       | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index cebf3e10def1..a92f157bb115 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -351,9 +351,9 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
 	return strcmp(name, "default") != 0  && strcmp(name, "all") != 0;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, int port)
 {
-	return net->ipv4.sysctl_ip_prot_sock;
+	return port < net->ipv4.sysctl_ip_prot_sock;
 }
 
 #else
@@ -362,9 +362,9 @@ static inline bool inet_is_local_reserved_port(struct net *net, int port)
 	return false;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, int port)
 {
-	return PROT_SOCK;
+	return port < PROT_SOCK;
 }
 #endif
 
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 53de8e00990e..2fe295432c24 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -495,7 +495,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
 	snum = ntohs(addr->sin_port);
 	err = -EACCES;
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		goto out;
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ef37e0574f54..60e2ff91a5b3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -292,7 +292,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 		return -EINVAL;
 
 	snum = ntohs(addr->sin6_port);
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 3be7398901e0..8d14a1acbc37 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -423,7 +423,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
 
 	if (!svc && protocol == IPPROTO_TCP &&
 	    atomic_read(&ipvs->ftpsvc_counter) &&
-	    (vport == FTPDATA || ntohs(vport) >= inet_prot_sock(ipvs->net))) {
+	    (vport == FTPDATA || !inet_port_requires_bind_service(ipvs->net, ntohs(vport)))) {
 		/*
 		 * Check if ftp service entry exists, the packet
 		 * might belong to FTP data connections.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83e4ca1fabda..8797a38baf00 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -384,7 +384,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 		}
 	}
 
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
@@ -1061,7 +1061,7 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
 		if (sctp_autobind(sk))
 			return -EAGAIN;
 	} else {
-		if (ep->base.bind_addr.port < inet_prot_sock(net) &&
+		if (inet_port_requires_bind_service(net, ep->base.bind_addr.port) &&
 		    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 			return -EACCES;
 	}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9625b99e677f..753b327f4806 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4623,8 +4623,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 
 			inet_get_local_port_range(sock_net(sk), &low, &high);
 
-			if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
-			    snum > high) {
+			if (inet_port_requires_bind_service(sock_net(sk), snum) ||
+			    snum < low || snum > high) {
 				err = sel_netport_sid(sk->sk_protocol,
 						      snum, &sid);
 				if (err)
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-24  9:27       ` [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
@ 2019-11-25 22:45         ` David Miller
  2019-11-25 23:32           ` Maciej Żenczykowski
  0 siblings, 1 reply; 14+ messages in thread
From: David Miller @ 2019-11-25 22:45 UTC (permalink / raw)
  To: zenczykowski; +Cc: maze, netdev, edumazet

From: Maciej Żenczykowski <zenczykowski@gmail.com>
Date: Sun, 24 Nov 2019 01:27:15 -0800

> -static inline int inet_prot_sock(struct net *net)
> +static inline bool inet_port_requires_bind_service(struct net *net, int port)


"int port"

> -static inline int inet_prot_sock(struct net *net)
> +static inline bool inet_port_requires_bind_service(struct net *net, int port)

"int port"

> @@ -495,7 +495,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
>  
>  	snum = ntohs(addr->sin_port);
>  	err = -EACCES;
> -	if (snum && snum < inet_prot_sock(net) &&
> +	if (snum && inet_port_requires_bind_service(net, snum) &&

"unsigned short snum"

> @@ -292,7 +292,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
>  		return -EINVAL;
>  
>  	snum = ntohs(addr->sin6_port);
> -	if (snum && snum < inet_prot_sock(net) &&
> +	if (snum && inet_port_requires_bind_service(net, snum) &&

"unsigned short snum"

> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 3be7398901e0..8d14a1acbc37 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -423,7 +423,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
>  
>  	if (!svc && protocol == IPPROTO_TCP &&
>  	    atomic_read(&ipvs->ftpsvc_counter) &&
> -	    (vport == FTPDATA || ntohs(vport) >= inet_prot_sock(ipvs->net))) {
> +	    (vport == FTPDATA || !inet_port_requires_bind_service(ipvs->net, ntohs(vport)))) {

ntohs(__be16 vport)

> @@ -384,7 +384,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
>  		}
>  	}
>  
> -	if (snum && snum < inet_prot_sock(net) &&
> +	if (snum && inet_port_requires_bind_service(net, snum) &&

"unsigned short snum"

And so on and so forth.

Please make the types in the helper(s) match actual usage, thank you.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-25 22:45         ` David Miller
@ 2019-11-25 23:32           ` Maciej Żenczykowski
  2019-11-25 23:37             ` [PATCH v2] " Maciej Żenczykowski
  0 siblings, 1 reply; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-25 23:32 UTC (permalink / raw)
  To: David Miller; +Cc: Linux NetDev, Eric Dumazet

I see ample assignments of htons() which is __u16 to unsigned short snum,
so I think the right answer is just to use unsigned short for the port
parameter.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-25 23:32           ` Maciej Żenczykowski
@ 2019-11-25 23:37             ` Maciej Żenczykowski
  2019-11-26 21:20               ` David Miller
  0 siblings, 1 reply; 14+ messages in thread
From: Maciej Żenczykowski @ 2019-11-25 23:37 UTC (permalink / raw)
  To: Maciej Żenczykowski, David S . Miller; +Cc: netdev, Eric Dumazet

From: Maciej Żenczykowski <maze@google.com>

Note that the sysctl write accessor functions guarantee that:
  net->ipv4.sysctl_ip_prot_sock <= net->ipv4.ip_local_ports.range[0]
invariant is maintained, and as such the max() in selinux hooks is actually spurious.

ie. even though
  if (snum < max(inet_prot_sock(sock_net(sk)), low) || snum > high) {
per logic is the same as
  if ((snum < inet_prot_sock(sock_net(sk)) && snum < low) || snum > high) {
it is actually functionally equivalent to:
  if (snum < low || snum > high) {
which is equivalent to:
  if (snum < inet_prot_sock(sock_net(sk)) || snum < low || snum > high) {
even though the first clause is spurious.

But we want to hold on to it in case we ever want to change what what
inet_port_requires_bind_service() means (for example by changing
it from a, by default, [0..1024) range to some sort of set).

Test: builds, git 'grep inet_prot_sock' finds no other references
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip.h               | 8 ++++----
 net/ipv4/af_inet.c             | 2 +-
 net/ipv6/af_inet6.c            | 2 +-
 net/netfilter/ipvs/ip_vs_ctl.c | 2 +-
 net/sctp/socket.c              | 4 ++--
 security/selinux/hooks.c       | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index cebf3e10def1..5a61bd948b18 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -351,9 +351,9 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
 	return strcmp(name, "default") != 0  && strcmp(name, "all") != 0;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
 {
-	return net->ipv4.sysctl_ip_prot_sock;
+	return port < net->ipv4.sysctl_ip_prot_sock;
 }
 
 #else
@@ -362,9 +362,9 @@ static inline bool inet_is_local_reserved_port(struct net *net, int port)
 	return false;
 }
 
-static inline int inet_prot_sock(struct net *net)
+static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port)
 {
-	return PROT_SOCK;
+	return port < PROT_SOCK;
 }
 #endif
 
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 53de8e00990e..2fe295432c24 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -495,7 +495,7 @@ int __inet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
 	snum = ntohs(addr->sin_port);
 	err = -EACCES;
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		goto out;
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ef37e0574f54..60e2ff91a5b3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -292,7 +292,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 		return -EINVAL;
 
 	snum = ntohs(addr->sin6_port);
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 3be7398901e0..8d14a1acbc37 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -423,7 +423,7 @@ ip_vs_service_find(struct netns_ipvs *ipvs, int af, __u32 fwmark, __u16 protocol
 
 	if (!svc && protocol == IPPROTO_TCP &&
 	    atomic_read(&ipvs->ftpsvc_counter) &&
-	    (vport == FTPDATA || ntohs(vport) >= inet_prot_sock(ipvs->net))) {
+	    (vport == FTPDATA || !inet_port_requires_bind_service(ipvs->net, ntohs(vport)))) {
 		/*
 		 * Check if ftp service entry exists, the packet
 		 * might belong to FTP data connections.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83e4ca1fabda..8797a38baf00 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -384,7 +384,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 		}
 	}
 
-	if (snum && snum < inet_prot_sock(net) &&
+	if (snum && inet_port_requires_bind_service(net, snum) &&
 	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 		return -EACCES;
 
@@ -1061,7 +1061,7 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
 		if (sctp_autobind(sk))
 			return -EAGAIN;
 	} else {
-		if (ep->base.bind_addr.port < inet_prot_sock(net) &&
+		if (inet_port_requires_bind_service(net, ep->base.bind_addr.port) &&
 		    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
 			return -EACCES;
 	}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9625b99e677f..753b327f4806 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4623,8 +4623,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 
 			inet_get_local_port_range(sock_net(sk), &low, &high);
 
-			if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
-			    snum > high) {
+			if (inet_port_requires_bind_service(sock_net(sk), snum) ||
+			    snum < low || snum > high) {
 				err = sel_netport_sid(sk->sk_protocol,
 						      snum, &sid);
 				if (err)
-- 
2.24.0.432.g9d3f5f5b63-goog


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port)
  2019-11-25 23:37             ` [PATCH v2] " Maciej Żenczykowski
@ 2019-11-26 21:20               ` David Miller
  0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2019-11-26 21:20 UTC (permalink / raw)
  To: zenczykowski; +Cc: maze, netdev, edumazet

From: Maciej Żenczykowski <zenczykowski@gmail.com>
Date: Mon, 25 Nov 2019 15:37:04 -0800

> From: Maciej Żenczykowski <maze@google.com>
> 
> Note that the sysctl write accessor functions guarantee that:
>   net->ipv4.sysctl_ip_prot_sock <= net->ipv4.ip_local_ports.range[0]
> invariant is maintained, and as such the max() in selinux hooks is actually spurious.
> 
> ie. even though
>   if (snum < max(inet_prot_sock(sock_net(sk)), low) || snum > high) {
> per logic is the same as
>   if ((snum < inet_prot_sock(sock_net(sk)) && snum < low) || snum > high) {
> it is actually functionally equivalent to:
>   if (snum < low || snum > high) {
> which is equivalent to:
>   if (snum < inet_prot_sock(sock_net(sk)) || snum < low || snum > high) {
> even though the first clause is spurious.
> 
> But we want to hold on to it in case we ever want to change what what
> inet_port_requires_bind_service() means (for example by changing
> it from a, by default, [0..1024) range to some sort of set).
> 
> Test: builds, git 'grep inet_prot_sock' finds no other references
> Cc: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Maciej Żenczykowski <maze@google.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2019-11-26 21:20 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-22  7:21 [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int Maciej Żenczykowski
2019-11-22  7:21 ` [PATCH 2/3] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
2019-11-22  7:21 ` [PATCH 3/3] net: Fail explicit unprivileged bind to local reserved ports Maciej Żenczykowski
2019-11-22 18:06 ` [PATCH 1/3] net: inet_is_local_reserved_port() should return bool not int David Miller
2019-11-22 21:48   ` Maciej Żenczykowski
2019-11-22 21:50     ` [PATCH] " Maciej Żenczykowski
2019-11-23  0:55       ` Jakub Kicinski
2019-11-23  3:31         ` Maciej Żenczykowski
2019-11-24  9:24     ` [PATCH 1/3] " Maciej Żenczykowski
2019-11-24  9:27       ` [PATCH] net: port < inet_prot_sock(net) --> inet_port_requires_bind_service(net, port) Maciej Żenczykowski
2019-11-25 22:45         ` David Miller
2019-11-25 23:32           ` Maciej Żenczykowski
2019-11-25 23:37             ` [PATCH v2] " Maciej Żenczykowski
2019-11-26 21:20               ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.