[PATCH net 1/1] net/rose: hold listener socket during call request handling
Ren Wei <[email protected]> Fri, 17 Apr 2026 19:01:51 +0800
| Newsgroups | org.kernel.vger.linux-hams,org.kernel.vger.netdev |
|---|---|
| Message-ID | <52776256bf0fc38de92fe3edf39434538b672b69.1776327338.git.tonanli66@gmail.com> |
From: Nan Li <[email protected]> The call request receive path keeps using the listener socket after the lookup lock has been dropped. Keep the listener alive across the remaining validation and child socket setup by taking a reference in the lookup path and releasing it once request handling is finished. This makes listener lifetime handling explicit and avoids races with concurrent socket teardown. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: [email protected] Reported-by: Yifan Wu <[email protected]> Reported-by: Juefei Pu <[email protected]> Reported-by: Xin Liu <[email protected]> Co-developed-by: Yuan Tan <[email protected]> Signed-off-by: Yuan Tan <[email protected]> Signed-off-by: Nan Li <[email protected]> Signed-off-by: Ren Wei <[email protected]> --- net/rose/af_rose.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index d5032840ee48..c96325e54a86 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -277,8 +277,10 @@ static struct sock *rose_find_listener(rose_address *addr, ax25_address *call) if (!rosecmp(&rose->source_addr, addr) && !ax25cmp(&rose->source_call, call) && - !rose->source_ndigis && s->sk_state == TCP_LISTEN) + !rose->source_ndigis && s->sk_state == TCP_LISTEN) { + sock_hold(s); goto found; + } } sk_for_each(s, &rose_list) { @@ -286,8 +288,10 @@ static struct sock *rose_find_listener(rose_address *addr, ax25_address *call) if (!rosecmp(&rose->source_addr, addr) && !ax25cmp(&rose->source_call, &null_ax25_address) && - s->sk_state == TCP_LISTEN) + s->sk_state == TCP_LISTEN) { + sock_hold(s); goto found; + } } s = NULL; found: @@ -1056,10 +1060,13 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros /* * We can't accept the Call Request. */ - if (sk == NULL || sk_acceptq_is_full(sk) || + if (sk == NULL) + goto out_clear_request; + + if (sk_acceptq_is_full(sk) || (make = rose_make_new(sk)) == NULL) { - rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120); - return 0; + sock_put(sk); + goto out_clear_request; } skb->sk = make; @@ -1110,7 +1117,14 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros if (!sock_flag(sk, SOCK_DEAD)) sk->sk_data_ready(sk); + sock_put(sk); + return 1; + +out_clear_request: + rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120); + + return 0; } static int rose_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) -- 2.43.0