FAILED: patch "[PATCH] rxrpc: Fix the ACK parser to extract the SACK table for" failed to apply to 6.12-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 333b6d5bb9f87827ac2639c737bf9613dbae7253
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026061541-settle-letdown-ad0c@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 333b6d5bb9f87827ac2639c737bf9613dbae7253 Mon Sep 17 00:00:00 2001
From: David Howells <[email protected]>
Date: Thu, 4 Jun 2026 12:46:00 +0100
Subject: [PATCH] rxrpc: Fix the ACK parser to extract the SACK table for
parsing
Fix modification of the received skbuff in rxrpc_input_soft_acks() and a potential incorrect access of the buffer in a fragmented UDP packet (the packet would probably have to be deliberately pre-generated as fragmented) when AF_RXRPC tries to extract the contents of the SACK table by copying out the contents of the SACK table into a buffer before attempting to parse
AF_RXRPC assumes that it can just call skb_condense() and then validly access the SACK table from skb->data and that it will be a flat buffer - but skb_condense() can silently fail to do anything under some circumstances.
Note that whilst rxrpc_input_soft_acks() should be able to parse extended ACKs, the rest of AF_RXRPC doesn't currently support that.
Further, there's then no need to call skb_condense() in rxrpc_input_ack(), so don't.
net/rxrpc/input.c +17 -9
@@ -963,23 +963,34 @@ 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 an individual SACK table. A normal SACK table is up to 255 +* bytes with 1 ACK flag per byte, but an extended SACK table can be up +* to 256 bytes with up to 8 ACK/NACK flags per byte. The ACK flags go +* across all bit 0's then all bit 1's, then all bit 2's, ... +*/ +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. */ +if ((i &255 ) ==0 ) + acks = sack;shiftr_adv_rotr (acks, extracted); -if (i ==256 ) { - acks -= i; - i =0 ; - } seq++; nr++;if ((seq &RXRPC_TXQ_MASK ) !=0 )
@@ -1117,9 +1128,6 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0)return rxrpc_proto_abort (call,0 , rxrpc_badmsg_short_ack_trailer); -if (nr_acks >0 ) -skb_condense (skb); - call->acks_latest_ts =ktime_get_real (); call->acks_hard_ack = hard_ack; call->acks_prev_seq = prev_pkt;
Sasha Levin
maintainerPATCH 1/1 rxrpc: Fix the ACK parser to extract the SACK table for parsing
From: David Howells <[email protected]>
[ Upstream commit 333b6d5bb9f87827ac2639c737bf9613dbae7253 ]
Fix modification of the received skbuff in rxrpc_input_soft_acks() and a potential incorrect access of the buffer in a fragmented UDP packet (the packet would probably have to be deliberately pre-generated as fragmented) when AF_RXRPC tries to extract the contents of the SACK table by copying out the contents of the SACK table into a buffer before attempting to parse
AF_RXRPC assumes that it can just call skb_condense() and then validly access the SACK table from skb->data and that it will be a flat buffer - but skb_condense() can silently fail to do anything under some circumstances.
Note that whilst rxrpc_input_soft_acks() should be able to parse extended ACKs, the rest of AF_RXRPC doesn't currently support that.
Further, there's then no need to call skb_condense() in rxrpc_input_ack(), so don't.
--- net/rxrpc/input.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
net/rxrpc/input.c +16 -5
@@ -775,9 +775,23 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, rxrpc_seq_t since) {struct rxrpc_skb_priv *sp =rxrpc_skb (skb); -unsigned int i, old_nacks =0 ; +unsigned int i, old_nacks =0 , nsack;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; + +/* AF_RXRPC assumes that it can access the SACK table directly from +* skb->data as a flat buffer, but the skb may be non-linear (e.g. a +* fragmented UDP packet) and skb_condense() can silently fail to +* linearise it. Copy the SACK table out into a local buffer before +* parsing it. +*/ +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 (i =0 ; i < sp->ack.nr_acks; i++) {if (acks[i] ==RXRPC_ACK_TYPE_ACK ) {
@@ -934,9 +948,6 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0)return rxrpc_proto_abort (call,0 , rxrpc_badmsg_short_ack_trailer); -if (nr_acks >0 ) -skb_condense (skb); -if (call->cong_last_nack) { since =rxrpc_input_check_prev_ack (call, &summary, first_soft_ack);rxrpc_free_skb (call->cong_last_nack, rxrpc_skb_put_last_nack);
Signature · 1 line
2.53.0