Skip to content

Commit 101cbf4

Browse files
committed
rxrpc: Fix recvmsg() unconditional requeue
jira VULN-175573 cve CVE-2026-23066 commit-author David Howells <dhowells@redhat.com> commit 2c28769 upstream-diff Used linux-6.12.y backport cf969bd as the basis, which, unlike the upstream, produces no conflicts in net/rxrpc/recvmsg.c and only trivial conflicts in include/trace/events/rxrpc.h. The contentious commit is the non-backported a2ea9a9 ("Use irq-disabling spinlocks between app and I/O thread"), which changes spin_lock()/spin_unlock() pairs to spin_lock_irq()/spin_unlock_irq(). Spin locks are used in the CVE fix which makes the upstream version incompatible. Linux 6.12 doesn't have this commit backported either which makes it better suited for LTS 9.6. Conflicts left in include/trace/events/rxrpc.h are just a matter of putting the newly defined trace points in a correct place on the alphabetically-ordered list. If rxrpc_recvmsg() fails because MSG_DONTWAIT was specified but the call at the front of the recvmsg queue already has its mutex locked, it requeues the call - whether or not the call is already queued. The call may be on the queue because MSG_PEEK was also passed and so the call was not dequeued or because the I/O thread requeued it. The unconditional requeue may then corrupt the recvmsg queue, leading to things like UAFs or refcount underruns. Fix this by only requeuing the call if it isn't already on the queue - and moving it to the front if it is already queued. If we don't queue it, we have to put the ref we obtained by dequeuing it. Also, MSG_PEEK doesn't dequeue the call so shouldn't call rxrpc_notify_socket() for the call if we didn't use up all the data on the queue, so fix that also. Fixes: 540b1c4 ("rxrpc: Fix deadlock between call creation and sendmsg/recvmsg") Reported-by: Faith <faith@zellic.io> Reported-by: Pumpkin Chang <pumpkin@devco.re> Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Marc Dionne <marc.dionne@auristor.com> cc: Nir Ohfeld <niro@wiz.io> cc: Willy Tarreau <w@1wt.eu> cc: Simon Horman <horms@kernel.org> cc: linux-afs@lists.infradead.org cc: stable@kernel.org Link: https://patch.msgid.link/95163.1768428203@warthog.procyon.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit cf969bd) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 55d4230 commit 101cbf4

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

include/trace/events/rxrpc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
EM(rxrpc_call_put_kernel, "PUT kernel ") \
274274
EM(rxrpc_call_put_poke, "PUT poke ") \
275275
EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \
276+
EM(rxrpc_call_put_recvmsg_peek_nowait, "PUT peek-nwt") \
276277
EM(rxrpc_call_put_release_sock, "PUT rls-sock") \
277278
EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \
278279
EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \
@@ -287,6 +288,9 @@
287288
EM(rxrpc_call_see_disconnected, "SEE disconn ") \
288289
EM(rxrpc_call_see_distribute_error, "SEE dist-err") \
289290
EM(rxrpc_call_see_input, "SEE input ") \
291+
EM(rxrpc_call_see_recvmsg_requeue, "SEE recv-rqu") \
292+
EM(rxrpc_call_see_recvmsg_requeue_first, "SEE recv-rqF") \
293+
EM(rxrpc_call_see_recvmsg_requeue_move, "SEE recv-rqM") \
290294
EM(rxrpc_call_see_release, "SEE release ") \
291295
EM(rxrpc_call_see_userid_exists, "SEE u-exists") \
292296
E_(rxrpc_call_see_zap, "SEE zap ")

net/rxrpc/recvmsg.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
415415
if (rxrpc_call_has_failed(call))
416416
goto call_failed;
417417

418-
if (!skb_queue_empty(&call->recvmsg_queue))
418+
if (!(flags & MSG_PEEK) &&
419+
!skb_queue_empty(&call->recvmsg_queue))
419420
rxrpc_notify_socket(call);
420421
goto not_yet_complete;
421422

@@ -446,11 +447,21 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
446447
error_requeue_call:
447448
if (!(flags & MSG_PEEK)) {
448449
spin_lock(&rx->recvmsg_lock);
449-
list_add(&call->recvmsg_link, &rx->recvmsg_q);
450-
spin_unlock(&rx->recvmsg_lock);
450+
if (list_empty(&call->recvmsg_link)) {
451+
list_add(&call->recvmsg_link, &rx->recvmsg_q);
452+
rxrpc_see_call(call, rxrpc_call_see_recvmsg_requeue);
453+
spin_unlock(&rx->recvmsg_lock);
454+
} else if (list_is_first(&call->recvmsg_link, &rx->recvmsg_q)) {
455+
spin_unlock(&rx->recvmsg_lock);
456+
rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_first);
457+
} else {
458+
list_move(&call->recvmsg_link, &rx->recvmsg_q);
459+
spin_unlock(&rx->recvmsg_lock);
460+
rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_move);
461+
}
451462
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
452463
} else {
453-
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
464+
rxrpc_put_call(call, rxrpc_call_put_recvmsg_peek_nowait);
454465
}
455466
error_no_call:
456467
release_sock(&rx->sk);

0 commit comments

Comments
 (0)