From: Marcelo Ricardo Leitner marcelo.leitner@gmail.com
stable inclusion from stable-v4.19.271 commit 26436553aabfd9b40e1daa537a099bf5bb13fb55 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6I7U3 CVE: CVE-2023-1074
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 458e279f861d3f61796894cd158b780765a1569f ]
Currently, if you bind the socket to something like: servaddr.sin6_family = AF_INET6; servaddr.sin6_port = htons(0); servaddr.sin6_scope_id = 0; inet_pton(AF_INET6, "::1", &servaddr.sin6_addr);
And then request a connect to: connaddr.sin6_family = AF_INET6; connaddr.sin6_port = htons(20000); connaddr.sin6_scope_id = if_nametoindex("lo"); inet_pton(AF_INET6, "fe88::1", &connaddr.sin6_addr);
What the stack does is: - bind the socket - create a new asoc - to handle the connect - copy the addresses that can be used for the given scope - try to connect
But the copy returns 0 addresses, and the effect is that it ends up trying to connect as if the socket wasn't bound, which is not the desired behavior. This unexpected behavior also allows KASLR leaks through SCTP diag interface.
The fix here then is, if when trying to copy the addresses that can be used for the scope used in connect() it returns 0 addresses, bail out. This is what TCP does with a similar reproducer.
Reported-by: Pietro Borrello borrello@diag.uniroma1.it Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Reviewed-by: Xin Long lucien.xin@gmail.com Link: https://lore.kernel.org/r/9fcd182f1099f86c6661f3717f63712ddd1c676c.167449673... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Dong Chenchen dongchenchen2@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- net/sctp/bind_addr.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f8a283245672..d723942e5e65 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -88,6 +88,12 @@ int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest, } }
+ /* If somehow no addresses were found that can be used with this + * scope, it's an error. + */ + if (list_empty(&dest->address_list)) + error = -ENETUNREACH; + out: if (error) sctp_bind_addr_clean(dest);