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