diff mbox series

net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind()

Message ID 20210405070652.2447152-1-zenczykowski@gmail.com (mailing list archive)
State Accepted
Commit 630e4576f83accf90366686f39808d665d8dbecc
Delegated to: Netdev Maintainers
Headers show
Series net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind() | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers fail 1 blamed authors not CCed: vincent@bernat.im; 8 maintainers not CCed: vincent@bernat.im dsahern@kernel.org marcelo.leitner@gmail.com yoshfuji@linux-ipv6.org vyasevich@gmail.com linux-sctp@vger.kernel.org nhorman@tuxdriver.com kuba@kernel.org
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 27 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Maciej Żenczykowski April 5, 2021, 7:06 a.m. UTC
From: Maciej Żenczykowski <maze@google.com>

Found by virtue of ipv6 raw sockets not honouring the per-socket
IP{,V6}_FREEBIND setting.

Based on hits found via:
  git grep '[.]ip_nonlocal_bind'
We fix both raw ipv6 sockets to honour IP{,V6}_FREEBIND and IP{,V6}_TRANSPARENT,
and we fix sctp sockets to honour IP{,V6}_TRANSPARENT (they already honoured
FREEBIND), and not just the ipv6 'ip_nonlocal_bind' sysctl.

The helper is defined as:
  static inline bool ipv6_can_nonlocal_bind(struct net *net, struct inet_sock *inet) {
    return net->ipv6.sysctl.ip_nonlocal_bind || inet->freebind || inet->transparent;
  }
so this change only widens the accepted opt-outs and is thus a clean bugfix.

I'm not entirely sure what 'fixes' tag to add, since this is AFAICT an ancient bug,
but IMHO this should be applied to stable kernels as far back as possible.
As such I'm adding a 'fixes' tag with the commit that originally added the helper,
which happened in 4.19.  Backporting to older LTS kernels (at least 4.9 and 4.14)
would presumably require open-coding it or backporting the helper as well.

Other possibly relevant commits:
  v4.18-rc6-1502-g83ba4645152d net: add helpers checking if socket can be bound to nonlocal address
  v4.18-rc6-1431-gd0c1f01138c4 net/ipv6: allow any source address for sendmsg pktinfo with ip_nonlocal_bind
  v4.14-rc5-271-gb71d21c274ef sctp: full support for ipv6 ip_nonlocal_bind & IP_FREEBIND
  v4.7-rc7-1883-g9b9742022888 sctp: support ipv6 nonlocal bind
  v4.1-12247-g35a256fee52c ipv6: Nonlocal bind

Cc: Lorenzo Colitti <lorenzo@google.com>
Fixes: 83ba4645152d ("net: add helpers checking if socket can be bound to nonlocal address")
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 net/ipv6/raw.c  | 2 +-
 net/sctp/ipv6.c | 7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

Comments

Lorenzo Colitti April 5, 2021, 1:01 p.m. UTC | #1
On Mon, Apr 5, 2021 at 4:07 PM Maciej Żenczykowski
<zenczykowski@gmail.com> wrote:
> The helper is defined as:
>   static inline bool ipv6_can_nonlocal_bind(struct net *net, struct inet_sock *inet) {
>     return net->ipv6.sysctl.ip_nonlocal_bind || inet->freebind || inet->transparent;
>   }
> so this change only widens the accepted opt-outs and is thus a clean bugfix.

Reviewed-By: Lorenzo Colitti <lorenzo@google.com>
patchwork-bot+netdevbpf@kernel.org April 5, 2021, 10:10 p.m. UTC | #2
Hello:

This patch was applied to netdev/net.git (refs/heads/master):

On Mon,  5 Apr 2021 00:06:52 -0700 you wrote:
> From: Maciej Żenczykowski <maze@google.com>
> 
> Found by virtue of ipv6 raw sockets not honouring the per-socket
> IP{,V6}_FREEBIND setting.
> 
> Based on hits found via:
>   git grep '[.]ip_nonlocal_bind'
> We fix both raw ipv6 sockets to honour IP{,V6}_FREEBIND and IP{,V6}_TRANSPARENT,
> and we fix sctp sockets to honour IP{,V6}_TRANSPARENT (they already honoured
> FREEBIND), and not just the ipv6 'ip_nonlocal_bind' sysctl.
> 
> [...]

Here is the summary with links:
  - net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind()
    https://git.kernel.org/netdev/net/c/630e4576f83a

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
diff mbox series

Patch

diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1f56d9aae589..bf3646b57c68 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -298,7 +298,7 @@  static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 		 */
 		v4addr = LOOPBACK4_IPV6;
 		if (!(addr_type & IPV6_ADDR_MULTICAST) &&
-		    !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) {
+		    !ipv6_can_nonlocal_bind(sock_net(sk), inet)) {
 			err = -EADDRNOTAVAIL;
 			if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
 					   dev, 0)) {
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index c3e89c776e66..bd08807c9e44 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -664,8 +664,8 @@  static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
 	if (!(type & IPV6_ADDR_UNICAST))
 		return 0;
 
-	return sp->inet.freebind || net->ipv6.sysctl.ip_nonlocal_bind ||
-		ipv6_chk_addr(net, in6, NULL, 0);
+	return ipv6_can_nonlocal_bind(net, &sp->inet) ||
+	       ipv6_chk_addr(net, in6, NULL, 0);
 }
 
 /* This function checks if the address is a valid address to be used for
@@ -954,8 +954,7 @@  static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
 			net = sock_net(&opt->inet.sk);
 			rcu_read_lock();
 			dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
-			if (!dev || !(opt->inet.freebind ||
-				      net->ipv6.sysctl.ip_nonlocal_bind ||
+			if (!dev || !(ipv6_can_nonlocal_bind(net, &opt->inet) ||
 				      ipv6_chk_addr(net, &addr->v6.sin6_addr,
 						    dev, 0))) {
 				rcu_read_unlock();