Commit 2886ed97 authored by Vladislav Efanov's avatar Vladislav Efanov Committed by Yongqiang Liu
Browse files

udp6: Fix race condition in udp6_sendmsg & connect

stable inclusion
from stable-v4.19.285
commit d328ad5e09f5d74af87e2ff4298617a88b51edd1
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7J5UF


CVE: NA

--------------------------------

[ Upstream commit 448a5ce1 ]

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: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarVladislav Efanov <VEfanov@ispras.ru>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent bd03da80
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1817,7 +1817,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;
@@ -1832,6 +1831,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);