[PATCH] rxrpc: Fix read+write past skb_headlen in soft-ACK parser
David Howells
dhowells at redhat.com
Fri May 15 16:17:38 PDT 2026
Jeffrey E Altman <jaltman at auristor.com> wrote:
> Aborting the call because skb_condense() was unable to consolidate the rx ack
> packet data is an unfriendly thing to do.
>
> As suggested by the commit message, copying the data before processing would
> be a friendlier solution to the identified problem.
Agreed. Something along the lines of the attached. It still needs a bit more
polishing, though.
David
---
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 24aceb183c2c..dde87b058a23 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -963,21 +963,30 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call,
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_txqueue *tq = call->tx_queue;
unsigned long extracted = ~0UL;
- unsigned int nr = 0;
+ unsigned int nr = 0, nsack;
rxrpc_seq_t seq = call->acks_hard_ack + 1;
rxrpc_seq_t lowest_nak = seq + sp->ack.nr_acks;
- u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
+ u8 sack[256] __aligned(sizeof(unsigned long));
+ u8 *acks = sack;
_enter("%x,%x,%u", tq->qbase, seq, sp->ack.nr_acks);
while (after(seq, tq->qbase + RXRPC_NR_TXQUEUE - 1))
tq = tq->next;
+ /* Extract a SACK table. A SACK table can hold up to 256*8 ACK bits. */
+ memset(sack, 0, sizeof(sack));
+ nsack = umin(sp->ack.nr_acks, 256);
+ if (skb_copy_bits(skb,
+ sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket),
+ sack, nsack) < 0)
+ return;
+
for (unsigned int i = 0; i < sp->ack.nr_acks; i++) {
/* Decant ACKs until we hit a txqueue boundary. */
shiftr_adv_rotr(acks, extracted);
if (i == 256) {
- acks -= i;
+ acks = sack;
i = 0;
}
seq++;
More information about the linux-afs
mailing list