linux/net/core
Jiayuan Chen 15c0250dae bpf, sockmap: Avoid using sk_socket after free when sending
[ Upstream commit 8259eb0e06 ]

The sk->sk_socket is not locked or referenced in backlog thread, and
during the call to skb_send_sock(), there is a race condition with
the release of sk_socket. All types of sockets(tcp/udp/unix/vsock)
will be affected.

Race conditions:
'''
CPU0                               CPU1

backlog::skb_send_sock
  sendmsg_unlocked
    sock_sendmsg
      sock_sendmsg_nosec
                                   close(fd):
                                     ...
                                     ops->release() -> sock_map_close()
                                     sk_socket->ops = NULL
                                     free(socket)
      sock->ops->sendmsg
            ^
            panic here
'''

The ref of psock become 0 after sock_map_close() executed.
'''
void sock_map_close()
{
    ...
    if (likely(psock)) {
    ...
    // !! here we remove psock and the ref of psock become 0
    sock_map_remove_links(sk, psock)
    psock = sk_psock_get(sk);
    if (unlikely(!psock))
        goto no_psock; <=== Control jumps here via goto
        ...
        cancel_delayed_work_sync(&psock->work); <=== not executed
        sk_psock_put(sk, psock);
        ...
}
'''

Based on the fact that we already wait for the workqueue to finish in
sock_map_close() if psock is held, we simply increase the psock
reference count to avoid race conditions.

With this patch, if the backlog thread is running, sock_map_close() will
wait for the backlog thread to complete and cancel all pending work.

If no backlog running, any pending work that hasn't started by then will
fail when invoked by sk_psock_get(), as the psock reference count have
been zeroed, and sk_psock_drop() will cancel all jobs via
cancel_delayed_work_sync().

In summary, we require synchronization to coordinate the backlog thread
and close() thread.

The panic I catched:
'''
Workqueue: events sk_psock_backlog
RIP: 0010:sock_sendmsg+0x21d/0x440
RAX: 0000000000000000 RBX: ffffc9000521fad8 RCX: 0000000000000001
...
Call Trace:
 <TASK>
 ? die_addr+0x40/0xa0
 ? exc_general_protection+0x14c/0x230
 ? asm_exc_general_protection+0x26/0x30
 ? sock_sendmsg+0x21d/0x440
 ? sock_sendmsg+0x3e0/0x440
 ? __pfx_sock_sendmsg+0x10/0x10
 __skb_send_sock+0x543/0xb70
 sk_psock_backlog+0x247/0xb80
...
'''

