Michal Kubecek dcee4f
From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Michal Kubecek dcee4f
Date: Mon, 23 Jan 2023 14:59:33 -0300
Michal Kubecek dcee4f
Subject: sctp: fail if no bound addresses can be used for a given scope
Frederic Weisbecker 5f575c
Patch-mainline: v6.2-rc6
Michal Kubecek dcee4f
Git-commit: 458e279f861d3f61796894cd158b780765a1569f
Michal Kubecek dcee4f
References: bsc#1206677
Michal Kubecek dcee4f
Michal Kubecek dcee4f
Currently, if you bind the socket to something like:
Michal Kubecek dcee4f
        servaddr.sin6_family = AF_INET6;
Michal Kubecek dcee4f
        servaddr.sin6_port = htons(0);
Michal Kubecek dcee4f
        servaddr.sin6_scope_id = 0;
Michal Kubecek dcee4f
        inet_pton(AF_INET6, "::1", &servaddr.sin6_addr);
Michal Kubecek dcee4f
Michal Kubecek dcee4f
And then request a connect to:
Michal Kubecek dcee4f
        connaddr.sin6_family = AF_INET6;
Michal Kubecek dcee4f
        connaddr.sin6_port = htons(20000);
Michal Kubecek dcee4f
        connaddr.sin6_scope_id = if_nametoindex("lo");
Michal Kubecek dcee4f
        inet_pton(AF_INET6, "fe88::1", &connaddr.sin6_addr);
Michal Kubecek dcee4f
Michal Kubecek dcee4f
What the stack does is:
Michal Kubecek dcee4f
 - bind the socket
Michal Kubecek dcee4f
 - create a new asoc
Michal Kubecek dcee4f
 - to handle the connect
Michal Kubecek dcee4f
   - copy the addresses that can be used for the given scope
Michal Kubecek dcee4f
   - try to connect
Michal Kubecek dcee4f
Michal Kubecek dcee4f
But the copy returns 0 addresses, and the effect is that it ends up
Michal Kubecek dcee4f
trying to connect as if the socket wasn't bound, which is not the
Michal Kubecek dcee4f
desired behavior. This unexpected behavior also allows KASLR leaks
Michal Kubecek dcee4f
through SCTP diag interface.
Michal Kubecek dcee4f
Michal Kubecek dcee4f
The fix here then is, if when trying to copy the addresses that can
Michal Kubecek dcee4f
be used for the scope used in connect() it returns 0 addresses, bail
Michal Kubecek dcee4f
out. This is what TCP does with a similar reproducer.
Michal Kubecek dcee4f
Michal Kubecek dcee4f
Reported-by: Pietro Borrello <borrello@diag.uniroma1.it>
Michal Kubecek dcee4f
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Michal Kubecek dcee4f
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Michal Kubecek dcee4f
Reviewed-by: Xin Long <lucien.xin@gmail.com>
Michal Kubecek dcee4f
Link: https://lore.kernel.org/r/9fcd182f1099f86c6661f3717f63712ddd1c676c.1674496737.git.marcelo.leitner@gmail.com
Michal Kubecek dcee4f
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Michal Kubecek dcee4f
Acked-by: Michal Kubecek <mkubecek@suse.cz>
Michal Kubecek dcee4f
Michal Kubecek dcee4f
---
Michal Kubecek dcee4f
 net/sctp/bind_addr.c | 6 ++++++
Michal Kubecek dcee4f
 1 file changed, 6 insertions(+)
Michal Kubecek dcee4f
Michal Kubecek dcee4f
--- a/net/sctp/bind_addr.c
Michal Kubecek dcee4f
+++ b/net/sctp/bind_addr.c
Michal Kubecek dcee4f
@@ -73,6 +73,12 @@ int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
Michal Kubecek dcee4f
 		}
Michal Kubecek dcee4f
 	}
Michal Kubecek dcee4f
 
Michal Kubecek dcee4f
+	/* If somehow no addresses were found that can be used with this
Michal Kubecek dcee4f
+	 * scope, it's an error.
Michal Kubecek dcee4f
+	 */
Michal Kubecek dcee4f
+	if (list_empty(&dest->address_list))
Michal Kubecek dcee4f
+		error = -ENETUNREACH;
Michal Kubecek dcee4f
+
Michal Kubecek dcee4f
 out:
Michal Kubecek dcee4f
 	if (error)
Michal Kubecek dcee4f
 		sctp_bind_addr_clean(dest);