* [PATCH net 1/1] atm: svc: fix listen state corruption in svc_listen
[not found] <cover.1781031726.git.zzhan461@ucr.edu>
@ 2026-06-10 17:33 ` Ren Wei
2026-06-12 23:34 ` Jakub Kicinski
0 siblings, 1 reply; 2+ messages in thread
From: Ren Wei @ 2026-06-10 17:33 UTC (permalink / raw)
To: linux-atm-general, netdev
Cc: 3chas3, yuantan098, zcliangcn, bird, tr0jan, zzhan461, n05ec
From: Zhao Zhang <zzhan461@ucr.edu>
svc_listen() can corrupt the vcc_hash hlist by inserting the same socket
twice. The function never validates that listen is only entered from the
unconnected state, and it publishes listener state even when the
signaling daemon reports an error. A connected socket is already hashed,
so calling listen() on it re-adds the same sk_node and causes hlist
corruption. A successful listener can also later flow into svc_connect()
and get inserted again because listener state was not tracked correctly.
Fix the state machine in net/atm/svc.c. Reject listen on connected or
otherwise invalid socket states, only mark the socket as listening after
the signaling reply succeeds, record listener state on sk->sk_state, and
reject connect on sockets already marked as listeners. This removes the
double-insert list-corruption bug at its source.
Fixes: 9301e320e98f ("[ATM]: track and close listen sockets when sigd exits")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Co-developed-by: Luxing Yin <tr0jan@lzu.edu.cn>
Signed-off-by: Luxing Yin <tr0jan@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Zhao Zhang <zzhan461@ucr.edu>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/atm/svc.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/net/atm/svc.c b/net/atm/svc.c
index 005964250ecd..dfc4f3762bf8 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -168,6 +168,10 @@ static int svc_connect(struct socket *sock, struct sockaddr_unsized *sockaddr,
error = -EINVAL;
goto out;
}
+ if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
+ error = -EINVAL;
+ goto out;
+ }
switch (sock->state) {
default:
@@ -302,6 +306,14 @@ static int svc_listen(struct socket *sock, int backlog)
error = -EADDRINUSE;
goto out;
}
+ if (sock->state == SS_CONNECTED) {
+ error = -EISCONN;
+ goto out;
+ }
+ if (sock->state != SS_UNCONNECTED) {
+ error = -EINVAL;
+ goto out;
+ }
set_bit(ATM_VF_WAITING, &vcc->flags);
sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local);
for (;;) {
@@ -315,10 +327,14 @@ static int svc_listen(struct socket *sock, int backlog)
error = -EUNATCH;
goto out;
}
+ error = -sk->sk_err;
+ if (error)
+ goto out;
set_bit(ATM_VF_LISTEN, &vcc->flags);
+ sk->sk_state = TCP_LISTEN;
vcc_insert_socket(sk);
sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
- error = -sk->sk_err;
+ error = 0;
out:
release_sock(sk);
return error;
--
2.47.3
^ permalink raw reply related [flat|nested] 2+ messages in thread