Fixes: 4b4647add7 ("sock_map: avoid race between sock_map_close and sk_psock_put")
Reported-by: Michal Luczaj <mhal@rbox.co>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/r/20250516141713.291150-1-jiayuan.chen@linux.dev
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2025-06-19 15:31:53 +02:00
..
bpf_sk_storage.c netlink: introduce type-checking attribute iteration 2024-03-29 15:06:02 -07:00
datagram.c net: add support for skbs with unreadable frags 2024-09-11 20:44:31 -07:00
dev.c net: flush_backlog() small changes 2025-05-29 11:03:01 +02:00
dev.h net: page_pool: avoid false positive warning if NAPI was never added 2025-05-29 11:02:59 +02:00
dev_addr_lists.c net: Correct spelling in net/core 2024-08-26 09:37:23 -07:00
dev_addr_lists_test.c net: dev_addr_lists: move locking out of init/exit in kunit 2024-04-15 10:26:35 +01:00
dev_ioctl.c netdevice: convert private flags > BIT(31) to bitfields 2024-09-03 11:36:43 +02:00
devmem.c net: devmem: do not WARN conditionally after netdev_rx_queue_restart() 2025-04-10 14:39:31 +02:00
devmem.h tcp: RX path for devmem TCP 2024-09-11 20:44:32 -07:00
drop_monitor.c drop_monitor: fix incorrect initialization order 2025-02-27 04:30:21 -08:00
dst.c net: decrease cached dst counters in dst_release 2025-04-10 14:39:34 +02:00
dst_cache.c net: dst_cache: add two DEBUG_NET warnings 2024-06-03 18:50:09 -07:00
failover.c net: failover: use IFF_NO_ADDRCONF flag to prevent ipv6 addrconf 2022-12-12 15:18:25 -08:00
fib_notifier.c net: fib_notifier: propagate extack down to the notifier block callback 2019-10-04 11:10:56 -07:00
fib_rules.c net: fib_rules: annotate data-races around rule->[io]ifindex 2025-02-21 14:01:16 +01:00
filter.c bpf: Scrub packet on bpf_redirect_peer 2025-05-18 08:24:48 +02:00
flow_dissector.c flow_dissector: Fix port range key handling in BPF conversion 2025-02-27 04:30:18 -08:00
flow_offload.c tc: flower: Enable offload support IPSEC SPI field. 2023-08-02 10:09:32 +01:00
gen_estimator.c net: use unrcu_pointer() helper 2024-06-06 11:52:52 +02:00
gen_stats.c net: Remove the obsolte u64_stats_fetch_*_irq() users (net). 2022-10-28 20:13:54 -07:00
gro.c net: Clear old fragment checksum value in napi_reuse_skb 2025-03-07 18:25:33 +01:00
gro_cells.c net: move netdev_max_backlog to net_hotdata 2024-03-07 21:12:42 -08:00
gso.c net: introduce struct net_hotdata 2024-03-07 21:12:41 -08:00
hotdata.c net: move sysctl_mem_pcpu_rsv to net_hotdata 2024-04-30 18:46:52 -07:00
hwbm.c net: hwbm: Make the hwbm_pool lock a mutex 2019-06-09 19:40:10 -07:00
ieee8021q_helpers.c net: add IEEE 802.1q specific helpers 2024-05-08 10:35:09 +01:00
link_watch.c ipvlan: Fix use-after-free in ipvlan_get_iflink(). 2025-01-17 13:40:39 +01:00
lwt_bpf.c bpf: lwtunnel: Unmask upper DSCP bits in bpf_lwt_xmit_reroute() 2024-09-09 14:14:52 +01:00
lwtunnel.c net: lwtunnel: disable BHs when required 2025-05-02 07:59:01 +02:00
Makefile netdev: support binding dma-buf to netdevice 2024-09-11 20:44:31 -07:00
mp_dmabuf_devmem.h memory-provider: dmabuf devmem memory provider 2024-09-11 20:44:31 -07:00
neighbour.c net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES 2025-03-28 22:03:28 +01:00
net-procfs.c net: make softnet_data.dropped an atomic_t 2024-04-01 11:28:32 +01:00
net-sysfs.c net: sysfs: Fix weird usage of class's namespace relevant fields 2024-09-09 10:30:52 +01:00
net-sysfs.h net-sysfs: add netdev_change_owner() 2020-02-26 20:07:25 -08:00
net-traces.c move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
net_namespace.c net: defer final 'struct net' free in netns dismantle 2024-12-19 18:13:13 +01:00
net_test.c pfcp: always set pfcp metadata 2024-04-01 10:49:28 +01:00
netclassid_cgroup.c cgroup, netclassid: on modifying netclassid in cgroup, only consider the main process. 2023-10-16 16:36:53 -07:00
netdev-genl-gen.c netdev: avoid CFI problems with sock priv helpers 2025-01-23 17:22:52 +01:00
netdev-genl-gen.h netdev: support binding dma-buf to netdevice 2024-09-11 20:44:31 -07:00
netdev-genl.c net: export a helper for adding up queue stats 2025-05-18 08:24:50 +02:00
netdev_rx_queue.c memory-provider: dmabuf devmem memory provider 2024-09-11 20:44:31 -07:00
netevent.c net: core: Correct function name netevent_unregister_notifier() in the kerneldoc 2021-03-28 17:56:56 -07:00
netmem_priv.h page_pool: Track DMA-mapped pages and unmap them when destroying the pool 2025-06-19 15:31:42 +02:00
netpoll.c netpoll: hold rcu read lock in __netpoll_send_skb() 2025-03-22 12:54:11 -07:00
netprio_cgroup.c bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode 2021-09-13 16:35:58 -07:00
of_net.c net: Explicitly include correct DT includes 2023-07-27 20:33:16 -07:00
page_pool.c page_pool: Track DMA-mapped pages and unmap them when destroying the pool 2025-06-19 15:31:42 +02:00
page_pool_priv.h memory-provider: dmabuf devmem memory provider 2024-09-11 20:44:31 -07:00
page_pool_user.c net: page_pool: don't cast mp param to devmem 2025-04-20 10:15:17 +02:00
pktgen.c net: pktgen: fix access outside of user given buffer in pktgen_thread_write() 2025-05-29 11:02:43 +02:00
ptp_classifier.c ptp: Add generic PTP is_sync() function 2022-03-07 11:31:34 +00:00
request_sock.c tcp: make sure init the accept_queue's spinlocks once 2024-01-19 21:13:25 -08:00
rtnetlink.c rtnetlink: Allocate vfinfo size for VF GUIDs when supported 2025-04-10 14:39:26 +02:00
scm.c tcp: devmem: don't write truncated dmabuf CMSGs to userspace 2025-03-07 18:25:32 +01:00
secure_seq.c tcp: Fix data-races around sysctl knobs related to SYN option. 2022-07-20 10:14:49 +01:00
selftests.c net: selftests: initialize TCP header and skb payload with zero 2025-05-02 07:59:06 +02:00
skbuff.c page_pool: Move pp_magic check into helper functions 2025-06-19 15:31:42 +02:00
skmsg.c bpf, sockmap: Avoid using sk_socket after free when sending 2025-06-19 15:31:53 +02:00
sock.c net: Fix null-ptr-deref by sock_lock_init_class_and_name() and rmmod. 2025-04-20 10:15:48 +02:00
sock_destructor.h skb_expand_head() adjust skb->truesize incorrectly 2021-10-22 12:35:51 -07:00
sock_diag.c net: use unrcu_pointer() helper 2024-06-06 11:52:52 +02:00
sock_map.c bpf: Disable non stream socket for strparser 2025-02-27 04:30:19 -08:00
sock_reuseport.c net: core: annotate socks of struct sock_reuseport with __counted_by 2024-08-02 17:16:59 -07:00
stream.c net: Return error from sk_stream_wait_connect() if sk_wait_event() fails 2023-12-15 10:48:51 +00:00
sysctl_net_core.c net: set the minimum for net_hotdata.netdev_budget_usecs 2025-03-07 18:25:29 +01:00
timestamping.c net: Change the API of PHY default timestamp to MAC 2024-07-15 08:02:26 -07:00
tso.c move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
utils.c net: Correct spelling in net/core 2024-08-26 09:37:23 -07:00
xdp.c page_pool: Move pp_magic check into helper functions 2025-06-19 15:31:42 +02:00