* [PATCH net v2 00/10] rxrpc: Miscellaneous fixes
@ 2026-06-18 13:47 David Howells
2026-06-18 13:47 ` [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase David Howells
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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
Here are some miscellaneous AF_RXRPC fixes for more stuff found by Sashiko[1][2]:
(1) Reject ACKALL packets for calls not in Tx or immediate post-Tx state.
(2) Fix connection leak from AF_RXRPC recvmsg userspace OOB handling.
(3) Fix double unlock in AF_RXRPC recvmsg userspace OOB handling.
(4) Fix AFS preallocate charge to flush the waitqueue after unlistening
the socket so that any charging thread that does manage to get started
will be waited for before socket destruction.
(5) Fix AFS OOB notify handling to cancel in-progress OOB notification
handling and then to flush the workqueue it's on.
(6) Fix handling of apparent reply reception before initial transmission
starts in client call.
(7) Fix OOB challenge leak in cleanup on notification failure.
(8) Fix infinite loop in recvmsg if OOB packet available, but no calls.
(9) Fix notify vs recvmsg race where notify thinks the call is already
queued.
(10) Fix MSG_PEEK call leak for calls with no content.
David
The patches can be found here also:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes
[1] https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
[2] https://sashiko.dev/#/patchset/20260616155749.2125907-1-dhowells%40redhat.com
Changes
=======
ver #2)
- Addressed the Sashiko review[2] of ver #1.
- Added patches to fix more bugs that it found.
- Adjusted AFS preallocate charge cleanup to only cancel the preallocate
work item after unlistening rather than flushing the entire waitqueue
(which may be waiting on DNS lookup).
-
David Howells (9):
rxrpc: Fix leak of connection from OOB challenge
rxrpc: Fix double unlock in rxrpc_recvmsg()
afs: Fix further netns teardown to cancel the preallocation charger
afs: Fix uncancelled rxrpc OOB message handler
rxrpc: Fix the reception of a reply packet before data transmission
rxrpc: Fix oob challenge leak in cleanup after notification failure
rxrpc: Fix potential infinite loop in rxrpc_recvmsg()
rxrpc: Fix socket notification race
rxrpc: Fix leak of released call in recvmsg(MSG_PEEK)
Wyatt Feng (1):
rxrpc: input: reject ACKALL outside transmit phase
fs/afs/cm_security.c | 3 ++-
fs/afs/rxrpc.c | 10 +++++++++-
net/rxrpc/ar-internal.h | 4 ++--
net/rxrpc/conn_event.c | 9 +++++++--
net/rxrpc/input.c | 29 +++++++++++++++++++++++++----
net/rxrpc/oob.c | 12 ++++++++++--
net/rxrpc/recvmsg.c | 10 ++++------
7 files changed, 59 insertions(+), 18 deletions(-)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-19 21:32 ` Jeffrey E Altman
2026-06-18 13:47 ` [PATCH net v2 02/10] rxrpc: Fix leak of connection from OOB challenge David Howells
` (8 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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, stable, Yuan Tan, Yifan Wu, Juefei Pu,
Zhengchuan Liang, Xin Liu, Ren Wei
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 rxrpc_input_ackall() to mirror the transmit-state gating already
used for normal ACK processing, and ignore ACKALL when there is no
outstanding transmit window to rotate.
Fixes: b341a0263b1b ("rxrpc: Implement progressive transmission queue struct")
Cc: stable@vger.kernel.org
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>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
---
net/rxrpc/input.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index ce761466b02d..37881dffa898 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1214,8 +1214,22 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_ack_summary summary = { 0 };
+ rxrpc_seq_t top = READ_ONCE(call->tx_top);
+
+ switch (__rxrpc_call_state(call)) {
+ case RXRPC_CALL_CLIENT_SEND_REQUEST:
+ case RXRPC_CALL_CLIENT_AWAIT_REPLY:
+ case RXRPC_CALL_SERVER_SEND_REPLY:
+ case RXRPC_CALL_SERVER_AWAIT_ACK:
+ break;
+ default:
+ return;
+ }
+
+ if (call->tx_bottom == top)
+ return;
- if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
+ if (rxrpc_rotate_tx_window(call, top, &summary))
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ackall);
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH net v2 02/10] rxrpc: Fix leak of connection from OOB challenge
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
2026-06-18 13:47 ` [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-18 13:47 ` [PATCH net v2 03/10] rxrpc: Fix double unlock in rxrpc_recvmsg() David Howells
` (7 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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] 15+ messages in thread
* [PATCH net v2 03/10] rxrpc: Fix double unlock in rxrpc_recvmsg()
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
2026-06-18 13:47 ` [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase David Howells
2026-06-18 13:47 ` [PATCH net v2 02/10] rxrpc: Fix leak of connection from OOB challenge David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-18 13:47 ` [PATCH net v2 04/10] afs: Fix further netns teardown to cancel the preallocation charger David Howells
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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] 15+ messages in thread
* [PATCH net v2 04/10] afs: Fix further netns teardown to cancel the preallocation charger
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (2 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 03/10] rxrpc: Fix double unlock in rxrpc_recvmsg() David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-18 13:47 ` [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler David Howells
` (5 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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 flushing the workqueue on which the charger runs 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] 15+ messages in thread
* [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (3 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 04/10] afs: Fix further netns teardown to cancel the preallocation charger David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-20 9:13 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission David Howells
` (4 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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..e8af2a661440 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 (net->live)
+ queue_work(afs_wq, &net->rx_oob_work);
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (4 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-20 9:17 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
` (3 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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 37881dffa898..01ccd2d2fe92 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -247,7 +247,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);
@@ -317,8 +317,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);
@@ -392,6 +391,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] 15+ messages in thread
* [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (5 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-20 9:17 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 08/10] rxrpc: Fix potential infinite loop in rxrpc_recvmsg() David Howells
` (2 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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 98f2165159d7..ead3419f08b7 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1355,9 +1355,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] 15+ messages in thread
* [PATCH net v2 08/10] rxrpc: Fix potential infinite loop in rxrpc_recvmsg()
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (6 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
@ 2026-06-18 13:47 ` David Howells
2026-06-18 13:48 ` [PATCH net v2 09/10] rxrpc: Fix socket notification race David Howells
2026-06-18 13:48 ` [PATCH net v2 10/10] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK) David Howells
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:47 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] 15+ messages in thread
* [PATCH net v2 09/10] rxrpc: Fix socket notification race
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (7 preceding siblings ...)
2026-06-18 13:47 ` [PATCH net v2 08/10] rxrpc: Fix potential infinite loop in rxrpc_recvmsg() David Howells
@ 2026-06-18 13:48 ` David Howells
2026-06-18 13:48 ` [PATCH net v2 10/10] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK) David Howells
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:48 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] 15+ messages in thread
* [PATCH net v2 10/10] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK)
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
` (8 preceding siblings ...)
2026-06-18 13:48 ` [PATCH net v2 09/10] rxrpc: Fix socket notification race David Howells
@ 2026-06-18 13:48 ` David Howells
9 siblings, 0 replies; 15+ messages in thread
From: David Howells @ 2026-06-18 13:48 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).
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
Fixes: 962fb1f651c2 ("rxrpc: Fix recv-recv race of completed call")
---
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] 15+ messages in thread
* Re: [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase
2026-06-18 13:47 ` [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase David Howells
@ 2026-06-19 21:32 ` Jeffrey E Altman
0 siblings, 0 replies; 15+ messages in thread
From: Jeffrey E Altman @ 2026-06-19 21:32 UTC (permalink / raw)
To: David Howells, netdev
Cc: Marc Dionne, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, linux-afs, linux-kernel, Wyatt Feng,
stable, Yuan Tan, Yifan Wu, Juefei Pu, Zhengchuan Liang, Xin Liu,
Ren Wei
On 6/18/2026 9:47 AM, David Howells wrote:
> 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 rxrpc_input_ackall() to mirror the transmit-state gating already
> used for normal ACK processing, and ignore ACKALL when there is no
> outstanding transmit window to rotate.
>
> Fixes: b341a0263b1b ("rxrpc: Implement progressive transmission queue struct")
> Cc: stable@vger.kernel.org
> 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>
> Assisted-by: Codex:GPT-5.4
> Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
> Signed-off-by: David Howells <dhowells@redhat.com>
> cc: Marc Dionne <marc.dionne@auristor.com>
> cc: linux-afs@lists.infradead.org
> ---
> net/rxrpc/input.c | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
> index ce761466b02d..37881dffa898 100644
> --- a/net/rxrpc/input.c
> +++ b/net/rxrpc/input.c
> @@ -1214,8 +1214,22 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
> static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
> {
> struct rxrpc_ack_summary summary = { 0 };
> + rxrpc_seq_t top = READ_ONCE(call->tx_top);
> +
> + switch (__rxrpc_call_state(call)) {
> + case RXRPC_CALL_CLIENT_SEND_REQUEST:
> + case RXRPC_CALL_CLIENT_AWAIT_REPLY:
> + case RXRPC_CALL_SERVER_SEND_REPLY:
> + case RXRPC_CALL_SERVER_AWAIT_ACK:
> + break;
> + default:
> + return;
> + }
> +
> + if (call->tx_bottom == top)
> + return;
>
> - if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
> + if (rxrpc_rotate_tx_window(call, top, &summary))
> rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ackall);
> }
>
Wyatt,
Thank you for identifying the NULL pointer dereference but I do not
believe the patch is correct from an RxRPC protocol perspective.
The rxrpc protocol is not formally standardized. Linux rxrpc is a clean
room implementation of Transarc/IBM RxRPC protocol used by AFS 3.0.
I've been spelunking through old source code trees dating back to
mid-1988. The original usage of the ACKALL packet was a form of delayed
acknowledgement only to be sent after all of the DATA packets inclusive
of the LAST_PACKET had been received. Your expectation of how the
packet type is intended to be used is consistent with that behavior.
However, in Nov 1988 the DATA acknowledgement logic was altered in a
backward incompatible manner. Instead of immediately sending ACK
packets in response to every DATA packet except when the final DATA
packet inclusive of LAST_PACKET was received, the ACK packet usage was
extended to permit delayed transmissions. From Nov 1988 onward ACK
packets were scheduled to be sent with a 200ms delay unless the received
DATA packet was a duplicate, out-of-sequence, out-of-window, etc OR
unless the received DATA packet had the RX_REQUEST_ACK flag set. The
delayed ACKs replaced the ACKALL usage in the general case.
But it appears there was a bug introduced which resulted in the sending
of arbitrary ACKALL packets at any point in the call lifetime. This
bug was not identified until Nov 2001 [OpenAFS
db2ddfaf1b322710e1bd4edce6d7519157c3c9eb] at which point the sending of
ACKALL packets was further restricted. One of the reasons why the
sending of ACKALL packets at arbitrary times was not identified as a
problem for more than a decade is that ACKALL packets received when
there were no transmitted packets waiting for acknowledgement had no
impact on the call state. If there were transmitted packets waiting
for acknowledgement and they were successfully delivered, then the call
continued successfully.
OpenAFS 1.6 pre-releases attempted to resume use of ACKALL packets as a
performance enhancement only to revert the change because of
compatibility problems.
I think the best change at this point would to accept the ACKALL packets
without generating an error regardless of the call state. If there are
transmitted DATA packets waiting for acknowledgement, acknowledge them.
If there are DATA packets which have yet to be sent, leave them alone.
Only complete the call in response to an ACKALL if the ACKALL is
received by the acceptor (incoming call) and all DATA packets inclusive
of LAST_PACKET have been transmitted at least once.
Sincerely,
Jeffrey Altman
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler
2026-06-18 13:47 ` [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler David Howells
@ 2026-06-20 9:13 ` Simon Horman
0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2026-06-20 9:13 UTC (permalink / raw)
To: dhowells
Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
linux-afs, linux-kernel, jaltman, stable
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
afs: Fix uncancelled rxrpc OOB message handler
This patch modifies AFS to cancel its OOB message processing during
shutdown. It moves OOB message processing to afs_wq and adds checks
for the net namespace's live state to prevent processing when no
longer live.
Link: https://sashiko.dev/#/patchset/20260609140911.838677-1-dhowells%40redhat.com
> diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c
> index edcbd249d2024..103168c70dd4d 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);
[Severity: Critical]
This isn't a bug introduced by this patch, but can afs_respond_to_challenge()
cause a null pointer dereference or use-after-free here?
When afs_respond_to_challenge() queries peer_data and casts it to an
afs_server pointer, it unconditionally dereferences it and locks its mutex:
fs/afs/cm_security.c:afs_respond_to_challenge() {
...
server = (struct afs_server *)peer_data;
if (!server->cm_rxgk_appdata.data) {
mutex_lock(&server->cm_token_lock);
...
}
If a challenge is received for an unknown peer, or if afs_server_destroyer()
concurrently clears the peer app_data to null during teardown, could
peer_data be null?
If the pointer was read just before being cleared, could the server object
be freed concurrently since no RCU read lock or refcount is held?
> diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
> index 6714a189d58fb..e8af2a6614405 100644
> --- a/fs/afs/rxrpc.c
> +++ b/fs/afs/rxrpc.c
[ ... ]
> @@ -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 (net->live)
> + queue_work(afs_wq, &net->rx_oob_work);
> }
[Severity: Medium]
Should net->live be read with READ_ONCE() here?
Since net->live can be modified concurrently by namespace teardown code
such as afs_close_socket() or afs_net_exit(), reading it without READ_ONCE()
might allow the compiler to optimize the read, leading to a stale evaluation.
The updated afs_process_oob_queue() function correctly uses READ_ONCE().
Should afs_rx_notify_oob() do the same to prevent data races?
[Severity: High]
This isn't a bug introduced by this patch, but there appears to be a similar
issue in fs/afs/server.c when retrieving the server pointer.
Can afs_find_server() increment the refcount of a freed object?
afs_find_server() fetches the pointer and increments its refcount:
fs/afs/server.c:afs_find_server() {
...
struct afs_server *server = (struct afs_server *)rxrpc_kernel_get_peer_data(peer);
if (!server)
return NULL;
return afs_use_server(server, false, afs_server_trace_use_cm_call);
...
}
If afs_server_destroyer() runs concurrently, unbinds the peer, and frees
the server, could afs_find_server() fetch the pointer just before it is
cleared?
If preempted, it seems this operation lacks RCU read lock protection and
could increment the refcount of a freed object without using
refcount_inc_not_zero().
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission
2026-06-18 13:47 ` [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission David Howells
@ 2026-06-20 9:17 ` Simon Horman
0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2026-06-20 9:17 UTC (permalink / raw)
To: dhowells
Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
linux-afs, linux-kernel, jaltman, stable
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
rxrpc: Fix the reception of a reply packet before data transmission
This commit fixes 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. It also adjusts rxrpc_rotate_tx_window() to handle an empty
Tx queue by changing the do...while loop into a while loop.
Link: https://sashiko.dev/#/patchset/20260616155749.2125907-1-dhowells%40redhat.com
> diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
> index 37881dffa898b..01ccd2d2fe92c 100644
> --- a/net/rxrpc/input.c
> +++ b/net/rxrpc/input.c
> @@ -247,7 +247,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)) {
[Severity: Critical]
This is a pre-existing issue, but can this trigger a use-after-free write
during a concurrent sendmsg() if the remote peer sends an early reply?
Right before this loop in rxrpc_rotate_tx_window(), the code unconditionally
frees the active transmission queue buffer:
if (seq == call->tx_qbase + RXRPC_NR_TXQUEUE) {
call->tx_qbase += RXRPC_NR_TXQUEUE;
call->tx_queue = tq->next;
...
kfree(tq);
tq = call->tx_queue;
}
If a full block of 63 packets is transmitted and ACKed, call->tx_bottom
reaches 63. If the remote peer then sends an early reply,
rxrpc_receiving_reply() calls rxrpc_rotate_tx_window() with to = 63 and seq
starting at 64.
This triggers the condition above and frees the active block (tq) without
verifying if it is still being written to. If it is still the tail
(tq == call->tx_qtail), call->send_queue and call->tx_qtail are left as
dangling pointers.
Concurrently, if the client is still sending data via sendmsg(), it might call
rxrpc_alloc_txqueue() for the 64th packet:
net/rxrpc/sendmsg.c:rxrpc_alloc_txqueue() {
...
if (call->send_queue) {
tq->qbase = call->send_top + 1;
call->send_queue->next = tq;
call->send_queue = tq;
}
...
}
Will call->send_queue->next = tq write a newly allocated pointer into the
recently freed memory block?
[ ... ]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure
2026-06-18 13:47 ` [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
@ 2026-06-20 9:17 ` Simon Horman
0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2026-06-20 9:17 UTC (permalink / raw)
To: dhowells
Cc: Simon Horman, netdev, marc.dionne, kuba, davem, edumazet, pabeni,
linux-afs, linux-kernel, jaltman, stable
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
rxrpc: Fix oob challenge leak in cleanup after notification failure
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.
Link: https://sashiko.dev/#/patchset/20260616155749.2125907-1-dhowells%40redhat.com
> diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
> index c96ca615b787c..611c790bc6d0c 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;
[Severity: Critical]
This is a pre-existing issue, but can the lockless read of
conn->channels[i].call in net/rxrpc/conn_event.c lead to a NULL pointer
dereference?
Looking at rxrpc_post_challenge(), the code does:
if (conn->channels[i].call) {
call = conn->channels[i].call;
rx = rcu_dereference(call->socket);
Without READ_ONCE(), the compiler could issue two separate loads. If a
concurrent thread clears the channel's call pointer after the if-check but
before the assignment, call becomes NULL.
Does this cause the subsequent rcu_dereference(call->socket) to panic by
dereferencing NULL->socket?
[Severity: High]
This isn't a bug introduced by this patch, but does taking a connection
reference here in rxrpc_post_challenge() lead to a leak if the packet is
later discarded due to connection abort or teardown?
If rxrpc_process_event() in net/rxrpc/conn_event.c encounters
conn->state == RXRPC_CONN_ABORTED, it returns -ECONNABORTED early:
if (conn->state == RXRPC_CONN_ABORTED)
return -ECONNABORTED;
This bypasses the cleanup, and the skb is consumed by
rxrpc_do_process_connection() without dropping the sp->chall.conn reference.
Similarly, during teardown, rxrpc_purge_queue() in net/rxrpc/skbuff.c
consumes skbs via:
while ((skb = skb_dequeue((list))) != NULL) {
...
consume_skb(skb);
}
Since it doesn't inspect the cb scratch space, doesn't this permanently leak
the connection references stored in sp->chall.conn?
[ ... ]
> if (call)
> - rxrpc_notify_socket_oob(call, skb);
> + queued = rxrpc_notify_socket_oob(call, skb);
[Severity: High]
This is a pre-existing issue, but does failing to set skb->mark to
RXRPC_OOB_CHALLENGE here in rxrpc_post_challenge() break OOB challenge
processing?
The skb->mark remains RXRPC_SKB_MARK_PACKET as set during ingress.
When the application attempts to respond via rxrpc_respond_to_oob() or read
via rxrpc_recvmsg_oob(), won't the operation fail with -EPROTO because it
expects skb->mark == RXRPC_OOB_CHALLENGE?
Additionally, when the OOB message is freed via rxrpc_kernel_free_oob(),
doesn't the switch statement on oob->mark fail to match, bypassing
rxrpc_put_connection() and leaking the connection reference stored in
sp->chall.conn?
> 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 3318c8bd82ad5..c80ee2487d094 100644
> --- a/net/rxrpc/oob.c
> +++ b/net/rxrpc/oob.c
[ ... ]
> @@ -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;
[Severity: High]
This isn't a bug introduced by this patch, but does unbounded queuing of
challenge packets onto recvmsg_oobq risk a kernel OOM?
In net/rxrpc/oob.c, rxrpc_notify_socket_oob() uses skb_queue_tail() without
checking memory limits (like sk_rmem_alloc vs sk_rcvbuf) or restricting the
total number of challenges.
Since rxrpc_encap_rcv() intercepts these packets before standard UDP memory
accounting occurs, could a remote attacker flood the host with valid
CHALLENGE packets?
If the application is slow to process them or ignores them, will these
accumulate infinitely in recvmsg_oobq and cause a Denial of Service?
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-06-20 9:17 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 13:47 [PATCH net v2 00/10] rxrpc: Miscellaneous fixes David Howells
2026-06-18 13:47 ` [PATCH net v2 01/10] rxrpc: input: reject ACKALL outside transmit phase David Howells
2026-06-19 21:32 ` Jeffrey E Altman
2026-06-18 13:47 ` [PATCH net v2 02/10] rxrpc: Fix leak of connection from OOB challenge David Howells
2026-06-18 13:47 ` [PATCH net v2 03/10] rxrpc: Fix double unlock in rxrpc_recvmsg() David Howells
2026-06-18 13:47 ` [PATCH net v2 04/10] afs: Fix further netns teardown to cancel the preallocation charger David Howells
2026-06-18 13:47 ` [PATCH net v2 05/10] afs: Fix uncancelled rxrpc OOB message handler David Howells
2026-06-20 9:13 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 06/10] rxrpc: Fix the reception of a reply packet before data transmission David Howells
2026-06-20 9:17 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 07/10] rxrpc: Fix oob challenge leak in cleanup after notification failure David Howells
2026-06-20 9:17 ` Simon Horman
2026-06-18 13:47 ` [PATCH net v2 08/10] rxrpc: Fix potential infinite loop in rxrpc_recvmsg() David Howells
2026-06-18 13:48 ` [PATCH net v2 09/10] rxrpc: Fix socket notification race David Howells
2026-06-18 13:48 ` [PATCH net v2 10/10] rxrpc: Fix leak of released call in recvmsg(MSG_PEEK) David Howells
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox