Re: [PATCH bpf v2 2/2] bpf: Unconditionally take socket references in lookup helpers
[email protected] Mon, 03 Aug 2026 09:35:44 +0000
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] A pre-existing socket reference leak exists when `bpf_sk_assign()` assigns a socket to an skb and `sock_pfree()` acts as the destructor. `bpf_sk_assign()` conditionally increments the reference count if `sk_is_refcounted()` returns true, but `sock_pfree()` independently re-evaluates `sk_is_refcounted()`. If the socket transitions to `SOCK_RCU_FREE` between these two calls (e.g., via `connect(AF_UNSPEC)` followed by `listen()`), `sock_pfree()` returns early without calling `sock_gen_put()`, permanently leaking the reference. -- --- Patch [2]: [PATCH bpf v2 2/2] bpf: Unconditionally take socket references in lookup helpers --- commit 7463d9a6a26a249e959688cc8e1b8c2847ee47d0 Author: Michal Luczaj <[email protected]> bpf: Unconditionally take socket references in lookup helpers This commit updates BPF socket lookup helpers to unconditionally acquire and release socket references. It fixes a leak that occurs if a socket transitions to SOCK_RCU_FREE between the time the reference is conditionally taken and released. Closes: https://lore.kernel.org/bpf/[email protected]/ > TC bpf_sk_assign() has the same issue; it takes a reference only when > sk_is_refcounted() is true at assign time, but sock_pfree() (the skb > destructor it installs) re-checks sk_is_refcounted() independently at > release time. The same connect(AF_UNSPEC)+listen() transition leaks the > socket here too. I'd welcome suggestions on the right way to handle this. [Severity: High] This is a pre-existing issue, but as you noted, a socket reference is permanently leaked if the socket state changes to unrefcounted between bpf_sk_assign() and the skb destructor running. In net/core/filter.c:bpf_sk_assign(), the reference is conditionally acquired and the destructor is set: if (sk_is_refcounted(sk) && unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) return -ENOENT; skb_orphan(skb); skb->sk = sk; skb->destructor = sock_pfree; Then in net/core/sock.c:sock_pfree(), the reference drop is independently evaluated: void sock_pfree(struct sk_buff *skb) { struct sock *sk = skb->sk; if (!sk_is_refcounted(sk)) return; ... sock_gen_put(sk); } If the socket transitions to SOCK_RCU_FREE via a connect(AF_UNSPEC) followed by a listen() before the skb is freed, sock_pfree() returns early without calling sock_gen_put(). Could this be addressed by either applying the same unconditional reference counting approach to bpf_sk_assign(), or by introducing a dedicated destructor for BPF-assigned sockets that unconditionally drops the reference without re-evaluating sk_is_refcounted()? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2