Netdev List
 help / color / mirror / Atom feed
* [PATCH 0/3] rxrpc: fix three bugs found by autokbug fuzzing
@ 2026-08-03  7:33 Henry Martin
  2026-08-03  7:33 ` [PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing Henry Martin
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Henry Martin @ 2026-08-03  7:33 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, marc.dionne, linux-afs, Henry Martin

These three patches fix independent rxrpc bugs found by the autokbug
dynamic kernel fuzzer at Tencent Yunding Lab.

  [1/3] Stack OOB read in TLP soft-ACK processing. A malicious peer
        can deterministically trigger it over an unencrypted
        (security-none) AF_RXRPC association - an immediate KASAN
        stack-out-of-bounds report even at the minimum offset.

  [2/3] kernel BUG in netns teardown: the conn_proc_list assertion
        in rxrpc_destroy_all_connections() races with connection
        destructors deferred to system_wq and fires on a healthy
        state, killing the cleanup_net kworker. Unprivileged
        userns+netns reachable.

  [3/3] WARN_ON in rxrpc_alloc_txqueue(): the TX_NO_MORE entry check
        from commit ae4f89989479 ("rxrpc: Fix ability to add more
        data to a call once MSG_MORE deasserted") is not re-done
        after sleeping in wait_for_space, so a racing sendmsg on the
        same call reaches the WARN on a legal finalized-call state
        (spurious splat and -ENOMEM; panic_on_warn DoS).

Thanks,
Henry

Henry Martin (3):
  rxrpc: fix stack OOB read in TLP soft-ACK processing
  rxrpc: wait for deferred conn destruction before conn_proc_list check
  rxrpc: recheck RXRPC_CALL_TX_NO_MORE after sleeping in rxrpc_send_data()

 net/rxrpc/ar-internal.h | 3 ++-
 net/rxrpc/conn_object.c | 10 ++++++----
 net/rxrpc/sendmsg.c     | 8 ++++++++
 3 files changed, 16 insertions(+), 5 deletions(-)

-- 
2.43.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing
  2026-08-03  7:33 [PATCH 0/3] rxrpc: fix three bugs found by autokbug fuzzing Henry Martin
@ 2026-08-03  7:33 ` Henry Martin
  2026-08-03  7:33 ` [PATCH 2/3] rxrpc: wait for deferred conn destruction before conn_proc_list check Henry Martin
  2026-08-03  7:33 ` [PATCH 3/3] rxrpc: recheck RXRPC_CALL_TX_NO_MORE after sleeping in rxrpc_send_data() Henry Martin
  2 siblings, 0 replies; 4+ messages in thread
From: Henry Martin @ 2026-08-03  7:33 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, marc.dionne, linux-afs, Henry Martin

rxrpc_seq_in_txq() is meant to test whether a sequence number belongs
to a given txqueue segment, but it compares the in-segment slot
number (seq & 63, range 0..63) against the segment's absolute base
sequence (tq->qbase, 0/64/128/...). Two consequences:

- For the first segment (qbase == 0), any seq that is a multiple of
  64 is wrongly judged to belong to it;
- For any later segment (qbase >= 64), the test is always false, so
  TLP probe handling is silently skipped for them.

In rxrpc_input_soft_ack_tq() the first case leads to

	test_bit(call->tlp_seq - tq->qbase, &new_acks)

being evaluated with tlp_seq - qbase == 64*N while new_acks is a
single unsigned long on the stack, i.e. a stack out-of-bounds read
8*N bytes above new_acks (KASAN reports stack-out-of-bounds at
offset 40 for tlp_seq == 64). With a large enough tlp_seq the read
walks off the vmalloc'd kthread stack into the guard page and panics.

Turn the broken slot comparison into a real range check. This bounds
tlp_seq - tq->qbase to [0, RXRPC_NR_TXQUEUE), keeping the test_bit()
inside new_acks, and also fixes TLP probe handling for non-first
segments.

Found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab.

Fixes: 7c482665931b ("rxrpc: Implement RACK/TLP to deal with transmission stalls [RFC8985]")
Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
---
 net/rxrpc/ar-internal.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 865f05fe37ab9..27992e10d82ad 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1580,7 +1580,8 @@ static inline u32 latest(u32 seq1, u32 seq2)
 
 static inline bool rxrpc_seq_in_txq(const struct rxrpc_txqueue *tq, rxrpc_seq_t seq)
 {
-	return (seq & (RXRPC_NR_TXQUEUE - 1)) == tq->qbase;
+	return after_eq(seq, tq->qbase) &&
+	       before(seq, tq->qbase + RXRPC_NR_TXQUEUE);
 }
 
 static inline void rxrpc_queue_rx_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
