From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 38FC947AF6D; Thu, 20 Aug 2026 16:44:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787244241; cv=none; b=IMAta5DN6Fky3HtTDJQVgumrySXv0puSMfIbMzLx9zFu9lvT9A49oq30Bgm/ZU3mkdrB1ArkaII/vV74eN7iw2WAZPjPN5dBLqq/W6oyqc3StF+pdnYtAAAsgsG/6vTJEldNgw5nlrR2iq/F9ujXUor1RhqA26exgO4My7No1Kw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787244241; c=relaxed/simple; bh=lHqOp2VsA5ViTWPOcJ2FEWyBx3V4rVkTLS50okMyn+M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lpXKytV45eM0x2bQKYFmZo7H8JZk9cv/YW7PxRxduY3xd+JRafrkwrk2VGFz0JAwTgVtdyVOvx4r5vSnOQLTcEhk3wXfNLemoK69KZ1QTnc9o9b9vuDwz939S1T3KqDrG4Tk0yxv+BGJ1zxVO6P+QgujVXrniK6rVxAVrzUiVow= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=E5g2bWCu; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="E5g2bWCu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 682741F00A3A; Thu, 20 Aug 2026 16:43:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787244239; bh=czirxMCWvcXn3IR5Kicg/QYssullSNvc5bGm4UQi5e8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=E5g2bWCu6QPuzS0V4SuqV5ApmVQmZlKePZfpBZeXQufOzxzyLtRNaZf4K3BjdadiF kErrmiFpxhA0km+dF65ZWxY2/SViascLmFOKaqIZWZrA7IpLixAIDJhgS+e+zaVpRL 54+fbs9SpUAN1pmu5rpFFqUNkNohUwV+2bMPYn8E= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, David Howells , Jeffrey Altman , Marc Dionne , "Junvyyang, Tencent Zhuque Lab" , LePremierHomme , Simon Horman , linux-afs@lists.infradead.org, Jakub Kicinski , Sasha Levin Subject: [PATCH 5.10 062/235] rxrpc: Fix notification vs call-release vs recvmsg Date: Thu, 20 Aug 2026 16:54:58 +0200 Message-ID: <20260820145218.328175099@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260820145216.426568665@linuxfoundation.org> References: <20260820145216.426568665@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 5.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: David Howells [ Upstream commit 2fd895842d49c23137ae48252dd211e5d6d8a3ed ] When a call is released, rxrpc takes the spinlock and removes it from ->recvmsg_q in an effort to prevent racing recvmsg() invocations from seeing the same call. Now, rxrpc_recvmsg() only takes the spinlock when actually removing a call from the queue; it doesn't, however, take it in the lead up to that when it checks to see if the queue is empty. It *does* hold the socket lock, which prevents a recvmsg/recvmsg race - but this doesn't prevent sendmsg from ending the call because sendmsg() drops the socket lock and relies on the call->user_mutex. Fix this by firstly removing the bit in rxrpc_release_call() that dequeues the released call and, instead, rely on recvmsg() to simply discard released calls (done in a preceding fix). Secondly, rxrpc_notify_socket() is abandoned if the call is already marked as released rather than trying to be clever by setting both pointers in call->recvmsg_link to NULL to trick list_empty(). This isn't perfect and can still race, resulting in a released call on the queue, but recvmsg() will now clean that up. Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both") Signed-off-by: David Howells Reviewed-by: Jeffrey Altman cc: Marc Dionne cc: Junvyyang, Tencent Zhuque Lab cc: LePremierHomme cc: Simon Horman cc: linux-afs@lists.infradead.org Link: https://patch.msgid.link/20250717074350.3767366-4-dhowells@redhat.com Signed-off-by: Jakub Kicinski Stable-dep-of: e66f8f32f501 ("rxrpc: Fix socket notification race") Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/rxrpc/call_object.c | 27 +++++++++++---------------- net/rxrpc/recvmsg.c | 4 ++++ 2 files changed, 15 insertions(+), 16 deletions(-) --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -529,7 +529,6 @@ void rxrpc_release_call(struct rxrpc_soc { const void *here = __builtin_return_address(0); struct rxrpc_connection *conn = call->conn; - bool put = false; _enter("{%d,%d}", call->debug_id, refcount_read(&call->ref)); @@ -547,23 +546,13 @@ void rxrpc_release_call(struct rxrpc_soc rxrpc_put_call_slot(call); rxrpc_delete_call_timer(call); - /* Make sure we don't get any more notifications */ + /* Note that at this point, the call may still be on or may have been + * added back on to the socket receive queue. recvmsg() must discard + * released calls. The CALL_RELEASED flag should prevent further + * notifications. + */ write_lock_bh(&rx->recvmsg_lock); - - if (!list_empty(&call->recvmsg_link)) { - _debug("unlinking once-pending call %p { e=%lx f=%lx }", - call, call->events, call->flags); - list_del(&call->recvmsg_link); - put = true; - } - - /* list_empty() must return false in rxrpc_notify_socket() */ - call->recvmsg_link.next = NULL; - call->recvmsg_link.prev = NULL; - write_unlock_bh(&rx->recvmsg_lock); - if (put) - rxrpc_put_call(call, rxrpc_call_put); write_lock(&rx->call_lock); @@ -612,6 +601,12 @@ void rxrpc_release_calls_on_socket(struc rxrpc_put_call(call, rxrpc_call_put); } + while ((call = list_first_entry_or_null(&rx->recvmsg_q, + struct rxrpc_call, recvmsg_link))) { + list_del_init(&call->recvmsg_link); + rxrpc_put_call(call, rxrpc_call_put); + } + _leave(""); } --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -29,6 +29,10 @@ void rxrpc_notify_socket(struct rxrpc_ca if (!list_empty(&call->recvmsg_link)) return; + if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { + rxrpc_see_call(call); + return; + } rcu_read_lock();