mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Juan Agustin Niccolini <juanagusnicco@gmail.com>
To: netdev@vger.kernel.org, linux-afs@lists.infradead.org
Cc: dhowells@redhat.com, marc.dionne@auristor.com, kuba@kernel.org,
	pabeni@redhat.com, edumazet@kernel.org, davem@davemloft.net,
	horms@kernel.org, jaltman@auristor.com,
	linux-kernel@vger.kernel.org
Subject: [PATCH net] rxrpc: Fix rxrpc_sock UAF caused by missing poke in rxrpc_abort_eproto()
Date: Thu,  5 Nov 2026 20:15:50 -0500	[thread overview]
Message-ID: <20261106011550.59902-1-juanagusnicco@gmail.com> (raw)

Since commit 03fc55adf876 ("rxrpc: Only disconnect calls in the I/O
thread"), only the I/O thread disconnects a call from its connection
channel, and hence, code that completes a call elsewhere must poke it
with rxrpc_poke_call(), which queues the call for the I/O thread.

rxrpc_abort_eproto(), which aborts a call when a DATA packet fails
security verification in recvmsg() or rxrpc_kernel_recv_data(), marks
the call as complete but doesn't poke it.  The call is then never
disconnected, not even when its socket is closed, because
rxrpc_propose_abort() skips calls that are already complete.  It stays
in conn->channels[], and its call->socket pointer, which holds no
reference on the socket, dangles once the socket is closed and freed.

If the peer then sends an rxgk CHALLENGE on that connection,
rxrpc_post_challenge() finds the call and reads the freed socket's
flags.  If the socket had enabled RXRPC_MANAGE_RESPONSE, the call is
then passed to rxrpc_notify_socket_oob(), which takes the freed
socket's lock:

  BUG: KASAN: slab-use-after-free in rxrpc_input_conn_packet+0x3b2/0x820
  Read of size 8 at addr ff1100011b343328 by task krxrpcio/21029/1030
  ...
  BUG: KASAN: slab-use-after-free in _raw_spin_lock_irq+0x72/0xe0
  Write of size 4 at addr ff1100011b343308 by task krxrpcio/21029/1030
  Call Trace:
   _raw_spin_lock_irq+0x72/0xe0
   rxrpc_notify_socket_oob+0x54/0x3f0
   rxrpc_input_conn_packet+0x682/0x820
   rxrpc_input_packet_on_conn.part.0+0x5f4/0xc30
   rxrpc_input_packet.constprop.0+0x8a2/0xea0
   rxrpc_io_thread+0x944/0x1570

rxrpc_post_challenge() doesn't appear in the reports because the
compiler inlined it into rxrpc_input_conn_packet().

Depending on the freed socket's contents, rxrpc_notify_socket_oob()
can also call a function pointer obtained from it (sk->sk_data_ready()
or rx->app_ops->notify_oob()).  The use-after-free is deterministic, an
unprivileged process can trigger it, and since the attacker controls
when the CHALLENGE is sent, they can reclaim the freed memory first.
These conditions make the bug reliably exploitable to hijack kernel
control flow and escalate privileges.

Note that without rxgk the stranded call still leaks.  A client call
pins its connection, so destroying the local endpoint hits the BUG()
in rxrpc_destroy_client_conn_ids(); and for any stranded call, netns
teardown hangs in rxrpc_destroy_all_calls() waiting for it to be
freed.

Fix this by poking the call from rxrpc_abort_eproto(), as
rxrpc_abort_calls() already does.

Fixes: 03fc55adf876 ("rxrpc: Only disconnect calls in the I/O thread")
Cc: stable@vger.kernel.org
Signed-off-by: Juan Agustin Niccolini <juanagusnicco@gmail.com>
---
A deterministic reproducer for the KASAN report above is available on
request.  A working privilege escalation exploit was sent to
security@kernel.org on 20 October, and I can share it with the rxrpc
and netdev maintainers upon request.  The bug was first reported to
the rxrpc maintainers and the security team on 11 October.  rxrpc
autoloads on Ubuntu, Fedora, and Arch when any process opens an
AF_RXRPC socket.

 net/rxrpc/ar-internal.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 865f05fe37ab..31528b5e34cb 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1455,6 +1455,7 @@ static inline int rxrpc_abort_eproto(struct rxrpc_call *call,
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 
 	rxrpc_abort_call(call, sp->hdr.seq, abort_code, -EPROTO, why);
+	rxrpc_poke_call(call, rxrpc_call_poke_abort);
 	return -EPROTO;
 }
 

base-commit: fafbc4051123d5459ea6950899cec08ed946e278
-- 
2.53.0


                 reply	other threads:[~2026-11-06  1:15 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261106011550.59902-1-juanagusnicco@gmail.com \
    --to=juanagusnicco@gmail.com \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=jaltman@auristor.com \
    --cc=kuba@kernel.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.dionne@auristor.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®