* [PATCH net v3 01/11] rxrpc: Fix ACKALL packet handling
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 02/11] rxrpc: Fix leak of connection from OOB challenge David Howells
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Wyatt Feng, Yuan Tan, Yifan Wu, Juefei Pu, Zhengchuan Liang,
Xin Liu, Ren Wei, stable
From: Wyatt Feng <bronzed_45_vested@icloud.com>
rxrpc_input_ackall() accepts ACKALL packets without checking whether the
call is in a state that can legitimately have outstanding transmit buffers.
A forged ACKALL can therefore reach a new service call in
RXRPC_CALL_SERVER_RECV_REQUEST before any reply packets have been queued.
In that state call->tx_top is zero and call->tx_queue is NULL, so
rxrpc_rotate_tx_window() dereferences a NULL txqueue and triggers a
null-pointer dereference.
Fix the handling of ACKALL packets by the following means:
(1) Add two new call states: RXRPC_CALL_CLIENT_PRE_SEND which indicates
that the client call is connected, but nothing has been transmitted as
yet; and RXRPC_CALL_CLIENT_AWAIT_ACK, which indicates that everything
has been transmitted at least once, but we're now waiting for the
stuff remaining in the Tx buffer to be ACK'd (retransmissions may
still happen).
The RXRPC_CALL_CLIENT_PRE_SEND state is set when the call is assigned
a channel and transitions to RXRPC_CALL_CLIENT_SEND_REQUEST when the
first packet is transmitted.
RXRPC_CALL_CLIENT_AWAIT_REPLY is then narrowed in scope to indicate
that all Tx packets have been ACK'd and we're now waiting for the
reply to be received.
(2) As per Wyatt Feng's original patch[1], the ACKALL handler then checks
that the call state is one in which there might be stuff in the Tx
buffer to ACK, but now this includes AWAIT_ACK rather than
AWAIT_REPLY. ACKALL packets are ignored if received in the wrong
state.
Note that unlike Wyatt Feng's patch, it's no longer necessary to check
to see if the Tx buffer exists as this the state set now covers this.
(3) Make the ACKALL handler use call->tx_transmitted rather than
call->tx_top as the former is explicitly the highest packet seq number
transmitted, whereas the latter has a looser definition.
Thanks to Jeffrey Altman for a description of the history of the ACKALL
packet[1].
Fixes: b341a0263b1b ("rxrpc: Implement progressive transmission queue struct")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Co-developed-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Ren Wei <n05ec@lzu.edu.cn>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20260616155749.2125907-2-dhowells@redhat.com/ [1]
Link: https://lore.kernel.org/r/c0fd4fec-1576-4070-b31e-a37d5506f5ed@auristor.com/ [2]
---
net/rxrpc/ar-internal.h | 2 ++
net/rxrpc/call_event.c | 5 ++++-
net/rxrpc/call_object.c | 2 ++
net/rxrpc/conn_client.c | 2 +-
net/rxrpc/input.c | 23 +++++++++++++++++++----
net/rxrpc/sendmsg.c | 3 ++-
6 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 98f2165159d7..b6ccd8a8199b 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -650,7 +650,9 @@ enum rxrpc_call_event {
enum rxrpc_call_state {
RXRPC_CALL_UNINITIALISED,
RXRPC_CALL_CLIENT_AWAIT_CONN, /* - client waiting for connection to become available */
+ RXRPC_CALL_CLIENT_PRE_SEND, /* - client is connected, but hasn't sent anything yet */
RXRPC_CALL_CLIENT_SEND_REQUEST, /* - client sending request phase */
+ RXRPC_CALL_CLIENT_AWAIT_ACK, /* - client awaiting ACKs of request */
RXRPC_CALL_CLIENT_AWAIT_REPLY, /* - client awaiting reply */
RXRPC_CALL_CLIENT_RECV_REPLY, /* - client receiving reply phase */
RXRPC_CALL_SERVER_PREALLOC, /* - service preallocation */
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index fec59d9338b9..21be9c86d7a7 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -178,7 +178,7 @@ static void rxrpc_close_tx_phase(struct rxrpc_call *call)
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
- rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY);
+ rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_ACK);
break;
case RXRPC_CALL_SERVER_SEND_REPLY:
rxrpc_set_call_state(call, RXRPC_CALL_SERVER_AWAIT_ACK);
@@ -244,6 +244,8 @@ static void rxrpc_transmit_fresh_data(struct rxrpc_call *call, unsigned int limi
break;
} while (req.n < limit && before(seq, send_top));
+ if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_PRE_SEND)
+ rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_SEND_REQUEST);
if (txb->flags & RXRPC_LAST_PACKET) {
rxrpc_close_tx_phase(call);
tq = NULL;
@@ -267,6 +269,7 @@ void rxrpc_transmit_some_data(struct rxrpc_call *call, unsigned int limit,
fallthrough;
case RXRPC_CALL_SERVER_SEND_REPLY:
+ case RXRPC_CALL_CLIENT_PRE_SEND:
case RXRPC_CALL_CLIENT_SEND_REQUEST:
if (!rxrpc_tx_window_space(call))
return;
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index fcb9d38bb521..817ed9acb91e 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -18,7 +18,9 @@
const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
[RXRPC_CALL_UNINITIALISED] = "Uninit ",
[RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn",
+ [RXRPC_CALL_CLIENT_PRE_SEND] = "ClPreSnd",
[RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq",
+ [RXRPC_CALL_CLIENT_AWAIT_ACK] = "ClAwtAck",
[RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl",
[RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl",
[RXRPC_CALL_SERVER_PREALLOC] = "SvPrealc",
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 9b757798dedd..48519f0de185 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -449,7 +449,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
trace_rxrpc_connect_call(call);
call->tx_last_sent = ktime_get_real();
rxrpc_start_call_timer(call);
- rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_SEND_REQUEST);
+ rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_PRE_SEND);
wake_up(&call->waitq);
}
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index ce761466b02d..2eedab1b0919 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -181,7 +181,8 @@ void rxrpc_congestion_degrade(struct rxrpc_call *call)
if (call->cong_ca_state != RXRPC_CA_SLOW_START &&
call->cong_ca_state != RXRPC_CA_CONGEST_AVOIDANCE)
return;
- if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
+ if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_ACK ||
+ __rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
return;
rtt = ns_to_ktime(call->srtt_us * (NSEC_PER_USEC / 8));
@@ -356,6 +357,7 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
+ case RXRPC_CALL_CLIENT_AWAIT_ACK:
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
if (reply_begun) {
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_RECV_REPLY);
@@ -694,6 +696,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
+ case RXRPC_CALL_CLIENT_AWAIT_ACK:
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
/* Received data implicitly ACKs all of the request
* packets we sent when we're acting as a client.
@@ -1154,10 +1157,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
if (hard_ack + 1 == 0)
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
- /* Ignore ACKs unless we are or have just been transmitting. */
+ /* Ignore ACKs unless we are transmitting or are waiting for
+ * acknowledgement of the packets we've just been transmitting.
+ */
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
- case RXRPC_CALL_CLIENT_AWAIT_REPLY:
+ case RXRPC_CALL_CLIENT_AWAIT_ACK:
case RXRPC_CALL_SERVER_SEND_REPLY:
case RXRPC_CALL_SERVER_AWAIT_ACK:
break;
@@ -1215,7 +1220,17 @@ static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_ack_summary summary = { 0 };
- if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
+ switch (__rxrpc_call_state(call)) {
+ case RXRPC_CALL_CLIENT_SEND_REQUEST:
+ case RXRPC_CALL_CLIENT_AWAIT_ACK:
+ case RXRPC_CALL_SERVER_SEND_REPLY:
+ case RXRPC_CALL_SERVER_AWAIT_ACK:
+ break;
+ default:
+ return;
+ }
+
+ if (rxrpc_rotate_tx_window(call, call->tx_transmitted, &summary))
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ackall);
}
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index c35de4fd75e3..ed2c9a51005a 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -366,7 +366,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
if (state >= RXRPC_CALL_COMPLETE)
goto maybe_error;
ret = -EPROTO;
- if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
+ if (state != RXRPC_CALL_CLIENT_PRE_SEND &&
+ state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
state != RXRPC_CALL_SERVER_SEND_REPLY) {
/* Request phase complete for this client call */
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 02/11] rxrpc: Fix leak of connection from OOB challenge
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
2026-06-24 16:38 ` [PATCH net v3 01/11] rxrpc: Fix ACKALL packet handling David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 03/11] rxrpc: Fix double unlock in rxrpc_recvmsg() David Howells
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
stable
Fix leak of connection object from OOB challenge queue when response is
provided by userspace.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Link: https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/oob.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/rxrpc/oob.c b/net/rxrpc/oob.c
index 05ca9c1faa57..3318c8bd82ad 100644
--- a/net/rxrpc/oob.c
+++ b/net/rxrpc/oob.c
@@ -210,6 +210,11 @@ static int rxrpc_respond_to_oob(struct rxrpc_sock *rx,
break;
}
+ switch (skb->mark) {
+ case RXRPC_OOB_CHALLENGE:
+ rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob);
+ break;
+ }
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
return ret;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 03/11] rxrpc: Fix double unlock in rxrpc_recvmsg()
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
2026-06-24 16:38 ` [PATCH net v3 01/11] rxrpc: Fix ACKALL packet handling David Howells
2026-06-24 16:38 ` [PATCH net v3 02/11] rxrpc: Fix leak of connection from OOB challenge David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 04/11] afs: Fix further netns teardown to cancel the preallocation charger David Howells
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
stable
Fix a double unlock in rxrpc_recvmsg() when dealing with OOB messages.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Link: https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/recvmsg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 82614cbdb60f..39a03684432d 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -471,7 +471,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
release_sock(&rx->sk);
if (ret == -EAGAIN)
goto try_again;
- goto error_no_call;
+ goto error_trace;
}
/* Find the next call and dequeue it if we're not just peeking. If we
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 04/11] afs: Fix further netns teardown to cancel the preallocation charger
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (2 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 03/11] rxrpc: Fix double unlock in rxrpc_recvmsg() David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 05/11] afs: Fix uncancelled rxrpc OOB message handler David Howells
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Li Daming, Ren Wei, Jeffrey Altman, stable
When an afs network namespace is torn down, it cancels and waits for the
work item that keeps the preallocated rxrpc call/conn/peer queue charged
before disabling incoming (i.e. listen 0), but there's a small window in
which it can be requeued by an incoming call wending through the I/O
thread.
Fix this by cancelling the charger work item again after reducing the
listen backlog to zero.
Fixes: 47694fbc9d24 ("afs: Fix netns teardown to cancel the preallocation charger")
Reported-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
cc: Li Daming <d4n.for.sec@gmail.com>
cc: Ren Wei <n05ec@lzu.edu.cn>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
fs/afs/rxrpc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index d5cfd24e815b..6714a189d58f 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -128,8 +128,13 @@ void afs_close_socket(struct afs_net *net)
_enter("");
cancel_work_sync(&net->charge_preallocation_work);
+ /* Future work items should now see ->live is false. */
+
kernel_listen(net->socket, 0);
+
+ /* Make sure work items are no longer running. */
flush_workqueue(afs_async_calls);
+ cancel_work_sync(&net->charge_preallocation_work);
if (net->spare_incoming_call) {
afs_put_call(net->spare_incoming_call);
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 05/11] afs: Fix uncancelled rxrpc OOB message handler
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (3 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 04/11] afs: Fix further netns teardown to cancel the preallocation charger David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 06/11] rxrpc: Fix the reception of a reply packet before data transmission David Howells
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Li Daming, Ren Wei, Jeffrey Altman, stable
Fix AFS to cancel its OOB message processing (typically to respond to
security challenges). Also move OOB message processing to afs_wq so that
it's also waited for and make the OOB handler just return if the net
namespace is no longer live.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Link: https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Li Daming <d4n.for.sec@gmail.com>
cc: Ren Wei <n05ec@lzu.edu.cn>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
fs/afs/cm_security.c | 3 ++-
fs/afs/rxrpc.c | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c
index edcbd249d202..103168c70dd4 100644
--- a/fs/afs/cm_security.c
+++ b/fs/afs/cm_security.c
@@ -101,7 +101,8 @@ void afs_process_oob_queue(struct work_struct *work)
struct sk_buff *oob;
enum rxrpc_oob_type type;
- while ((oob = rxrpc_kernel_dequeue_oob(net->socket, &type))) {
+ while (READ_ONCE(net->live) &&
+ (oob = rxrpc_kernel_dequeue_oob(net->socket, &type))) {
switch (type) {
case RXRPC_OOB_CHALLENGE:
afs_respond_to_challenge(oob);
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 6714a189d58f..d82916657a3d 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -128,6 +128,7 @@ void afs_close_socket(struct afs_net *net)
_enter("");
cancel_work_sync(&net->charge_preallocation_work);
+ cancel_work_sync(&net->rx_oob_work);
/* Future work items should now see ->live is false. */
kernel_listen(net->socket, 0);
@@ -148,6 +149,7 @@ void afs_close_socket(struct afs_net *net)
kernel_sock_shutdown(net->socket, SHUT_RDWR);
flush_workqueue(afs_async_calls);
+ cancel_work_sync(&net->rx_oob_work);
net->socket->sk->sk_user_data = NULL;
sock_release(net->socket);
key_put(net->fs_cm_token_key);
@@ -989,5 +991,6 @@ static void afs_rx_notify_oob(struct sock *sk, struct sk_buff *oob)
{
struct afs_net *net = sk->sk_user_data;
- schedule_work(&net->rx_oob_work);
+ if (READ_ONCE(net->live))
+ queue_work(afs_wq, &net->rx_oob_work);
}
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 06/11] rxrpc: Fix the reception of a reply packet before data transmission
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (4 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 05/11] afs: Fix uncancelled rxrpc OOB message handler David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 07/11] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/input.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 2eedab1b0919..9bd0f1b92463 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -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);
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 07/11] rxrpc: Fix oob challenge leak in cleanup after notification failure
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (5 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 06/11] rxrpc: Fix the reception of a reply packet before data transmission David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 08/11] rxrpc: Fix potential infinite loop in rxrpc_recvmsg() David Howells
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
Fix rxrpc_notify_socket_oob() to return an indication of failure in the
event that it failed to queue a packet and fix rxrpc_post_challenge() to
clean up the connection ref in such an event.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/ar-internal.h | 4 ++--
net/rxrpc/conn_event.c | 9 +++++++--
net/rxrpc/oob.c | 7 +++++--
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index b6ccd8a8199b..d2b31d15851b 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1357,9 +1357,9 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
}
/*
- * out_of_band.c
+ * oob.c
*/
-void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb);
+bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb);
void rxrpc_add_pending_oob(struct rxrpc_sock *rx, struct sk_buff *skb);
int rxrpc_sendmsg_oob(struct rxrpc_sock *rx, struct msghdr *msg, size_t len);
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index c96ca615b787..611c790bc6d0 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -436,7 +436,7 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_call *call = NULL;
struct rxrpc_sock *rx;
- bool respond = false;
+ bool respond = false, queued = false;
sp->chall.conn =
rxrpc_get_connection(conn, rxrpc_conn_get_challenge_input);
@@ -472,8 +472,13 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
}
if (call)
- rxrpc_notify_socket_oob(call, skb);
+ queued = rxrpc_notify_socket_oob(call, skb);
rcu_read_unlock();
+ if (call && !queued) {
+ rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
+ sp->chall.conn = NULL;
+ return false;
+ }
if (!call)
rxrpc_post_packet_to_conn(conn, skb);
diff --git a/net/rxrpc/oob.c b/net/rxrpc/oob.c
index 3318c8bd82ad..c80ee2487d09 100644
--- a/net/rxrpc/oob.c
+++ b/net/rxrpc/oob.c
@@ -32,11 +32,12 @@ struct rxrpc_oob_params {
* Post an out-of-band message for attention by the socket or kernel service
* associated with a reference call.
*/
-void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
+bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_sock *rx;
struct sock *sk;
+ bool queued = false;
rcu_read_lock();
@@ -49,6 +50,7 @@ void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
skb->skb_mstamp_ns = rx->oob_id_counter++;
rxrpc_get_skb(skb, rxrpc_skb_get_post_oob);
skb_queue_tail(&rx->recvmsg_oobq, skb);
+ queued = true;
trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
if (rx->app_ops)
@@ -56,11 +58,12 @@ void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
}
spin_unlock_irq(&rx->recvmsg_lock);
- if (!rx->app_ops && !sock_flag(sk, SOCK_DEAD))
+ if (queued && !rx->app_ops && !sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk);
}
rcu_read_unlock();
+ return queued;
}
/*
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 08/11] rxrpc: Fix potential infinite loop in rxrpc_recvmsg()
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (6 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 07/11] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 09/11] rxrpc: Fix socket notification race David Howells
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
Fix the wait in rxrpc_recvmsg() also take check the oob queue.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/recvmsg.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 39a03684432d..f382a47c6eb0 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -438,7 +438,8 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
return -EAGAIN;
}
- if (list_empty(&rx->recvmsg_q)) {
+ if (list_empty(&rx->recvmsg_q) &&
+ skb_queue_empty_lockless(&rx->recvmsg_oobq)) {
ret = -EWOULDBLOCK;
if (timeo == 0) {
call = NULL;
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 09/11] rxrpc: Fix socket notification race
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (7 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 08/11] rxrpc: Fix potential infinite loop in rxrpc_recvmsg() David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 10/11] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK) David Howells
2026-06-24 16:38 ` [PATCH net v3 11/11] rxrpc: Fix rxrpc_rotate_tx_rotate() to check there's something to rotate David Howells
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
There's a race between rxrpc_recvmsg() and rxrpc_notify_socket(), whereby
the latter's attempt to avoid disabling interrupts and taking the socket's
recvmsg_lock if the call is already queued may happen simultaneously with
the former's discarding of a call that has nothing queued.
Fix this by removing the shortcut. Note that this only affects userspace's
use of AF_RXRPC; the AFS filesystem driver doesn't use the socket queue.
Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/recvmsg.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index f382a47c6eb0..9962e135cb73 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -27,8 +27,6 @@ void rxrpc_notify_socket(struct rxrpc_call *call)
_enter("%d", call->debug_id);
- if (!list_empty(&call->recvmsg_link))
- return;
if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
rxrpc_see_call(call, rxrpc_call_see_notify_released);
return;
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 10/11] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK)
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (8 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 09/11] rxrpc: Fix socket notification race David Howells
@ 2026-06-24 16:38 ` David Howells
2026-06-24 16:38 ` [PATCH net v3 11/11] rxrpc: Fix rxrpc_rotate_tx_rotate() to check there's something to rotate David Howells
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
Fix rxrpc_recvmsg() to also drop the ref it holds on an already-released
call if MSG_PEEK is in force (the function holds a ref on the call
irrespective of whether MSG_PEEK is specified or not).
Fixes: 962fb1f651c2 ("rxrpc: Fix recv-recv race of completed call")
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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/recvmsg.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 9962e135cb73..efcba4b2e74f 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -529,8 +529,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
rxrpc_see_call(call, rxrpc_call_see_already_released);
mutex_unlock(&call->user_mutex);
- if (!(flags & MSG_PEEK))
- rxrpc_put_call(call, rxrpc_call_put_recvmsg);
+ rxrpc_put_call(call, rxrpc_call_put_recvmsg);
goto try_again;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net v3 11/11] rxrpc: Fix rxrpc_rotate_tx_rotate() to check there's something to rotate
2026-06-24 16:38 [PATCH net v3 00/11] rxrpc: Miscellaneous fixes David Howells
` (9 preceding siblings ...)
2026-06-24 16:38 ` [PATCH net v3 10/11] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK) David Howells
@ 2026-06-24 16:38 ` David Howells
10 siblings, 0 replies; 12+ messages in thread
From: David Howells @ 2026-06-24 16:38 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel,
Jeffrey Altman, stable
Fix rxrpc_rotate_tx_rotate() to check that there's something in the
transmission buffer to be rotated before it attempts to rotate anything.
Fixes: b341a0263b1b ("rxrpc: Implement progressive transmission queue struct")
Link: https://sashiko.dev/#/patchset/20260618134802.2477777-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: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
net/rxrpc/input.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 9bd0f1b92463..73cafe6bfa9f 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -237,6 +237,9 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
call->acks_lowest_nak = to;
}
+ if (after(seq, to))
+ return false;
+
/* We may have a left over fully-consumed buffer at the front that we
* couldn't drop before (rotate_and_keep below).
*/
^ permalink raw reply related [flat|nested] 12+ messages in thread