diff options
author | Vladislav Efanov <VEfanov@ispras.ru> | 2023-05-30 14:39:41 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-06-09 10:23:57 +0200 |
commit | d328ad5e09f5d74af87e2ff4298617a88b51edd1 (patch) | |
tree | 24869f4f37a299370fa2d416b6c1f981f263dcd2 | |
parent | 16072e1e6ec237c9d8decdce0758f7629c175354 (diff) | |
download | linux-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.c | 2 |
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); |