[PATCH net] appletalk: Hold socket reference in atalk_rcv()
From: Yizhou Zhao
Date: Sun Jun 14 2026 - 05:53:03 EST
atalk_search_socket() walks the global atalk_sockets list while holding
atalk_sockets_lock, but it returns the matching socket after dropping the
lock without taking a reference. atalk_rcv() then passes that pointer to
sock_queue_rcv_skb().
That leaves a race with close(). A concurrent atalk_release() can orphan
the socket, remove it from atalk_sockets, and drop the final reference via
atalk_destroy_socket(), freeing the socket before atalk_rcv() queues the
incoming skb.
On a KASAN-enabled kernel this can be reproduced by racing AppleTalk DDP
delivery on loopback against close/rebind of the destination DGRAM socket:
BUG: KASAN: slab-use-after-free in selinux_socket_sock_rcv_skb()
sk_filter_trim_cap()
sock_queue_rcv_skb_reason()
atalk_rcv()
snap_rcv()
llc_rcv()
Take a reference on the selected socket before dropping
atalk_sockets_lock, and put it after sock_queue_rcv_skb() has finished.
This keeps the socket alive for the receive path without changing socket
lookup semantics. A malformed or racing receive still drops the skb on
queueing failure as before.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Yizhou Zhao <zhaoyz24@xxxxxxxxxxxxxxxxxxxxx>
Reported-by: Yuxiang Yang <yangyx22@xxxxxxxxxxxxxxxxxxxxx>
Reported-by: Ao Wang <wangao@xxxxxxxxxx>
Reported-by: Xuewei Feng <fengxw06@xxxxxxx>
Reported-by: Qi Li <qli01@xxxxxxxxxxxxxxx>
Reported-by: Ke Xu <xuke@xxxxxxxxxxxxxxx>
Assisted-by: GLM:GLM-5.1
Signed-off-by: Yizhou Zhao <zhaoyz24@xxxxxxxxxxxxxxxxxxxxx>
---
net/appletalk/ddp.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 30a6dc06291c..61ec5c569dc3 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -131,6 +131,8 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
}
s = def_socket;
found:
+ if (s)
+ sock_hold(s);
read_unlock_bh(&atalk_sockets_lock);
return s;
}
@@ -1474,9 +1476,12 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
goto drop;
/* Queue packet (standard) */
- if (sock_queue_rcv_skb(sock, skb) < 0)
+ if (sock_queue_rcv_skb(sock, skb) < 0) {
+ sock_put(sock);
goto drop;
+ }
+ sock_put(sock);
return NET_RX_SUCCESS;
drop:
--
2.43.0