summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladislav Efanov <VEfanov@ispras.ru>2023-05-30 14:39:41 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-06-09 10:23:57 +0200
commitd328ad5e09f5d74af87e2ff4298617a88b51edd1 (patch)
tree24869f4f37a299370fa2d416b6c1f981f263dcd2
parent16072e1e6ec237c9d8decdce0758f7629c175354 (diff)
downloadlinux-stable-d328ad5e09f5d74af87e2ff4298617a88b51edd1.tar.gz
linux-stable-d328ad5e09f5d74af87e2ff4298617a88b51edd1.tar.bz2
linux-stable-d328ad5e09f5d74af87e2ff4298617a88b51edd1.zip
udp6: Fix race condition in udp6_sendmsg & connect
[ Upstream commit 448a5ce1120c5bdbce1f1ccdabcd31c7d029f328 ] Syzkaller got the following report: BUG: KASAN: use-after-free in sk_setup_caps+0x621/0x690 net/core/sock.c:2018 Read of size 8 at addr ffff888027f82780 by task syz-executor276/3255 The function sk_setup_caps (called by ip6_sk_dst_store_flow-> ip6_dst_store) referenced already freed memory as this memory was freed by parallel task in udpv6_sendmsg->ip6_sk_dst_lookup_flow-> sk_dst_check. task1 (connect) task2 (udp6_sendmsg) sk_setup_caps->sk_dst_set | | sk_dst_check-> | sk_dst_set | dst_release sk_setup_caps references | to already freed dst_entry| The reason for this race condition is: sk_setup_caps() keeps using the dst after transferring the ownership to the dst cache. Found by Linux Verification Center (linuxtesting.org) with syzkaller. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Vladislav Efanov <VEfanov@ispras.ru> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--net/core/sock.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index cd23a8e4556c..347a55519d0a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1795,7 +1795,6 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
u32 max_segs = 1;
- sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features | sk->sk_route_forced_caps;
if (sk->sk_route_caps & NETIF_F_GSO)
sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
@@ -1810,6 +1809,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
}
}
sk->sk_gso_max_segs = max_segs;
+ sk_dst_set(sk, dst);
}
EXPORT_SYMBOL_GPL(sk_setup_caps);