CVE-2023-53585

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
04/10/2025
Last modified:
06/10/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> bpf: reject unhashed sockets in bpf_sk_assign<br /> <br /> The semantics for bpf_sk_assign are as follows:<br /> <br /> sk = some_lookup_func()<br /> bpf_sk_assign(skb, sk)<br /> bpf_sk_release(sk)<br /> <br /> That is, the sk is not consumed by bpf_sk_assign. The function<br /> therefore needs to make sure that sk lives long enough to be<br /> consumed from __inet_lookup_skb. The path through the stack for a<br /> TCPv4 packet is roughly:<br /> <br /> netif_receive_skb_core: takes RCU read lock<br /> __netif_receive_skb_core:<br /> sch_handle_ingress:<br /> tcf_classify:<br /> bpf_sk_assign()<br /> deliver_ptype_list_skb:<br /> deliver_skb:<br /> ip_packet_type-&gt;func == ip_rcv:<br /> ip_rcv_core:<br /> ip_rcv_finish_core:<br /> dst_input:<br /> ip_local_deliver:<br /> ip_local_deliver_finish:<br /> ip_protocol_deliver_rcu:<br /> tcp_v4_rcv:<br /> __inet_lookup_skb:<br /> skb_steal_sock<br /> <br /> The existing helper takes advantage of the fact that everything<br /> happens in the same RCU critical section: for sockets with<br /> SOCK_RCU_FREE set bpf_sk_assign never takes a reference.<br /> skb_steal_sock then checks SOCK_RCU_FREE again and does sock_put<br /> if necessary.<br /> <br /> This approach assumes that SOCK_RCU_FREE is never set on a sk<br /> between bpf_sk_assign and skb_steal_sock, but this invariant is<br /> violated by unhashed UDP sockets. A new UDP socket is created<br /> in TCP_CLOSE state but without SOCK_RCU_FREE set. That flag is only<br /> added in udp_lib_get_port() which happens when a socket is bound.<br /> <br /> When bpf_sk_assign was added it wasn&amp;#39;t possible to access unhashed<br /> UDP sockets from BPF, so this wasn&amp;#39;t a problem. This changed<br /> in commit 0c48eefae712 ("sock_map: Lift socket state restriction<br /> for datagram sockets"), but the helper wasn&amp;#39;t adjusted accordingly.<br /> The following sequence of events will therefore lead to a refcount<br /> leak:<br /> <br /> 1. Add socket(AF_INET, SOCK_DGRAM) to a sockmap.<br /> 2. Pull socket out of sockmap and bpf_sk_assign it. Since<br /> SOCK_RCU_FREE is not set we increment the refcount.<br /> 3. bind() or connect() the socket, setting SOCK_RCU_FREE.<br /> 4. skb_steal_sock will now set refcounted = false due to<br /> SOCK_RCU_FREE.<br /> 5. tcp_v4_rcv() skips sock_put().<br /> <br /> Fix the problem by rejecting unhashed sockets in bpf_sk_assign().<br /> This matches the behaviour of __inet_lookup_skb which is ultimately<br /> the goal of bpf_sk_assign().

Impact