-- 
2.43.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] rxrpc: wait for deferred conn destruction before conn_proc_list check
  2026-08-03  7:33 [PATCH 0/3] rxrpc: fix three bugs found by autokbug fuzzing Henry Martin
  2026-08-03  7:33 ` [PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing Henry Martin
@ 2026-08-03  7:33 ` Henry Martin
  2026-08-03  7:33 ` [PATCH 3/3] rxrpc: recheck RXRPC_CALL_TX_NO_MORE after sleeping in rxrpc_send_data() Henry Martin
  2 siblings, 0 replies; 4+ messages in thread
From: Henry Martin @ 2026-08-03  7:33 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, marc.dionne, linux-afs, Henry Martin

rxrpc_destroy_all_connections() flushes rxrpc_workqueue and then
immediately asserts that rxnet->conn_proc_list is empty. However,
connection destruction is normally deferred to system_wq: the
final-ACK timer is still pending when the last ref is dropped, so
rxrpc_put_connection() schedules conn->destructor instead of running
it inline. conn->proc_link is only removed by the deferred
destructor (rxrpc_clean_up_connection()), which the
flush_workqueue(rxrpc_workqueue) call does not cover - so the
assertion can fire on a perfectly healthy intermediate state:

	rxrpc: Assertion failed
	kernel BUG at net/rxrpc/conn_object.c:488!
	Workqueue: netns cleanup_net

The BUG kills the cleanup_net kworker mid-teardown, leaving the
netns half-destroyed and potentially wedging later netns operations.
This is easily reachable from an unprivileged userns+netns running
loopback AF_RXRPC traffic.

The existing wait_var_event() on nr_conns is exactly the right
synchronization: nr_conns only reaches zero after every destructor
and RCU free has completed, which implies proc_link has been removed
from every connection. It is, however, placed *after* the assertion
it is meant to make reliable. Move it between the service_conns
leak check (whose outcome is already final once the reaper has been
flushed) and the conn_proc_list assertion.

This also silences the spurious "AF_RXRPC: Leaked peer" messages
seen during netns teardown, which share the same root cause: peer
references are dropped by the same deferred destructors.

Found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab.

Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
---
 net/rxrpc/conn_object.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 0ece717db0f85..df3f92b1a42e9 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -485,11 +485,13 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
 	write_unlock(&rxnet->conn_lock);
 	BUG_ON(leak);
 
-	ASSERT(list_empty(&rxnet->conn_proc_list));
-
-	/* We need to wait for the connections to be destroyed by RCU as they
-	 * pin things that we still need to get rid of.
+	/* Connection destruction is normally deferred to system_wq because
+	 * the final-ACK timer is still pending when the last ref is dropped.
+	 * Wait for the deferred destructors (and the RCU frees) to complete
+	 * before checking conn_proc_list; they remove conns from it.
 	 */
 	wait_var_event(&rxnet->nr_conns, !atomic_read(&rxnet->nr_conns));
+
+	ASSERT(list_empty(&rxnet->conn_proc_list));
 	_leave("");
 }
-- 
2.43.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] rxrpc: recheck RXRPC_CALL_TX_NO_MORE after sleeping in rxrpc_send_data()
  2026-08-03  7:33 [PATCH 0/3] rxrpc: fix three bugs found by autokbug fuzzing Henry Martin
  2026-08-03  7:33 ` [PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing Henry Martin
  2026-08-03  7:33 ` [PATCH 2/3] rxrpc: wait for deferred conn destruction before conn_proc_list check Henry Martin
@ 2026-08-03  7:33 ` Henry Martin
  2 siblings, 0 replies; 4+ messages in thread
From: Henry Martin @ 2026-08-03  7:33 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, marc.dionne, linux-afs, Henry Martin

Commit ae4f89989479 ("rxrpc: Fix ability to add more data to a call
once MSG_MORE deasserted") added the RXRPC_CALL_TX_NO_MORE flag and an
entry check in rxrpc_send_data() to stop late sends on a finalized
call. However, the check runs only once at function entry: when the
transmit window is full, wait_for_space drops call->user_mutex and
sleeps, during which another thread sharing the same user_call_ID can
finalize the call (queue the LAST packet, setting TX_NO_MORE and
clearing send_queue). Upon waking, the reload path only re-verifies
the shutdown flag and call state - and a just-finalized call is still
in RXRPC_CALL_CLIENT_SEND_REQUEST until its data is hard-acked - so
the thread proceeds to rxrpc_alloc_txqueue() with send_queue == NULL
but tx_queue != NULL, triggering:

	WARNING: net/rxrpc/sendmsg.c:297 at rxrpc_alloc_txqueue

and returning a spurious -ENOMEM. The call state itself is entirely
legal at that point; the WARN_ON's implied assumption that
send_queue == NULL implies tx_queue == NULL simply does not hold after
finalization.

Re-check RXRPC_CALL_TX_NO_MORE in the reload path after reacquiring
user_mutex, mirroring the entry check, and bail out with -EPROTO.

Found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab.

Fixes: ae4f89989479 ("rxrpc: Fix ability to add more data to a call once MSG_MORE deasserted")
Signed-off-by: Henry Martin <bsdhenrymartin@gmail.com>
---
 net/rxrpc/sendmsg.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index ed2c9a51005ad..b39af552c6b46 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -358,6 +358,14 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 	if (txb)
 		rxrpc_see_txbuf(txb, rxrpc_txbuf_see_send_more);
 
+	ret = -EPROTO;
+	if (test_bit(RXRPC_CALL_TX_NO_MORE, &call->flags)) {
+		trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
+				  call->cid, call->call_id, call->rx_consumed,
+				  0, -EPROTO);
+		goto maybe_error;
+	}
+
 	ret = -EPIPE;
 	if (sk->sk_shutdown & SEND_SHUTDOWN)
 		goto maybe_error;
-- 
2.43.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-03  7:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-03  7:33 [PATCH 0/3] rxrpc: fix three bugs found by autokbug fuzzing Henry Martin
2026-08-03  7:33 ` [PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing Henry Martin
2026-08-03  7:33 ` [PATCH 2/3] rxrpc: wait for deferred conn destruction before conn_proc_list check Henry Martin
2026-08-03  7:33 ` [PATCH 3/3] rxrpc: recheck RXRPC_CALL_TX_NO_MORE after sleeping in rxrpc_send_data() Henry Martin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox