CVE-2024-56664 Information
Description
In the Linux kernel the following vulnerability has been resolved:
bpf sockmap: Fix race between element replace and close()
Element replace (with a socket different from the one stored) may race with socket’s close() link popping & unlinking. __sock_map_delete() unconditionally unrefs the (wrong) element:
// set map[0] = s0 map_update_elem(map 0 s0)
// drop fd of s0 close(s0) sock_map_close() lock_sock(sk) (s0!) sock_map_remove_links(sk) link = sk_psock_link_pop() sock_map_unlink(sk link) sock_map_delete_from_link // replace map[0] with s1 map_update_elem(map 0 s1) sock_map_update_elem (s1!) lock_sock(sk) sock_map_update_common psock = sk_psock(sk) spin_lock(&stab->lock) osk = stab->sks[idx] sock_map_add_link(… &stab->sks[idx]) sock_map_unref(osk &stab->sks[idx]) psock = sk_psock(osk) sk_psock_put(sk psock) if (refcount_dec_and_test(&psock)) sk_psock_drop(sk psock) spin_unlock(&stab->lock) unlock_sock(sk) __sock_map_delete spin_lock(&stab->lock) sk = psk // s1 replaced s0; sk == s1 if (!sk_test || sk_test == sk) // sk_test (s0) != sk (s1); no branch sk = xchg(psk NULL) if (sk) sock_map_unref(sk psk) // unref s1; sks[idx] will dangle psock = sk_psock(sk) sk_psock_put(sk psock) if (refcount_dec_and_test()) sk_psock_drop(sk psock) spin_unlock(&stab->lock) release_sock(sk)
Then close(map) enqueues bpf_map_free_deferred which finally calls sock_map_free(). This results in some refcount_t warnings along with a KASAN splat [1].
Fix __sock_map_delete() do not allow sock_map_unref() on elements that may have been replaced.
[1]: BUG: KASAN: slab-use-after-free in sock_map_free+0x10e/0x330 Write of size 4 at addr ffff88811f5b9100 by task kworker/u64:12/1063
CPU: 14 UID: 0 PID: 1063 Comm: kworker/u64:12 Not tainted 6.12.0+ 125
Hardware name: QEMU Standard PC (i440FX + PIIX 1996) BIOS Arch Linux 1.16.3-1-1 04/01/2014
Workqueue: events_unbound bpf_map_free_deferred
Call Trace:
Allocated by task 1202: kasan_save_stack+0x1e/0x40 kasan_save_track+0x10/0x30 __kasan_slab_alloc+0x85/0x90 kmem_cache_alloc_noprof+0x131/0x450 sk_prot_alloc+0x5b/0x220 sk_alloc+0x2c/0x870 unix_create1+0x88/0x8a0 unix_create+0xc5/0x180 __sock_create+0x241/0x650 __sys_socketpair+0x1ce/0x420 __x64_sys_socketpair+0x92/0x100 do_syscall_64+0x93/0x180 entry_SYSCALL_64_after_hwframe+0x76/0x7e
Freed by task 46: kasan_save_stack+0x1e/0x40 kasan_save_track+0x10/0x30 kasan_save_free_info+0x37/0x60 __kasan_slab_free+0x4b/0x70 kmem_cache_free+0x1a1/0x590 __sk_destruct+0x388/0x5a0 sk_psock_destroy+0x73e/0xa50 process_one_work+0x846/0x1420 worker_thread+0x5b3/0xf80 kthread+0x29e/0x360 ret_from_fork+0x2d/0x70 ret_from_fork_asm+0x1a/0x30
The bu
truncated—
Reference
https://git.kernel.org/stable/c/b015f19fedd2e12283a8450dd0aefce49ec57015 https://git.kernel.org/stable/c/bf2318e288f636a882eea39f7e1015623629f168 https://git.kernel.org/stable/c/ed1fc5d76b81a4d681211333c026202cad4d5649
Share on: