Skip to content

Commit 610678d

Browse files
dslee2022gregkh
authored andcommitted
net/x25: fix use-after-free in x25_kill_by_neigh()
commit 5499e06 upstream. x25_kill_by_neigh() walks the global X.25 socket list looking for sockets attached to a terminating neighbour. x25_list_lock protects list membership while the lookup is in progress, but it does not pin a socket's lifetime after the lock is dropped. The function currently drops x25_list_lock before calling lock_sock(s). A concurrent close can run x25_release(), remove the same socket from x25_list, and drop the last socket reference in that window. The neighbour teardown path can then lock or inspect a freed struct sock/struct x25_sock. Take sock_hold(s) while x25_list_lock still proves that the list entry is live, then drop the temporary reference after the socket has been locked, rechecked, and released. Recheck x25_sk(s)->neighbour after lock_sock(), because another path may have disconnected the socket before this path acquired the socket lock. Restart the list walk after each disconnect because the list lock was dropped and the previous iterator state may no longer be valid. A QEMU/KASAN run against origin/master reproduced a slab-use-after-free in x25_kill_by_neigh(). Fixes: 7781607 ("net/x25: Fix null-ptr-deref caused by x25_disconnect") Cc: stable@vger.kernel.org Signed-off-by: David Lee <david.lee@trailofbits.com> Assisted-by: Codex:gpt-5.5 Acked-by: Martin Schiller <ms@dev.tdt.de> Link: https://patch.msgid.link/20260713104752.241175-1-david.lee@trailofbits.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c698b27 commit 610678d

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

net/x25/af_x25.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,15 +1772,19 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
17721772
{
17731773
struct sock *s;
17741774

1775+
again:
17751776
write_lock_bh(&x25_list_lock);
17761777

17771778
sk_for_each(s, &x25_list) {
17781779
if (x25_sk(s)->neighbour == nb) {
1780+
sock_hold(s);
17791781
write_unlock_bh(&x25_list_lock);
17801782
lock_sock(s);
1781-
x25_disconnect(s, ENETUNREACH, 0, 0);
1783+
if (x25_sk(s)->neighbour == nb)
1784+
x25_disconnect(s, ENETUNREACH, 0, 0);
17821785
release_sock(s);
1783-
write_lock_bh(&x25_list_lock);
1786+
sock_put(s);
1787+
goto again;
17841788
}
17851789
}
17861790
write_unlock_bh(&x25_list_lock);

0 commit comments

Comments
 (0)