]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rxrpc: Fix the reception of a reply packet before data transmission
authorDavid Howells <dhowells@redhat.com>
Wed, 24 Jun 2026 16:38:13 +0000 (17:38 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Jun 2026 17:07:18 +0000 (10:07 -0700)
Fix rxrpc_receiving_reply() to handle the reception of an apparent reply
DATA packet before rxrpc has had a chance to send any request DATA packets
on a client call by checking to see if the call has been exposed yet by
sending the first packet.

Without this, rxrpc_rotate_tx_window() might oops.

Also fix rxrpc_rotate_tx_window() to handle the Tx queue being empty by
changing the do...while loop into a while loop, just in case a call is
abnormally terminated by an early reply before the last request packet is
transmitted.

Fixes: b341a0263b1b ("rxrpc: Implement progressive transmission queue struct")
Link: https://sashiko.dev/#/patchset/20260616155749.2125907-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
Link: https://patch.msgid.link/20260624163819.3017002-7-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/rxrpc/input.c

index 2eedab1b0919237b369e53e6c2b72ca6ecb091a0..9bd0f1b92463c82370aec749dfc225e4d656a8fb 100644 (file)
@@ -248,7 +248,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
                tq = call->tx_queue;
        }
 
-       do {
+       while (before_eq(seq, to)) {
                unsigned int ix = seq - call->tx_qbase;
 
                _debug("tq=%x seq=%x i=%d f=%x", tq->qbase, seq, ix, tq->bufs[ix]->flags);
@@ -318,8 +318,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
                                break;
                        }
                }
-
-       } while (before_eq(seq, to));
+       }
 
        if (trace)
                trace_rxrpc_rack_update(call, summary);
@@ -394,6 +393,14 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
                trace_rxrpc_timer_can(call, rxrpc_timer_trace_delayed_ack);
        }
 
+       /* Deal with an apparent reply coming in before we've got the request
+        * queued or transmitted.
+        */
+       if (!test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
+               rxrpc_proto_abort(call, top, rxrpc_eproto_early_reply);
+               return false;
+       }
+
        if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
                if (!rxrpc_rotate_tx_window(call, top, &summary)) {
                        rxrpc_proto_abort(call, top, rxrpc_eproto_early_reply);