* [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service
@ 2026-06-08 7:46 Ren Wei
2026-06-08 7:46 ` [PATCH net v2 2/2] llc: conn: publish OUT_OF_SVC before draining timers Ren Wei
2026-06-10 1:58 ` [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Jakub Kicinski
0 siblings, 2 replies; 3+ messages in thread
From: Ren Wei @ 2026-06-08 7:46 UTC (permalink / raw)
To: netdev; +Cc: yuantan098, yifanwucs, tomapufckgml, bird, zcliangcn, n05ec
From: Zhengchuan Liang <zcliangcn@gmail.com>
llc_conn_service() only rejects states above NBR_CONN_STATES before
the state machine lookup. That misses LLC_CONN_OUT_OF_SVC, whose value
is 0.
The LLC state machine can set a socket to LLC_CONN_OUT_OF_SVC, and
llc_conn_disc() does not actually detach or free that socket yet. A
later packet can therefore reach llc_qualify_conn_ev() with state 0,
which indexes llc_conn_state_table[state - 1] and turns the lookup
into an out-of-bounds access.
Take one READ_ONCE() snapshot in llc_conn_service(), reject
LLC_CONN_OUT_OF_SVC there, and pass the validated state down to
llc_qualify_conn_ev(). This also keeps the lookup on one consistent
state value.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
changes in v2:
- Use a single READ_ONCE() snapshot of llc->state in llc_conn_service().
- Pass the validated state into llc_qualify_conn_ev() to avoid mixed state reads.
- v1 link: https://lore.kernel.org/all/5f646c530f4a0820060499054c46b8dbecebd7be.1778638129.git.zlian064@ucr.edu/
net/llc/llc_conn.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 5c0ac243b248..9602183d09d8 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -37,7 +37,8 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
const struct llc_conn_state_trans *trans,
struct sk_buff *ev);
static const struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
- struct sk_buff *skb);
+ struct sk_buff *skb,
+ u8 state);
/* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
@@ -358,12 +359,15 @@ static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_trans *trans;
struct llc_sock *llc = llc_sk(sk);
+ u8 state = READ_ONCE(llc->state);
int rc = 1;
- if (llc->state > NBR_CONN_STATES)
+ if (state == LLC_CONN_OUT_OF_SVC)
+ return 0;
+ if (state > NBR_CONN_STATES)
goto out;
rc = 0;
- trans = llc_qualify_conn_ev(sk, skb);
+ trans = llc_qualify_conn_ev(sk, skb, state);
if (trans) {
rc = llc_exec_conn_trans_actions(sk, trans, skb);
if (!rc && trans->next_state != NO_STATE_CHANGE) {
@@ -385,20 +389,20 @@ static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
* Returns pointer to found transition on success, %NULL otherwise.
*/
static const struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ u8 state)
{
const struct llc_conn_state_trans **next_trans;
const llc_conn_ev_qfyr_t *next_qualifier;
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
- struct llc_sock *llc = llc_sk(sk);
struct llc_conn_state *curr_state =
- &llc_conn_state_table[llc->state - 1];
+ &llc_conn_state_table[state - 1];
/* search thru events for this state until
* list exhausted or until no more
*/
for (next_trans = curr_state->transitions +
- llc_find_offset(llc->state - 1, ev->type);
+ llc_find_offset(state - 1, ev->type);
(*next_trans)->ev; next_trans++) {
if (!((*next_trans)->ev)(sk, skb)) {
/* got POSSIBLE event match; the event may require
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH net v2 2/2] llc: conn: publish OUT_OF_SVC before draining timers
2026-06-08 7:46 [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Ren Wei
@ 2026-06-08 7:46 ` Ren Wei
2026-06-10 1:58 ` [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Jakub Kicinski
1 sibling, 0 replies; 3+ messages in thread
From: Ren Wei @ 2026-06-08 7:46 UTC (permalink / raw)
To: netdev; +Cc: yuantan098, yifanwucs, tomapufckgml, bird, zcliangcn, n05ec
From: Zhengchuan Liang <zcliangcn@gmail.com>
llc_ui_release() drops the socket lock with release_sock() before it
calls llc_sk_free(). In that window, llc_conn_handler() can still take
bh_lock_sock() on the same socket and run the LLC state machine.
If teardown only deletes timers at the end of llc_sk_free(), that
concurrent packet path can still arm a timer again after teardown has
started. timer_delete_sync() only drains timer callbacks; it does not
wait for packet processing that races through llc_conn_handler().
Publish LLC_CONN_OUT_OF_SVC under sk->sk_lock.slock with bottom halves
disabled before synchronously deleting timers. bh_lock_sock() takes
that same lock, so teardown-time RX or timer work serialized there sees
the closed state and stops instead of rearming timers, which closes the
teardown window that can keep stale sockets active.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
- New in v2 to address the teardown timer race raised in review.
- Publish LLC_CONN_OUT_OF_SVC before draining timers.
- v1 link: https://lore.kernel.org/all/5f646c530f4a0820060499054c46b8dbecebd7be.1778638129.git.zlian064@ucr.edu/
net/llc/llc_conn.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 9602183d09d8..dba114929bdd 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -978,8 +978,9 @@ void llc_sk_free(struct sock *sk)
{
struct llc_sock *llc = llc_sk(sk);
- llc->state = LLC_CONN_OUT_OF_SVC;
- /* Stop all (possibly) running timers */
+ spin_lock_bh(&sk->sk_lock.slock);
+ WRITE_ONCE(llc->state, LLC_CONN_OUT_OF_SVC);
+ spin_unlock_bh(&sk->sk_lock.slock);
llc_sk_stop_all_timers(sk, true);
#ifdef DEBUG_LLC_CONN_ALLOC
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __func__,
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service
2026-06-08 7:46 [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Ren Wei
2026-06-08 7:46 ` [PATCH net v2 2/2] llc: conn: publish OUT_OF_SVC before draining timers Ren Wei
@ 2026-06-10 1:58 ` Jakub Kicinski
1 sibling, 0 replies; 3+ messages in thread
From: Jakub Kicinski @ 2026-06-10 1:58 UTC (permalink / raw)
To: Ren Wei; +Cc: netdev, yuantan098, yifanwucs, tomapufckgml, bird, zcliangcn
On Mon, 8 Jun 2026 15:46:53 +0800 Ren Wei wrote:
> llc_conn_service() only rejects states above NBR_CONN_STATES before
> the state machine lookup. That misses LLC_CONN_OUT_OF_SVC, whose value
> is 0.
Warning: ../net/llc/llc_conn.c:393 function parameter 'state' not described in 'llc_qualify_conn_ev'
--
pw-bot: cr
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-06-10 1:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-08 7:46 [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Ren Wei
2026-06-08 7:46 ` [PATCH net v2 2/2] llc: conn: publish OUT_OF_SVC before draining timers Ren Wei
2026-06-10 1:58 ` [PATCH net v2 1/2] llc: conn: use one state snapshot in llc_conn_service Jakub Kicinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.