Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sock_map: Fix a potential use-after-free in sock_map_close()

The last refcnt of the psock can be gone right after
sock_map_remove_links(), so sk_psock_stop() could trigger a UAF.
The reason why I placed sk_psock_stop() there is to avoid RCU read
critical section, and more importantly, some callee of
sock_map_remove_links() is supposed to be called with RCU read lock,
we can not simply get rid of RCU read lock here. Therefore, the only
choice we have is to grab an additional refcnt with sk_psock_get()
and put it back after sk_psock_stop().

Fixes: 799aa7f98d53 ("skmsg: Avoid lock_sock() in sk_psock_backlog()")
Reported-by: syzbot+7b6548ae483d6f4c64ae@syzkaller.appspotmail.com
Signed-off-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Jakub Sitnicki <jakub@cloudflare.com>
Link: https://lore.kernel.org/bpf/20210408030556.45134-1-xiyou.wangcong@gmail.com

authored by

Cong Wang and committed by
Daniel Borkmann
aadb2bb8 51e0158a

+2 -1
+2 -1
net/core/sock_map.c
··· 1521 1521 1522 1522 lock_sock(sk); 1523 1523 rcu_read_lock(); 1524 - psock = sk_psock(sk); 1524 + psock = sk_psock_get(sk); 1525 1525 if (unlikely(!psock)) { 1526 1526 rcu_read_unlock(); 1527 1527 release_sock(sk); ··· 1532 1532 sock_map_remove_links(sk, psock); 1533 1533 rcu_read_unlock(); 1534 1534 sk_psock_stop(psock, true); 1535 + sk_psock_put(sk, psock); 1535 1536 release_sock(sk); 1536 1537 saved_close(sk, timeout); 1537 1538 }