From: Zihan Xi rxrpc_encap_rcv() moves encapsulated UDP packets onto the local RxRPC queue without preserving UDP receive-buffer accounting. A local AF_RXRPC service such as the AFS callback listener can therefore be flooded with RxRPC-shaped UDP packets until the local queue grows without bound and consumes large amounts of memory. Reaccount encapsulated packets against the UDP socket before queueing them on the RxRPC local queue and drop packets once the socket rcvbuf limit is reached. Clear sk_user_data under RCU protection and release the socket only after queued skbs are purged so the new skb ownership does not outlive the UDP socket. Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: Codex:gpt-5.4 Signed-off-by: Zihan Xi Signed-off-by: Ren Wei --- net/rxrpc/io_thread.c | 15 +++++++++++++-- net/rxrpc/local_object.c | 8 ++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c index dc5184a2f..85411a2d8 100644 --- a/net/rxrpc/io_thread.c +++ b/net/rxrpc/io_thread.c @@ -41,8 +41,6 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb) if (skb->tstamp == 0) skb->tstamp = ktime_get_real(); - skb->mark = RXRPC_SKB_MARK_PACKET; - rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv); rx_queue = &local->rx_queue; #ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY if (rxrpc_inject_rx_delay || @@ -52,6 +50,19 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb) } #endif + if (atomic_read(&udp_sk->sk_rmem_alloc) >= READ_ONCE(udp_sk->sk_rcvbuf) || + !sk_rmem_schedule(udp_sk, skb, skb->truesize)) { + atomic_inc(&udp_sk->sk_drops); + kfree_skb(skb); + return 0; + } + + skb->dev = NULL; + skb_set_owner_r(skb, udp_sk); + skb_dst_force(skb); + + skb->mark = RXRPC_SKB_MARK_PACKET; + rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv); skb_queue_tail(rx_queue, skb); wake_up_process(io_thread); return 0; diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 169f9dfda..6604f9f95 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c @@ -437,8 +437,8 @@ void rxrpc_destroy_local(struct rxrpc_local *local) if (socket) { local->socket = NULL; kernel_sock_shutdown(socket, SHUT_RDWR); - socket->sk->sk_user_data = NULL; - sock_release(socket); + rcu_assign_sk_user_data(socket->sk, NULL); + synchronize_rcu(); } /* At this point, there should be no more packets coming in to the @@ -448,6 +448,10 @@ void rxrpc_destroy_local(struct rxrpc_local *local) rxrpc_purge_queue(&local->rx_delay_queue); #endif rxrpc_purge_queue(&local->rx_queue); + + if (socket) + sock_release(socket); + rxrpc_purge_client_connections(local); page_frag_cache_drain(&local->tx_alloc); } -- 2.43.0