Jiri Slaby 0bd3d4
From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Jiri Slaby 0bd3d4
Date: Wed, 24 Jun 2020 17:34:18 -0300
Jiri Slaby 0bd3d4
Subject: sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket
Jiri Slaby 0bd3d4
Git-commit: 471e39df96b9a4c4ba88a2da9e25a126624d7a9c
Jiri Slaby 0bd3d4
Patch-mainline: 5.8-rc3
Jiri Slaby 0bd3d4
References: networking-stable-20_06_28
Jiri Slaby 0bd3d4
Jiri Slaby 0bd3d4
If a socket is set ipv6only, it will still send IPv4 addresses in the
Jiri Slaby 0bd3d4
INIT and INIT_ACK packets. This potentially misleads the peer into using
Jiri Slaby 0bd3d4
them, which then would cause association termination.
Jiri Slaby 0bd3d4
Jiri Slaby 0bd3d4
The fix is to not add IPv4 addresses to ipv6only sockets.
Jiri Slaby 0bd3d4
Jiri Slaby 0bd3d4
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Jiri Slaby 0bd3d4
Reported-by: Corey Minyard <cminyard@mvista.com>
Jiri Slaby 0bd3d4
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Jiri Slaby 0bd3d4
Tested-by: Corey Minyard <cminyard@mvista.com>
Jiri Slaby 0bd3d4
Signed-off-by: David S. Miller <davem@davemloft.net>
Jiri Slaby 0bd3d4
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 0bd3d4
---
Jiri Slaby 0bd3d4
 include/net/sctp/constants.h |    8 +++++---
Jiri Slaby 0bd3d4
 net/sctp/associola.c         |    5 ++++-
Jiri Slaby 0bd3d4
 net/sctp/bind_addr.c         |    1 +
Jiri Slaby 0bd3d4
 net/sctp/protocol.c          |    3 ++-
Jiri Slaby 0bd3d4
 4 files changed, 12 insertions(+), 5 deletions(-)
Jiri Slaby 0bd3d4
Jiri Slaby 0bd3d4
--- a/include/net/sctp/constants.h
Jiri Slaby 0bd3d4
+++ b/include/net/sctp/constants.h
Jiri Slaby 0bd3d4
@@ -362,11 +362,13 @@ typedef enum {
Jiri Slaby 0bd3d4
 	 ipv4_is_anycast_6to4(a))
Jiri Slaby 0bd3d4
 
Jiri Slaby 0bd3d4
 /* Flags used for the bind address copy functions.  */
Jiri Slaby 0bd3d4
-#define SCTP_ADDR6_ALLOWED	0x00000001	/* IPv6 address is allowed by
Jiri Slaby 0bd3d4
+#define SCTP_ADDR4_ALLOWED	0x00000001	/* IPv4 address is allowed by
Jiri Slaby 0bd3d4
 						   local sock family */
Jiri Slaby 0bd3d4
-#define SCTP_ADDR4_PEERSUPP	0x00000002	/* IPv4 address is supported by
Jiri Slaby 0bd3d4
+#define SCTP_ADDR6_ALLOWED	0x00000002	/* IPv6 address is allowed by
Jiri Slaby 0bd3d4
+						   local sock family */
Jiri Slaby 0bd3d4
+#define SCTP_ADDR4_PEERSUPP	0x00000004	/* IPv4 address is supported by
Jiri Slaby 0bd3d4
 						   peer */
Jiri Slaby 0bd3d4
-#define SCTP_ADDR6_PEERSUPP	0x00000004	/* IPv6 address is supported by
Jiri Slaby 0bd3d4
+#define SCTP_ADDR6_PEERSUPP	0x00000008	/* IPv6 address is supported by
Jiri Slaby 0bd3d4
 						   peer */
Jiri Slaby 0bd3d4
 
Jiri Slaby 0bd3d4
 /* Reasons to retransmit. */
Jiri Slaby 0bd3d4
--- a/net/sctp/associola.c
Jiri Slaby 0bd3d4
+++ b/net/sctp/associola.c
Jiri Slaby 0bd3d4
@@ -1596,12 +1596,15 @@ void sctp_assoc_rwnd_decrease(struct sct
Jiri Slaby 0bd3d4
 int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
Jiri Slaby 0bd3d4
 				     sctp_scope_t scope, gfp_t gfp)
Jiri Slaby 0bd3d4
 {
Jiri Slaby 0bd3d4
+	struct sock *sk = asoc->base.sk;
Jiri Slaby 0bd3d4
 	int flags;
Jiri Slaby 0bd3d4
 
Jiri Slaby 0bd3d4
 	/* Use scoping rules to determine the subset of addresses from
Jiri Slaby 0bd3d4
 	 * the endpoint.
Jiri Slaby 0bd3d4
 	 */
Jiri Slaby 0bd3d4
-	flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
Jiri Slaby 0bd3d4
+	flags = (PF_INET6 == sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
Jiri Slaby 0bd3d4
+	if (!inet_v6_ipv6only(sk))
Jiri Slaby 0bd3d4
+		flags |= SCTP_ADDR4_ALLOWED;
Jiri Slaby 0bd3d4
 	if (asoc->peer.ipv4_address)
Jiri Slaby 0bd3d4
 		flags |= SCTP_ADDR4_PEERSUPP;
Jiri Slaby 0bd3d4
 	if (asoc->peer.ipv6_address)
Jiri Slaby 0bd3d4
--- a/net/sctp/bind_addr.c
Jiri Slaby 0bd3d4
+++ b/net/sctp/bind_addr.c
Jiri Slaby 0bd3d4
@@ -454,6 +454,7 @@ static int sctp_copy_one_addr(struct net
Jiri Slaby 0bd3d4
 		 * well as the remote peer.
Jiri Slaby 0bd3d4
 		 */
Jiri Slaby 0bd3d4
 		if ((((AF_INET == addr->sa.sa_family) &&
Jiri Slaby 0bd3d4
+		      (flags & SCTP_ADDR4_ALLOWED) &&
Jiri Slaby 0bd3d4
 		      (flags & SCTP_ADDR4_PEERSUPP))) ||
Jiri Slaby 0bd3d4
 		    (((AF_INET6 == addr->sa.sa_family) &&
Jiri Slaby 0bd3d4
 		      (flags & SCTP_ADDR6_ALLOWED) &&
Jiri Slaby 0bd3d4
--- a/net/sctp/protocol.c
Jiri Slaby 0bd3d4
+++ b/net/sctp/protocol.c
Jiri Slaby 0bd3d4
@@ -214,7 +214,8 @@ int sctp_copy_local_addr_list(struct net
Jiri Slaby 0bd3d4
 		 * sock as well as the remote peer.
Jiri Slaby 0bd3d4
 		 */
Jiri Slaby 0bd3d4
 		if (addr->a.sa.sa_family == AF_INET &&
Jiri Slaby 0bd3d4
-		    !(copy_flags & SCTP_ADDR4_PEERSUPP))
Jiri Slaby 0bd3d4
+		    (!(copy_flags & SCTP_ADDR4_ALLOWED) ||
Jiri Slaby 0bd3d4
+		     !(copy_flags & SCTP_ADDR4_PEERSUPP)))
Jiri Slaby 0bd3d4
 			continue;
Jiri Slaby 0bd3d4
 		if (addr->a.sa.sa_family == AF_INET6 &&
Jiri Slaby 0bd3d4
 		    (!(copy_flags & SCTP_ADDR6_ALLOWED) ||