Merge branch 'rxrpc-miscellaneous-fixes'

David Howells says:

====================
rxrpc: Miscellaneous fixes

Here are some miscellaneous AF_RXRPC fixes:

 (1) Make sure rxrpc_verify_data() allocates a buffer, even if the DATA
     packet being looked at is zero length to avoid potential NULL-pointer
     exceptions.

 (2) Don't move an OOB message (e.g. an RxGK CHALLENGE) off the receive
     queue onto the pending queue in recvmsg() if MSG_PEEK is specified.

 (3) Fix a potential UAF in rxgk_issue_challenge() in which a tracepoint
     refers to memory just freed by a different pointer.

 (4) Fix afs net namespace teardown to cancel the incoming call
     preallocation charger before we disable listening (which will delete
     the preallocation queue).

 (5) Fix rxrpc_kernel_charge_accept() to use the socket mutex to defend
     against listen(0)/shutdown simultaneously deleting the preallocation
     queue.
====================

Link: https://patch.msgid.link/20260609140911.838677-1-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-12 16:48:57 -07:00
commit 344873108c
4 changed files with 32 additions and 15 deletions

View File

@ -127,6 +127,7 @@ void afs_close_socket(struct afs_net *net)
{
_enter("");
cancel_work_sync(&net->charge_preallocation_work);
kernel_listen(net->socket, 0);
flush_workqueue(afs_async_calls);
@ -742,7 +743,7 @@ void afs_charge_preallocation(struct work_struct *work)
container_of(work, struct afs_net, charge_preallocation_work);
struct afs_call *call = net->spare_incoming_call;
for (;;) {
while (READ_ONCE(net->live)) {
if (!call) {
call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
if (!call)
@ -792,7 +793,8 @@ static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
if (!call->server)
trace_afs_cm_no_server(call, rxrpc_kernel_remote_srx(call->peer));
queue_work(afs_wq, &net->charge_preallocation_work);
if (net->live)
queue_work(afs_wq, &net->charge_preallocation_work);
}
/*

View File

@ -471,13 +471,26 @@ int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
unsigned long user_call_ID, gfp_t gfp,
unsigned int debug_id)
{
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
struct rxrpc_backlog *b = rx->backlog;
struct rxrpc_backlog *b;
struct rxrpc_sock *rx;
struct sock *sk;
int ret;
if (sock->sk->sk_state == RXRPC_CLOSE)
return -ESHUTDOWN;
sk = sock->sk;
rx = rxrpc_sk(sk);
return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
gfp, debug_id);
lock_sock(sk);
if (sk->sk_state != RXRPC_SERVER_LISTENING || !rx->backlog) {
ret = -ESHUTDOWN;
goto out;
}
b = rx->backlog;
ret = rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
gfp, debug_id);
out:
release_sock(sk);
return ret;
}
EXPORT_SYMBOL(rxrpc_kernel_charge_accept);

View File

@ -161,7 +161,7 @@ static int rxrpc_verify_data(struct rxrpc_call *call, struct sk_buff *skb)
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
int ret;
if (sp->len > call->rx_dec_bsize) {
if (sp->len > call->rx_dec_bsize || !call->rx_dec_buffer) {
/* Make sure we can hold a 1412-byte jumbo subpacket and make
* sure that the buffer size is aligned to a crypto blocksize.
*/
@ -262,12 +262,13 @@ static int rxrpc_recvmsg_oob(struct socket *sock, struct msghdr *msg,
break;
}
if (!(flags & MSG_PEEK))
if (!(flags & MSG_PEEK)) {
skb_unlink(skb, &rx->recvmsg_oobq);
if (need_response)
rxrpc_add_pending_oob(rx, skb);
else
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
if (need_response)
rxrpc_add_pending_oob(rx, skb);
else
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
}
return ret;
}

View File

@ -687,16 +687,17 @@ static int rxgk_issue_challenge(struct rxrpc_connection *conn)
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
if (ret > 0)
rxrpc_peer_mark_tx(conn->peer);
__free_page(page);
if (ret < 0) {
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
rxrpc_tx_point_rxgk_challenge);
__free_page(page);
return -EAGAIN;
}
trace_rxrpc_tx_packet(conn->debug_id, whdr,
rxrpc_tx_point_rxgk_challenge);
__free_page(page);
_leave(" = 0");
return 0;
}