[PATCH 1/3] rxrpc: fix stack OOB read in TLP soft-ACK processing

Henry Martin <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.