From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 258773A544F for ; Mon, 13 Jul 2026 08:10:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930245; cv=none; b=R2K0JshjI1JuPjCh8o8F/R2qdJ8uFGQtKBnbR/3PiIGJQnoi64WnFunRqemQYhbQpW1xmWWZHf1T/kdBYIKs1McLjoNNWqh6bcYOslO4RD1eqlE/g2xYGiWkCHuLW/ugqMdpl7Qcc+dYprq+CEDiTsprfRXKWjFRqtK1v036wvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930245; c=relaxed/simple; bh=xyALdxjU1TW9/Ki7zm9C1YzWa0+d5DiMlT8No6I9Mes=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PAbjL+2O/jeqgJw1ng6h5KoO2bRRjZhI6GDa60e2J5PlEvbK8dsbR6RH47+BRLJOnqU+bv2Jxysy8EflLjOQdDZMNlM/VSDFgsPlxBFaI1bAALLTLwGULoXQrIb7zQpO/a9/wiRBB/D+4msuH7rRF/af+udKeWPLRjQxI2SpD9o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=cwv01f+3; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="cwv01f+3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930243; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BOWCDRxNUNYjz7orMFcedmQGQ2BN2L8e1lJ1KDGIQsg=; b=cwv01f+3lsiITa5abzYFGnCh+AR/MAvpjaGJMbUTwkfurrWWEpTLOmjODDQUn4VTtz3mQH FGsSvs4pTtv+5SkERarFtZOgiKcaT5AVsttFx0JlryUp2yNKcjnzaeZVSRPgLvMyiDFeII RY+FZVt4EGPbDz5h+gDAGzLHiDeAMrE= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-649-YGhgeM7mPeu8Ippvzz01gQ-1; Mon, 13 Jul 2026 04:10:36 -0400 X-MC-Unique: YGhgeM7mPeu8Ippvzz01gQ-1 X-Mimecast-MFC-AGG-ID: YGhgeM7mPeu8Ippvzz01gQ_1783930235 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E9AB21955D9C; Mon, 13 Jul 2026 08:10:34 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3F83C180028B; Mon, 13 Jul 2026 08:10:31 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman Subject: [PATCH net v3 01/14] rxrpc: Fix sendmsg to not return an error if last packet queued Date: Mon, 13 Jul 2026 09:10:07 +0100 Message-ID: <20260713081022.2186481-2-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Fix AF_RXRPC sendmsg() so that it doesn't return an error if it has successfully queued the last packet of a call, but the call has seen to have completed after it did that. Rather, leave it to recvmsg() to report the completion (which it will do anyway). The problem with trying to report the error twice is that the caller may try to clean up the dead call twice. Fixes: d41b3f5b9688 ("rxrpc: Wrap accesses to get call state to put the bar= rier in one place") Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org --- net/rxrpc/sendmsg.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index ed2c9a51005a..4c754f78ece9 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -453,9 +453,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, =20 success: ret =3D copied; - if (rxrpc_call_is_complete(call) && - call->error < 0) - ret =3D call->error; out: call->tx_pending =3D txb; _leave(" =3D %d", ret); @@ -467,8 +464,14 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, return call->error; =20 maybe_error: - if (copied) + if (copied) { + if (rxrpc_call_is_complete(call) && + call->error < 0) { + ret =3D call->error; + goto out; + } goto success; + } goto out; =20 efault: From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 1A49D36897C for ; Mon, 13 Jul 2026 08:10:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930245; cv=none; b=Cmp3bEAYVhOpeolOGnvi9ONEEAVxMnZ58nSzGN6jAXi1OVoJahnOYVIbSxhWj3bwbw+KEnpvXtz9GbD3y1za0Xg0lYqQJgOX4a2IZVnbQZP9tXQEnsn+Ll7wVMiLObwMdUT6LkAty8PiziKZdLRW2I9FpTkW5s8QgwI/MpoSKeI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930245; c=relaxed/simple; bh=E5WS46j5a8G17EdBUcF4rWwBW8nW3IbIBrOVF96DvQY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HpHm/+PLZ7zePYRwAfUbyCK2+Ruj6jAmLOnBDzLqqm3Xpt/HkrQTYntoa5XYozzN1p7cSjux6fuH9g3sevNnbYvz9de2tJm8hOIjbHUandJfNmUjSxY9fJ3iwXQApe1XieQuZj2t3Icq6x6jZ4QVfsu79O0U7FWTG3RWW+lGS3U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CyobyZc3; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CyobyZc3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930243; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SgpV4kjwvH55LZvzMLmX7XWaBZ5UY8VXhuMtFgykJ6U=; b=CyobyZc3VEdkokRhNVgvZsfVcEivh+cxzPCY+rIgdXC3HEx8rcLMfX1Xp4YTSNCFD2eSXc 3eoaYz4zelKwdiZIGSv+NOURoID/n1d8vG2I4MiwSfZmY8/8qrSIV9tuk9v1WWTsQU13q/ 8YPEC065TG81qfRWcpXGksmHY2yIDic= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-167-dp_kmYWCOqKMYhXkwz-ECg-1; Mon, 13 Jul 2026 04:10:41 -0400 X-MC-Unique: dp_kmYWCOqKMYhXkwz-ECg-1 X-Mimecast-MFC-AGG-ID: dp_kmYWCOqKMYhXkwz-ECg_1783930240 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 114BA1805A0E; Mon, 13 Jul 2026 08:10:40 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9B8EF1800348; Mon, 13 Jul 2026 08:10:36 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , stable@kernel.org Subject: [PATCH net v3 02/14] afs: Fix UAF when sending a message Date: Mon, 13 Jul 2026 09:10:08 +0100 Message-ID: <20260713081022.2186481-3-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" In afs_make_call(), there's a race with async call reception and destruction. If a call is dispatched that doesn't have call->write_iter set (used to specify the data content for FS.StoreData), then the first rxrpc_kernel_send_data() will not set MSG_MORE in the msghdr. Once rxrpc_send_data() queues the last request packet, the response could come in at any time and cause the call to be completed and put. However, afs_make_call() will look at the call again to see it ->write_iter should be handled - something it's only allowed to do if it has its own ref on the call. Whilst this is the case for synchronous calls, it isn't true for async calls such as FS.FetchData. generic/650 plays games with randomly taking CPUs offline, and can interject a significant delay such that the call is deallocated before afs_make_call() gets to check call->write_iter - and a UAF ensues (caught by KASAN). BUG: KASAN: slab-use-after-free in afs_make_call+0x1c90/0x2210 [kafs] Read of size 8 at addr ffff888035e050e8 by task fsstress/1409 Fix this by caching the call->write_iter and call->debug_id so that neither variable needs to be accessed after the first send. Fixes: eddf51f2bb2c ("afs: Make {Y,}FS.FetchData an asynchronous operation") Reported-by: Marc Dionne Signed-off-by: David Howells cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- fs/afs/rxrpc.c | 12 ++++++++---- include/trace/events/afs.h | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index d82916657a3d..06c711c75f55 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -347,7 +347,9 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) struct rxrpc_call *rxcall; struct msghdr msg; struct kvec iov[1]; + unsigned int debug_id =3D call->debug_id; size_t len; + bool write_iter =3D call->write_iter; s64 tx_total_len; int ret; =20 @@ -410,7 +412,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, call->request_size); msg.msg_control =3D NULL; msg.msg_controllen =3D 0; - msg.msg_flags =3D MSG_WAITALL | (call->write_iter ? MSG_MORE : 0); + msg.msg_flags =3D MSG_WAITALL | (write_iter ? MSG_MORE : 0); =20 ret =3D rxrpc_kernel_send_data(call->net->socket, rxcall, &msg, call->request_size, @@ -418,7 +420,9 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) if (ret < 0) goto error_do_abort; =20 - if (call->write_iter) { + /* We lost our ref on call if MSG_MORE was not set and ret >=3D 0. */ + + if (write_iter) { msg.msg_iter =3D *call->write_iter; msg.msg_flags &=3D ~MSG_MORE; trace_afs_send_data(call, &msg); @@ -427,9 +431,9 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) call->rxcall, &msg, iov_iter_count(&msg.msg_iter), afs_notify_end_request_tx); - *call->write_iter =3D msg.msg_iter; + /* We lost our ref on call if ret >=3D 0. */ =20 - trace_afs_sent_data(call, &msg, ret); + trace_afs_sent_data(debug_id, &msg, ret); if (ret < 0) goto error_do_abort; } diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 1b3c48b5591d..cf7218efb861 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -937,9 +937,9 @@ TRACE_EVENT(afs_send_data, ); =20 TRACE_EVENT(afs_sent_data, - TP_PROTO(struct afs_call *call, struct msghdr *msg, int ret), + TP_PROTO(unsigned int call_debug_id, struct msghdr *msg, int ret), =20 - TP_ARGS(call, msg, ret), + TP_ARGS(call_debug_id, msg, ret), =20 TP_STRUCT__entry( __field(unsigned int, call) @@ -949,7 +949,7 @@ TRACE_EVENT(afs_sent_data, ), =20 TP_fast_assign( - __entry->call =3D call->debug_id; + __entry->call =3D call_debug_id; __entry->ret =3D ret; __entry->offset =3D msg->msg_iter.xarray_start + msg->msg_iter.iov_o= ffset; __entry->count =3D iov_iter_count(&msg->msg_iter); From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 297F03A545E for ; Mon, 13 Jul 2026 08:10:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930253; cv=none; b=UtbttFB3YlDHmvRp/ghHbJTwVe7Z6KMJynj4lyQBAI9Oh5N1W2B9/DtWZD8kq5Bte2yvEC6skwQQ5m8sXZMsABZdMHcoVcGVlD0WDT8SSxEbi31UoGRguZnzQQlQDLcByEsUJjIlS84bQSOOeLPeuG67K3ESIPUtCw9PEZmdRUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930253; c=relaxed/simple; bh=Jwc5fJ9xrRVYizICnQ5yAooHRkTMnng50fBKpa7UdCY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iOxQYoOmC28XvDtWNBPKi24b9FPEDzMkchIlCog7Heeh7VUx7TfoUn1ol3AN5gvh8ZJ+G2mevguU3Pw55yc6mtEL2/ThUI5u8uOQ8t3AcKRaNl8t56xS4f46Ksg3VU5/WQjYNMgFLMoF3oSLvRf4/lvarjqfrqA0lsF0N+vM2e4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=KVnR5rTq; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="KVnR5rTq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CJbYCTF46Xtoig1WDNcBh4wAMxmGdrepxhiioBEnY2E=; b=KVnR5rTqkQ5Pqyjqwg+Ud3Wammt3f0mcdcaUO6hQ8XOEgks2Rc6TY8FIrOBfWjKbHJS9+T qWu22uoTcdeC5xH9Ym5HVKEtz5QxUr3wLG/nn9e9HxIsRXbALmZ4nFzsCxz3zPjbHAj5Zm 7jqUtfw6AqgeNlyYW0geB+xWww32h9Y= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-515-JZFpb0L8P4aVcdFTGB51KQ-1; Mon, 13 Jul 2026 04:10:46 -0400 X-MC-Unique: JZFpb0L8P4aVcdFTGB51KQ-1 X-Mimecast-MFC-AGG-ID: JZFpb0L8P4aVcdFTGB51KQ_1783930245 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 133851955F21; Mon, 13 Jul 2026 08:10:45 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B4FBF195394B; Mon, 13 Jul 2026 08:10:41 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , stable@kernel.org Subject: [PATCH net v3 03/14] afs: Fix afs_fs_fetch_data() to set call->async Date: Mon, 13 Jul 2026 09:10:09 +0100 Message-ID: <20260713081022.2186481-4-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Fix afs_fs_fetch_data() to set call->async on an async operation as does afs_fs_fetch_data64(). Fixes: eddf51f2bb2c ("afs: Make {Y,}FS.FetchData an asynchronous operation") Link: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- fs/afs/fsclient.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index a2ffd60889f8..626e1d37b915 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -477,6 +477,9 @@ void afs_fs_fetch_data(struct afs_operation *op) if (!call) return afs_op_nomem(op); =20 + if (op->flags & AFS_OPERATION_ASYNC) + call->async =3D true; + /* marshall the parameters */ bp =3D call->request; bp[0] =3D htonl(FSFETCHDATA); From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 A9A023A5E78 for ; Mon, 13 Jul 2026 08:10:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930258; cv=none; b=hCJWTGT76VjfMmsfrXGX1GoOMeIFxEYTqMqNdTQ7TKnSCg/rDWUNyq1ifSMPgNceJnR3pj9Uq89qcAxmeQr8FVQ3ZWd7BS1SfSJCXGpZ0IkfcVaL1KBUraaT4bNdWhx/FhBDElFa/cpynxO8Yy/WY6YyjO5SKPIIn2xhZnalwYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930258; c=relaxed/simple; bh=V4XZIwt4gt9pplDEMEB/pkTeQMmDUhFKeT3JiltPjx8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B4QiaNLGSinh4ieWNmksbec1dG59dZ2Tnsbvz6Lh7NNjJL3SuiyQLlqd41TL3gB97hrh8OSCG2RVtOe6L8Cyt/DzQzXvbVnZzTj+tOdjQL21ViXM3tT7BzpYL6dZl2XGofJ7GMHLDa4524cg5gtAhSTAP5u87GmS3xvbiPIenQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=UnBBt3nZ; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="UnBBt3nZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930254; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OEMH5m6huYYvtFTie5OCy8ftQODB3i6QPytEwHtas9k=; b=UnBBt3nZSuzKjDWKvQ5pEv1Q3b215kaMy2Axz8ZMqU1mjcRjZeibU/4fXqiXr2DOr4bBL5 NnebOEZHRzyBN30BOHKqbTYk/itCshqcTs9VjfnlUzNP6aOjh22/iYUOth36+CAV6FUR4l 7GVs3OxQws87KgoB34PyRiEzFjmLJko= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-21-nkQeFBYpPx-SseJzutMcbw-1; Mon, 13 Jul 2026 04:10:51 -0400 X-MC-Unique: nkQeFBYpPx-SseJzutMcbw-1 X-Mimecast-MFC-AGG-ID: nkQeFBYpPx-SseJzutMcbw_1783930249 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D1CDF180064A; Mon, 13 Jul 2026 08:10:49 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BD04B1800348; Mon, 13 Jul 2026 08:10:46 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 04/14] rxrpc: Fix packet encryption error handling Date: Mon, 13 Jul 2026 09:10:10 +0100 Message-ID: <20260713081022.2186481-5-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" In rxrpc_send_data(), if ->secure_packet() returns an error, the code currently just jumps to out: and returns the error to the app on the assumption that any error returned by this is automatically fatal for the call, and may even have corrupted the transmission queue - but leaving it to userspace to deal with. Nothing stops the application from retrying the sendmsg(), which will try to encrypt the buffer again, and might succeed with a corrupt buffer. Fix rxrpc_send_data() in the following ways: (1) If -ENOMEM is returned, assume we never got as far as the encryption and that the operation is retryable. In which case, jump to maybe_error. (2) If any other error occurs, set the TX_ERROR flag on the call and return that error directly; on all subsequent attempts to add data to the call, return -EIO. The app must then abort the call to get rid of it (this allows the app to choose the abort code to use). Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by u= serspace and kernel both") Closes: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40r= edhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- include/trace/events/rxrpc.h | 1 + net/rxrpc/ar-internal.h | 1 + net/rxrpc/sendmsg.c | 25 ++++++++++++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 704a10de6670..8f3e3967885a 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -148,6 +148,7 @@ EM(rxrpc_eproto_wrong_security, "wrong-sec") \ EM(rxrpc_recvmsg_excess_data, "recvmsg-excess") \ EM(rxrpc_recvmsg_short_data, "recvmsg-short") \ + EM(rxrpc_sendmsg_tx_error, "tx-error") \ E_(rxrpc_sendmsg_late_send, "sendmsg-late") =20 #define rxrpc_call_poke_traces \ diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index ce946b0a03e2..b6e7e8c5e96f 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -642,6 +642,7 @@ enum rxrpc_call_flag { RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at rxtx_top) */ RXRPC_CALL_TX_ALL_ACKED, /* Last packet has been hard-acked */ RXRPC_CALL_TX_NO_MORE, /* No more data to transmit (MSG_MORE deasserted)= */ + RXRPC_CALL_TX_ERROR, /* Terminal error; call needs abort */ RXRPC_CALL_SEND_PING, /* A ping will need to be sent */ RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */ RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */ diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 4c754f78ece9..d5060fd9631a 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -330,12 +330,18 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, bool more =3D msg->msg_flags & MSG_MORE; int ret, copied =3D 0; =20 - if (test_bit(RXRPC_CALL_TX_NO_MORE, &call->flags)) { + if (unlikely(test_bit(RXRPC_CALL_TX_NO_MORE, &call->flags))) { trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send, call->cid, call->call_id, call->rx_consumed, 0, -EPROTO); return -EPROTO; } + if (unlikely(test_bit(RXRPC_CALL_TX_ERROR, &call->flags))) { + trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_tx_error, + call->cid, call->call_id, call->rx_consumed, + 0, -EIO); + return -EIO; + } =20 timeo =3D sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); =20 @@ -440,12 +446,21 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, /* add the packet to the send queue if it's now full */ if (!txb->space || (msg_data_left(msg) =3D=3D 0 && !more)) { - if (msg_data_left(msg) =3D=3D 0 && !more) - txb->flags |=3D RXRPC_LAST_PACKET; - + /* Do any required crypto. If this fails, it could + * have corrupted the txbuf content with a partial + * encrypt. Assume that ENOMEM is retryable, but + * everything else is terminal. + */ ret =3D call->security->secure_packet(call, txb); - if (ret < 0) + if (ret < 0) { + if (ret =3D=3D -ENOMEM) + goto maybe_error; + set_bit(RXRPC_CALL_TX_ERROR, &call->flags); goto out; + } + + if (msg_data_left(msg) =3D=3D 0 && !more) + txb->flags |=3D RXRPC_LAST_PACKET; rxrpc_queue_packet(rx, call, txb, notify_end_tx); txb =3D NULL; } From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 E2E823A5E78 for ; Mon, 13 Jul 2026 08:11:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930263; cv=none; b=Gv0jTdT7gTkRHsxCFmJXr/doR7Ng83RyfBX0NsV750Ejs1fIlAFdIYELJzl5ujCTRvK2zOBrmxWTneaVDtykRwGXabivyJdoglSR1hbXXDwscE/rBf3lran9ZfQfdm95nKRX+RqZRgiikAGsnI5mH1wwP1igyoG4vlzLOKxWvhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930263; c=relaxed/simple; bh=RqEZ8V3VTBLUYMWessvmE35+orqVW6T6gXuF1INaQHs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nV35ojogoDo4V5/d/4mvJzowWZGxeOIRISGUj4mjVRbxcm3iGkbP/lyCalskfUKnSdURgAv1IeTk2CTFJKPKb7/pIbD+sItnkrt5T1x1oYjRvHBBCBcCb2gpsFbtJfpfDq1J0yxGCcmDISC/33b/iEg429kP1YkuRqMlchCFdE8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=gQtcIdCI; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gQtcIdCI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930260; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5tnXvZhH3Uv8RMIWKCx6J8r5QB8JHDWA9/+oQzZb+wc=; b=gQtcIdCItNur2BabSkokYMhhp94oAcQa6P1x49xD2/pq7N3MAxS1XbokQSrzFjFsNa7fJv ETV615l+y/JeFb4NM/bksnKpbhb7BH6AqEgN1hRrwFWgTR0lxeJoURJqK8VN54hkYPkBF3 6CYbr8J2S8GOviOnJoYpHWuLh1iIq8g= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-664-a0llZpPCNQmF2I-erdN-sg-1; Mon, 13 Jul 2026 04:10:56 -0400 X-MC-Unique: a0llZpPCNQmF2I-erdN-sg-1 X-Mimecast-MFC-AGG-ID: a0llZpPCNQmF2I-erdN-sg_1783930255 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DEA4C1956066; Mon, 13 Jul 2026 08:10:54 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6FF9D36919; Mon, 13 Jul 2026 08:10:51 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 05/14] rxrpc: Fix update of call->tx_pending without holding lock Date: Mon, 13 Jul 2026 09:10:11 +0100 Message-ID: <20260713081022.2186481-6-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" Currently, rxrpc_send_data() updates call->tx_pending just before it returns - but it won't be holding the call->lock when it does this if a wait was interrupted by a signal. This would allow a parallel sendmsg() to race. Further, both the callers of rxrpc_send_data() call it with the lock held, and then it returns an indication through the parameter list to say whether it has dropped the lock or not - after which the callers both just drop the lock if it's still held. Fix this by: (1) Moving the release of call->lock down into rxrpc_send_data() and get rid of the indicator parameter. This makes it easier to see where the lock is held. (2) Make the wait_for_space path move the value in txb back into call->tx_pending before dropping the lock prior to the wait. (3) After waiting, if the attempt to reacquire the mutex is interrupted, just return directly there rather than going to out_unlock Fixes: b0f571ecd794 ("rxrpc: Fix locking in rxrpc's sendmsg") Closes: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40r= edhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- net/rxrpc/sendmsg.c | 52 +++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index d5060fd9631a..71343998b87d 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -320,8 +320,8 @@ static int rxrpc_alloc_txqueue(struct sock *sk, struct = rxrpc_call *call) static int rxrpc_send_data(struct rxrpc_sock *rx, struct rxrpc_call *call, struct msghdr *msg, size_t len, - rxrpc_notify_end_tx_t notify_end_tx, - bool *_dropped_lock) + rxrpc_notify_end_tx_t notify_end_tx) + __releases(&call->user_mutex) { struct rxrpc_txbuf *txb; struct sock *sk =3D &rx->sk; @@ -334,25 +334,27 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send, call->cid, call->call_id, call->rx_consumed, 0, -EPROTO); - return -EPROTO; + ret =3D -EPROTO; + goto out_unlock; } if (unlikely(test_bit(RXRPC_CALL_TX_ERROR, &call->flags))) { trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_tx_error, call->cid, call->call_id, call->rx_consumed, 0, -EIO); - return -EIO; + ret =3D -EIO; + goto out_unlock; } =20 timeo =3D sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); =20 ret =3D rxrpc_wait_to_be_connected(call, &timeo); if (ret < 0) - return ret; + goto out_unlock; =20 if (call->conn->state =3D=3D RXRPC_CONN_CLIENT_UNSECURED) { ret =3D rxrpc_init_client_conn_security(call->conn); if (ret < 0) - return ret; + goto out_unlock; } =20 /* this should be in poll */ @@ -456,7 +458,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, if (ret =3D=3D -ENOMEM) goto maybe_error; set_bit(RXRPC_CALL_TX_ERROR, &call->flags); - goto out; + goto out_txb; } =20 if (msg_data_left(msg) =3D=3D 0 && !more) @@ -468,51 +470,58 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, =20 success: ret =3D copied; -out: +out_txb: call->tx_pending =3D txb; +out_unlock: + mutex_unlock(&call->user_mutex); _leave(" =3D %d", ret); return ret; =20 call_terminated: rxrpc_put_txbuf(txb, rxrpc_txbuf_put_send_aborted); - _leave(" =3D %d", call->error); - return call->error; + call->tx_pending =3D NULL; + ret =3D call->error; + goto out_unlock; =20 maybe_error: if (copied) { if (rxrpc_call_is_complete(call) && call->error < 0) { ret =3D call->error; - goto out; + goto out_unlock; } goto success; } - goto out; + goto out_txb; =20 efault: ret =3D -EFAULT; - goto out; + goto out_txb; =20 wait_for_space: ret =3D -EAGAIN; if (msg->msg_flags & MSG_DONTWAIT) goto maybe_error; + call->tx_pending =3D txb; + txb =3D NULL; mutex_unlock(&call->user_mutex); - *_dropped_lock =3D true; + ret =3D rxrpc_wait_for_tx_window(rx, call, &timeo, msg->msg_flags & MSG_WAITALL); if (ret < 0) - goto maybe_error; + goto out_nolock; if (call->interruptibility =3D=3D RXRPC_INTERRUPTIBLE) { if (mutex_lock_interruptible(&call->user_mutex) < 0) { ret =3D sock_intr_errno(timeo); - goto maybe_error; + goto out_nolock; } } else { mutex_lock(&call->user_mutex); } - *_dropped_lock =3D false; goto reload; +out_nolock: + _leave(" =3D %d [intr]", ret); + return copied ?: ret; } =20 /* @@ -787,8 +796,8 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msgh= dr *msg, size_t len) ret =3D 0; break; case RXRPC_CMD_SEND_DATA: - ret =3D rxrpc_send_data(rx, call, msg, len, NULL, &dropped_lock); - break; + ret =3D rxrpc_send_data(rx, call, msg, len, NULL); + goto error_put; default: ret =3D -EINVAL; break; @@ -826,7 +835,6 @@ int rxrpc_kernel_send_data(struct socket *sock, struct = rxrpc_call *call, struct msghdr *msg, size_t len, rxrpc_notify_end_tx_t notify_end_tx) { - bool dropped_lock =3D false; int ret; =20 _enter("{%d},", call->debug_id); @@ -837,12 +845,10 @@ int rxrpc_kernel_send_data(struct socket *sock, struc= t rxrpc_call *call, mutex_lock(&call->user_mutex); =20 ret =3D rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len, - notify_end_tx, &dropped_lock); + notify_end_tx); if (ret =3D=3D -ESHUTDOWN) ret =3D call->error; =20 - if (!dropped_lock) - mutex_unlock(&call->user_mutex); _leave(" =3D %d", ret); return ret; } From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 D329F3AFB12 for ; Mon, 13 Jul 2026 08:11:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930267; cv=none; b=JZzKQXn2+2fuNauz9x8w/MdwWmloR8KxYx+jVi0+OyYMCK1YpJ65UCpuxX1DiGKFWh4VUU3bkoHmL+Uqei0QCJ44u6MpjkPPvcBKCBvQ+o+9S4PhtAO9bzjknuu6XZDHKjuFc4l1pcPkdtEqlJ7zQRLiYQrmIpRpJKMVc4YEJZk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930267; c=relaxed/simple; bh=LLqegErpiwnNJz+6QEiPVr0B0jHHttmhiT2gIzb7tbI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h/Ir3LF2wF0wy3hUhzsLVleoFHYh/xS0rxWwx0e2QkniypVlkWVhOgplPQPXVPKSDmaPUOuZFjHZ2mS2HR9S5I0THXZZ9S8ldFtRZJM2mT6pX1ylP1X8lBojjv/Uwdkl23VHVR9VdEukQ9Y7l4envi6wOfEZp1N4am4rMiG8Dcc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=IFMWcV1j; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IFMWcV1j" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930264; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=n0U90slAaEmIBgfeuUR2Wm/d5X06U5sN8cTBSeFBj2M=; b=IFMWcV1j2Ky8RNuh4IxtYraKtFXd3QTO+3W+ji9Cws9Aijk0BZLTHO4uhMPA2KzSih21l0 8KLuRrKKK+8ZmFNzmF9dgFLEhDuNUYSJDUbi+5SGP0XypB5nSSad9aJL736w+6GzHPZZEE w+CJ7hI4+M0Avm6yEneLFrlcFNISHT0= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-650-z-U9RDirNlKfwNyEruPWoQ-1; Mon, 13 Jul 2026 04:11:01 -0400 X-MC-Unique: z-U9RDirNlKfwNyEruPWoQ-1 X-Mimecast-MFC-AGG-ID: z-U9RDirNlKfwNyEruPWoQ_1783930259 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A1FEA1955EBC; Mon, 13 Jul 2026 08:10:59 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 92E2118005A0; Mon, 13 Jul 2026 08:10:56 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 06/14] rxrpc: Fix generation of notifications after call completion Date: Mon, 13 Jul 2026 09:10:12 +0100 Message-ID: <20260713081022.2186481-7-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" AF_RXRPC may generate a notification to the application after a call has completed because it generates one notification when rxrpc_input_split_jumbo() queues the final packet and completes the call and then generates another when rxrpc_input_split_jumbo() does the aggregated data receive notification at the end of the function. This might cause the AFS filesystem to malfunction because it tries to queue the afs_call for processing an extra time. Most of the time this happens quickly enough that the second queue_work skips, but sometimes this means that the call work may happen a second time with implications for afs_call lifetime management. Fix this by: (1) Create a lighter version of rxrpc_notify_socket() that's just used to requeue a call for rxrpc_recvmsg() without creating another notification. (2) Move rxrpc_notify_socket() to call_state.c and rename it to __rxrpc_notify_socket(). (3) Create a wrapper called rxrpc_notify_socket() that skips the notification if a call is completed. (4) Make rxrpc_set_call_completion() call __rxrpc_notify_socket() to avoid the skip-if-completed check. Fixes: 2d1faf7a0ca3 ("rxrpc: Simplify skbuff accounting in receive path") Signed-off-by: David Howells cc: Marc Dionne cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- include/trace/events/rxrpc.h | 1 + net/rxrpc/call_state.c | 57 +++++++++++++++++++++++++++++++++++- net/rxrpc/recvmsg.c | 42 +++++++++----------------- 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 8f3e3967885a..d7c7b04d69fc 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -343,6 +343,7 @@ EM(rxrpc_call_see_distribute_error, "SEE dist-err") \ EM(rxrpc_call_see_input, "SEE input ") \ EM(rxrpc_call_see_notify_released, "SEE nfy-rlsd") \ + EM(rxrpc_call_see_notify_skipped, "SEE nfy-skip") \ EM(rxrpc_call_see_recvmsg, "SEE recvmsg ") \ EM(rxrpc_call_see_recvmsg_requeue, "SEE recv-rqu") \ EM(rxrpc_call_see_recvmsg_requeue_first, "SEE recv-rqF") \ diff --git a/net/rxrpc/call_state.c b/net/rxrpc/call_state.c index 6afb54373ebb..6e402312e145 100644 --- a/net/rxrpc/call_state.c +++ b/net/rxrpc/call_state.c @@ -7,6 +7,61 @@ =20 #include "ar-internal.h" =20 +/* + * Post a call for attention by the socket or kernel service. Further + * notifications are suppressed by putting recvmsg_link on a dummy queue. + */ +static void __rxrpc_notify_socket(struct rxrpc_call *call) +{ + struct rxrpc_sock *rx; + struct sock *sk; + + if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { + rxrpc_see_call(call, rxrpc_call_see_notify_released); + return; + } + + rcu_read_lock(); + + rx =3D rcu_dereference(call->socket); + sk =3D &rx->sk; + if (rx && sk->sk_state < RXRPC_CLOSE) { + if (call->notify_rx) { + spin_lock_irq(&call->notify_lock); + call->notify_rx(sk, call, call->user_call_ID); + spin_unlock_irq(&call->notify_lock); + } else { + spin_lock_irq(&rx->recvmsg_lock); + if (list_empty(&call->recvmsg_link)) { + rxrpc_get_call(call, rxrpc_call_get_notify_socket); + list_add_tail(&call->recvmsg_link, &rx->recvmsg_q); + } + spin_unlock_irq(&rx->recvmsg_lock); + + if (!sock_flag(sk, SOCK_DEAD)) { + _debug("call %ps", sk->sk_data_ready); + sk->sk_data_ready(sk); + } + } + } + + rcu_read_unlock(); +} + +/* + * Post a call for attention by the socket or kernel service. Further + * notifications are suppressed by putting recvmsg_link on a dummy queue. + */ +void rxrpc_notify_socket(struct rxrpc_call *call) +{ + if (rxrpc_call_is_complete(call)) { + rxrpc_see_call(call, rxrpc_call_see_notify_skipped); + return; + } + + __rxrpc_notify_socket(call); +} + /* * Transition a call to the complete state. */ @@ -25,7 +80,7 @@ bool rxrpc_set_call_completion(struct rxrpc_call *call, rxrpc_set_call_state(call, RXRPC_CALL_COMPLETE); trace_rxrpc_call_complete(call); wake_up(&call->waitq); - rxrpc_notify_socket(call); + __rxrpc_notify_socket(call); return true; } =20 diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index efcba4b2e74f..28b2148b5693 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -17,13 +17,12 @@ #include "ar-internal.h" =20 /* - * Post a call for attention by the socket or kernel service. Further - * notifications are suppressed by putting recvmsg_link on a dummy queue. + * Requeue a call for recvmsg() to pick up. */ -void rxrpc_notify_socket(struct rxrpc_call *call) +static void rxrpc_requeue_call(struct socket *sock, struct rxrpc_call *cal= l) { - struct rxrpc_sock *rx; - struct sock *sk; + struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); + struct sock *sk =3D &rx->sk; =20 _enter("%d", call->debug_id); =20 @@ -32,31 +31,18 @@ void rxrpc_notify_socket(struct rxrpc_call *call) return; } =20 - rcu_read_lock(); - - rx =3D rcu_dereference(call->socket); - sk =3D &rx->sk; - if (rx && sk->sk_state < RXRPC_CLOSE) { - if (call->notify_rx) { - spin_lock_irq(&call->notify_lock); - call->notify_rx(sk, call, call->user_call_ID); - spin_unlock_irq(&call->notify_lock); - } else { - spin_lock_irq(&rx->recvmsg_lock); - if (list_empty(&call->recvmsg_link)) { - rxrpc_get_call(call, rxrpc_call_get_notify_socket); - list_add_tail(&call->recvmsg_link, &rx->recvmsg_q); - } - spin_unlock_irq(&rx->recvmsg_lock); + spin_lock_irq(&rx->recvmsg_lock); + if (list_empty(&call->recvmsg_link)) { + rxrpc_get_call(call, rxrpc_call_get_notify_socket); + list_add_tail(&call->recvmsg_link, &rx->recvmsg_q); + } + spin_unlock_irq(&rx->recvmsg_lock); =20 - if (!sock_flag(sk, SOCK_DEAD)) { - _debug("call %ps", sk->sk_data_ready); - sk->sk_data_ready(sk); - } - } + if (!sock_flag(sk, SOCK_DEAD)) { + _debug("call %ps", sk->sk_data_ready); + sk->sk_data_ready(sk); } =20 - rcu_read_unlock(); _leave(""); } =20 @@ -561,7 +547,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *m= sg, size_t len, =20 if (!(flags & MSG_PEEK) && !skb_queue_empty(&call->recvmsg_queue)) - rxrpc_notify_socket(call); + rxrpc_requeue_call(sock, call); goto not_yet_complete; =20 call_failed: From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 6F91B3B0ADB for ; Mon, 13 Jul 2026 08:11:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930273; cv=none; b=NhJ6UZ6Wm+/oUYfkiS8oEbDakXN0El+CEA89GcrHpxdgIhMQUYcfmwyBledFYRqdO6S5P14mkfbqFf/4vXzVfy5Wa9MmunQ/DK9ajpvAyseU9mi/o/4mC57dpJerGTZRrMtiHq543S5wcR9Ly82oiNqPT0LvQAqvVb8ZnxsRQJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930273; c=relaxed/simple; bh=fH9PoXCyIlFnZSeO5S7KAc+KiFPN9psvq1q9mQZOGbI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sWRFKp/1WOYuxu1eReB6mU05lixEa3u/rXHubqbI6oeq/WXXYu1HEpPXxIv+//xYTXllDg5Rw0VzEaYDDuHh+NYfW3b8OAPnnxYlKwgZVICc4SH559ar9qNL6mQmfFrOJNAvGmHSgwtyBSa+8/8fmWqQASlEfGDCLk4I0VK1prA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Jtefj9tc; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Jtefj9tc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930269; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R0Wv8j/SsBkcIqut4rXhApQ4srhvttZcN9wllI+HXYk=; b=Jtefj9tcikiXreEtcLCisPQM0tbf7bI4y413eKglTrYzDlDm5MenC4XqI1UjCyKw+EL+cH FZhdUNjJGlysX7rulGhwoc0BEFzZakqZ0ey6WQXgOwIftCL6gOsRZf3Snqz9KI+Q8oVx/7 SDI4OJW/gtzyVh2XYiEF58bUvkktERk= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-110-I_2UDJZ_OiyFJlA36mSrtA-1; Mon, 13 Jul 2026 04:11:06 -0400 X-MC-Unique: I_2UDJZ_OiyFJlA36mSrtA-1 X-Mimecast-MFC-AGG-ID: I_2UDJZ_OiyFJlA36mSrtA_1783930265 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 50C1B1805A0A; Mon, 13 Jul 2026 08:11:04 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3F04830001A1; Mon, 13 Jul 2026 08:11:01 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman Subject: [PATCH net v3 07/14] afs: Simplify call refcounting Date: Mon, 13 Jul 2026 09:10:13 +0100 Message-ID: <20260713081022.2186481-8-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Simplify afs_call refcounting so that a queued work item doesn't hold a ref on the call. Rather, for async calls, put the retaining ref when the call completes. For synchronous calls, the caller of afs_make_call() holds its own ref. This means that queuing a call's async work doesn't require a ref to be taken first on a call - and then there's no need to try and revert the ref taken from the context of the rxrpc I/O thread if the call is already queued. Further, the AFS cache manager server RPC handler functions (SRXAFSCB_*) are then called directly from afs_deliver_to_call() rather then being dispatched to a different workqueue. With that, call->work is changed to a function pointer. Also, there is no longer a need to keep an extra ref on an async call and call->drop_ref can be removed. Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org --- fs/afs/cmservice.c | 33 ++++++------------ fs/afs/file.c | 10 +++--- fs/afs/internal.h | 18 ++-------- fs/afs/rxrpc.c | 69 +++++++++++--------------------------- include/trace/events/afs.h | 1 + 5 files changed, 39 insertions(+), 92 deletions(-) diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index db394f101fc6..32120bc1dcb0 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -23,11 +23,11 @@ static int afs_deliver_cb_callback(struct afs_call *); static int afs_deliver_cb_probe_uuid(struct afs_call *); static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *); static void afs_cm_destructor(struct afs_call *); -static void SRXAFSCB_CallBack(struct work_struct *); -static void SRXAFSCB_InitCallBackState(struct work_struct *); -static void SRXAFSCB_Probe(struct work_struct *); -static void SRXAFSCB_ProbeUuid(struct work_struct *); -static void SRXAFSCB_TellMeAboutYourself(struct work_struct *); +static void SRXAFSCB_CallBack(struct afs_call *call); +static void SRXAFSCB_InitCallBackState(struct afs_call *call); +static void SRXAFSCB_Probe(struct afs_call *call); +static void SRXAFSCB_ProbeUuid(struct afs_call *call); +static void SRXAFSCB_TellMeAboutYourself(struct afs_call *call); =20 static int afs_deliver_yfs_cb_callback(struct afs_call *); =20 @@ -161,10 +161,8 @@ static void afs_abort_service_call(struct afs_call *ca= ll, u32 abort_code, int er /* * The server supplied a list of callbacks that it wanted to break. */ -static void SRXAFSCB_CallBack(struct work_struct *work) +static void SRXAFSCB_CallBack(struct afs_call *call) { - struct afs_call *call =3D container_of(work, struct afs_call, work); - _enter(""); =20 /* We need to break the callbacks before sending the reply as the @@ -180,7 +178,6 @@ static void SRXAFSCB_CallBack(struct work_struct *work) } =20 afs_send_empty_reply(call); - afs_put_call(call); _leave(""); } =20 @@ -284,16 +281,13 @@ static int afs_deliver_cb_callback(struct afs_call *c= all) /* * allow the fileserver to request callback state (re-)initialisation */ -static void SRXAFSCB_InitCallBackState(struct work_struct *work) +static void SRXAFSCB_InitCallBackState(struct afs_call *call) { - struct afs_call *call =3D container_of(work, struct afs_call, work); - _enter("{%p}", call->server); =20 if (call->server) afs_init_callback_state(call->server); afs_send_empty_reply(call); - afs_put_call(call); _leave(""); } =20 @@ -380,13 +374,10 @@ static int afs_deliver_cb_init_call_back_state3(struc= t afs_call *call) /* * allow the fileserver to see if the cache manager is still alive */ -static void SRXAFSCB_Probe(struct work_struct *work) +static void SRXAFSCB_Probe(struct afs_call *call) { - struct afs_call *call =3D container_of(work, struct afs_call, work); - _enter(""); afs_send_empty_reply(call); - afs_put_call(call); _leave(""); } =20 @@ -413,9 +404,8 @@ static int afs_deliver_cb_probe(struct afs_call *call) * Allow the fileserver to quickly find out if the cache manager has been * rebooted. */ -static void SRXAFSCB_ProbeUuid(struct work_struct *work) +static void SRXAFSCB_ProbeUuid(struct afs_call *call) { - struct afs_call *call =3D container_of(work, struct afs_call, work); struct afs_uuid *r =3D call->request; =20 _enter(""); @@ -425,7 +415,6 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work) else afs_abort_service_call(call, 1, 1, afs_abort_probeuuid_negative); =20 - afs_put_call(call); _leave(""); } =20 @@ -489,9 +478,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *c= all) /* * allow the fileserver to ask about the cache manager's capabilities */ -static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) +static void SRXAFSCB_TellMeAboutYourself(struct afs_call *call) { - struct afs_call *call =3D container_of(work, struct afs_call, work); int loop; =20 struct { @@ -523,7 +511,6 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_st= ruct *work) reply.cap.capcount =3D htonl(1); reply.cap.caps[0] =3D htonl(AFS_CAP_ERROR_TRANSLATION); afs_send_simple_reply(call, &reply, sizeof(reply)); - afs_put_call(call); _leave(""); } =20 diff --git a/fs/afs/file.c b/fs/afs/file.c index 0467742bfeee..35d68f7f498d 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -316,15 +316,17 @@ void afs_fetch_data_async_rx(struct work_struct *work) struct afs_call *call =3D container_of(work, struct afs_call, async_work); =20 afs_read_receive(call); - afs_put_call(call); + + if (call->state =3D=3D AFS_CALL_COMPLETE) { + cancel_work(&call->async_work); + afs_put_call(call); + } } =20 void afs_fetch_data_immediate_cancel(struct afs_call *call) { if (call->async) { - afs_get_call(call, afs_call_trace_wake); - if (!queue_work(afs_async_calls, &call->async_work)) - afs_deferred_put_call(call); + queue_work(afs_async_calls, &call->async_work); flush_work(&call->async_work); } } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 601f01e5c15f..e55363f1d5ab 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -129,7 +129,7 @@ struct afs_call { const struct afs_call_type *type; /* type of call */ wait_queue_head_t waitq; /* processes awaiting completion */ struct work_struct async_work; /* async I/O processor */ - struct work_struct work; /* actual work processor */ + void (*work)(struct afs_call *call); /* Worker function */ struct work_struct free_work; /* Deferred free processor */ struct rxrpc_call *rxcall; /* RxRPC call handle */ struct rxrpc_peer *peer; /* Remote endpoint */ @@ -169,7 +169,6 @@ struct afs_call { unsigned reply_max; /* maximum size of reply */ unsigned count2; /* count used in unmarshalling */ unsigned char unmarshall; /* unmarshalling phase */ - bool drop_ref; /* T if need to drop ref for incoming call */ bool need_attention; /* T if RxRPC poked us */ bool async; /* T if asynchronous */ bool upgrade; /* T to request service upgrade */ @@ -208,7 +207,7 @@ struct afs_call_type { void (*async_rx)(struct work_struct *work); =20 /* Work function */ - void (*work)(struct work_struct *work); + void (*work)(struct afs_call *call); =20 /* Call done function (gets called immediately on success or failure) */ void (*done)(struct afs_call *call); @@ -1381,7 +1380,6 @@ extern int __net_init afs_open_socket(struct afs_net = *); extern void __net_exit afs_close_socket(struct afs_net *); extern void afs_charge_preallocation(struct work_struct *); extern void afs_put_call(struct afs_call *); -void afs_deferred_put_call(struct afs_call *call); void afs_make_call(struct afs_call *call, gfp_t gfp); void afs_deliver_to_call(struct afs_call *call); void afs_wait_for_call_to_complete(struct afs_call *call); @@ -1494,7 +1492,6 @@ static inline void afs_set_call_complete(struct afs_c= all *call, int error, u32 remote_abort) { enum afs_call_state state; - bool ok =3D false; =20 spin_lock_bh(&call->state_lock); state =3D call->state; @@ -1504,19 +1501,8 @@ static inline void afs_set_call_complete(struct afs_= call *call, call->state =3D AFS_CALL_COMPLETE; trace_afs_call_state(call, state, AFS_CALL_COMPLETE, error, remote_abort); - ok =3D true; } spin_unlock_bh(&call->state_lock); - if (ok) { - trace_afs_call_done(call); - - /* Asynchronous calls have two refs to release - one from the alloc and - * one queued with the work item - and we can't just deallocate the - * call because the work item may be queued again. - */ - if (call->drop_ref) - afs_put_call(call); - } } =20 /* diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 06c711c75f55..a404b6f0cc7c 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -177,7 +177,6 @@ static struct afs_call *afs_alloc_call(struct afs_net *= net, call->debug_id =3D atomic_inc_return(&rxrpc_debug_id); refcount_set(&call->ref, 1); INIT_WORK(&call->async_work, type->async_rx ?: afs_process_async_call); - INIT_WORK(&call->work, call->type->work); INIT_WORK(&call->free_work, afs_deferred_free_worker); init_waitqueue_head(&call->waitq); spin_lock_init(&call->state_lock); @@ -244,37 +243,6 @@ static void afs_deferred_free_worker(struct work_struc= t *work) afs_free_call(call); } =20 -/* - * Dispose of a reference on a call, deferring the cleanup to a workqueue - * to avoid lock recursion. - */ -void afs_deferred_put_call(struct afs_call *call) -{ - struct afs_net *net =3D call->net; - unsigned int debug_id =3D call->debug_id; - bool zero; - int r, o; - - zero =3D __refcount_dec_and_test(&call->ref, &r); - o =3D atomic_read(&net->nr_outstanding_calls); - trace_afs_call(debug_id, afs_call_trace_put, r - 1, o, - __builtin_return_address(0)); - if (zero) - schedule_work(&call->free_work); -} - -/* - * Queue the call for actual work. - */ -static void afs_queue_call_work(struct afs_call *call) -{ - if (call->type->work) { - afs_get_call(call, afs_call_trace_work); - if (!queue_work(afs_wq, &call->work)) - afs_put_call(call); - } -} - /* * allocate a call with flat request and reply buffers */ @@ -375,10 +343,8 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) /* If the call is going to be asynchronous, we need an extra ref for * the call to hold itself so the caller need not hang on to its ref. */ - if (call->async) { + if (call->async) afs_get_call(call, afs_call_trace_get); - call->drop_ref =3D true; - } =20 /* create a call */ rxcall =3D rxrpc_kernel_begin_call(call->net->socket, call->peer, call->k= ey, @@ -479,8 +445,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) if (call->rxcall) rxrpc_kernel_shutdown_call(call->net->socket, call->rxcall); if (call->async) { - if (cancel_work_sync(&call->async_work)) - afs_put_call(call); + cancel_work_sync(&call->async_work); afs_set_call_complete(call, ret, 0); } =20 @@ -566,7 +531,8 @@ void afs_deliver_to_call(struct afs_call *call) switch (ret) { case 0: call->responded =3D true; - afs_queue_call_work(call); + if (call->work) + call->work(call); if (state =3D=3D AFS_CALL_CL_PROC_REPLY) { if (call->op) set_bit(AFS_SERVER_FL_MAY_HAVE_CB, @@ -616,6 +582,7 @@ void afs_deliver_to_call(struct afs_call *call) } =20 done: + trace_afs_call_done(call); if (call->type->done) call->type->done(call); out: @@ -704,19 +671,16 @@ static void afs_wake_up_async_call(struct sock *sk, s= truct rxrpc_call *rxcall, unsigned long call_user_ID) { struct afs_call *call =3D (struct afs_call *)call_user_ID; - int r; =20 trace_afs_notify_call(rxcall, call); call->need_attention =3D true; =20 - if (__refcount_inc_not_zero(&call->ref, &r)) { - trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1, - atomic_read(&call->net->nr_outstanding_calls), - __builtin_return_address(0)); + trace_afs_call(call->debug_id, afs_call_trace_wake, + refcount_read(&call->ref), + atomic_read(&call->net->nr_outstanding_calls), + __builtin_return_address(0)); =20 - if (!queue_work(afs_async_calls, &call->async_work)) - afs_deferred_put_call(call); - } + queue_work(afs_async_calls, &call->async_work); } =20 /* @@ -729,12 +693,20 @@ static void afs_process_async_call(struct work_struct= *work) =20 _enter(""); =20 + trace_afs_call(call->debug_id, afs_call_trace_async_process, + refcount_read(&call->ref), + atomic_read(&call->net->nr_outstanding_calls), + __builtin_return_address(0)); + if (call->state < AFS_CALL_COMPLETE && call->need_attention) { call->need_attention =3D false; afs_deliver_to_call(call); } =20 - afs_put_call(call); + if (call->state =3D=3D AFS_CALL_COMPLETE) { + cancel_work(&call->async_work); + afs_put_call(call); + } _leave(""); } =20 @@ -760,7 +732,6 @@ void afs_charge_preallocation(struct work_struct *work) if (!call) break; =20 - call->drop_ref =3D true; call->async =3D true; call->state =3D AFS_CALL_SV_AWAIT_OP_ID; init_waitqueue_head(&call->waitq); @@ -836,7 +807,7 @@ static int afs_deliver_cm_op_id(struct afs_call *call) &call->enctype); =20 trace_afs_cb_call(call); - call->work.func =3D call->type->work; + call->work =3D call->type->work; =20 /* pass responsibility for the remainder of this message off to the * cache manager op */ diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index cf7218efb861..4f18a2a5b9f6 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -123,6 +123,7 @@ enum yfs_cm_operation { EM(afs_call_trace_alloc, "ALLOC") \ EM(afs_call_trace_async_abort, "ASYAB") \ EM(afs_call_trace_async_kill, "ASYKL") \ + EM(afs_call_trace_async_process, "ASYPR") \ EM(afs_call_trace_free, "FREE ") \ EM(afs_call_trace_get, "GET ") \ EM(afs_call_trace_put, "PUT ") \ From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 C757333FE0A for ; Mon, 13 Jul 2026 08:11:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930274; cv=none; b=I1n8QsMBIc3xrO0b4wxZL84Wi6lfYGiD/DyTwZMOWiaFe/RLLUA6SpgJTgFTj116jyhYiDaot7fx3oS1z10aHZAvWwiD2ale6YCHrwjlwYHXuQA7qCdlpsgDDK/kCkKZ+mm2bgzuJM76Ls29F2As5a3gC9GM3Eg/kp6BIVmG5Mk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930274; c=relaxed/simple; bh=yIdV7gkMrothlRw1nIxJBgNaDFr9FexOqxBLQ13zHlg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WHM0ks6WPdFl0FB9s2PlM5zwWOUxndgiKpQ/UaqF3AuY+e9IsPjM/1FBD+LYMJpRK0RKJp71+M7PNcy3gfg4DK3+DQ68bEMyqP4nNRRNqRYuZ8a/Gf63sGmcdbQ4dwlUx0kcRvluvQ65nlVZ9mi88zbB1V+8RVCGbxsRQP7afb4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=AAe6oxq7; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AAe6oxq7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930272; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HmaQ+z81XvDwrbaoGbipH/iozNJa7b0A3DkToai5LFE=; b=AAe6oxq7bOZBekKbAkBreQSQIQprpm9c4syWp30teLUXe7stPgVQAn/NBSpv6YTbOJGyqH K2xXfJ84GQ5q29d6useXbn8hkmuBMJJ0cpfIqkn88l3XWhxRA1gbt99US9Y3zDGwafsvrF DjcNNfwGR2PpnjeBS2sO/7W/GO1jQKU= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-632-_KaV8wsiNVuMIjTTuPGQhA-1; Mon, 13 Jul 2026 04:11:10 -0400 X-MC-Unique: _KaV8wsiNVuMIjTTuPGQhA-1 X-Mimecast-MFC-AGG-ID: _KaV8wsiNVuMIjTTuPGQhA_1783930269 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EFA081955D91; Mon, 13 Jul 2026 08:11:08 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E0A5C18005A0; Mon, 13 Jul 2026 08:11:05 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman Subject: [PATCH net v3 08/14] afs: Make afs_put_call() take trace argument Date: Mon, 13 Jul 2026 09:10:14 +0100 Message-ID: <20260713081022.2186481-9-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Make afs_put_call() take trace argument to display in the afs_call trace line and stop showing the function return address (which isn't unique due to inlining and tail-calling). Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org --- fs/afs/file.c | 4 ++-- fs/afs/fs_operation.c | 2 +- fs/afs/fsclient.c | 4 ++-- fs/afs/internal.h | 8 +++----- fs/afs/rxrpc.c | 39 ++++++++++++++------------------------ fs/afs/vl_probe.c | 2 +- fs/afs/vlclient.c | 8 ++++---- include/trace/events/afs.h | 38 +++++++++++++++++++++---------------- 8 files changed, 49 insertions(+), 56 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 35d68f7f498d..625dc67f79f3 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -298,7 +298,7 @@ static void afs_read_receive(struct afs_call *call) op->call_responded =3D call->responded; op->call =3D NULL; call->op =3D NULL; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_read_op); =20 /* If the call failed, then we need to crank the server rotation * handle and try the next. @@ -319,7 +319,7 @@ void afs_fetch_data_async_rx(struct work_struct *work) =20 if (call->state =3D=3D AFS_CALL_COMPLETE) { cancel_work(&call->async_work); - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_read_complete); } } =20 diff --git a/fs/afs/fs_operation.c b/fs/afs/fs_operation.c index 20801b29521d..b887047398b9 100644 --- a/fs/afs/fs_operation.c +++ b/fs/afs/fs_operation.c @@ -296,7 +296,7 @@ void afs_wait_for_operation(struct afs_operation *op) op->call_abort_code =3D op->call->abort_code; op->call_error =3D op->call->error; op->call_responded =3D op->call->responded; - afs_put_call(op->call); + afs_put_call(op->call, afs_call_trace_put_wait_op); } } =20 diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 626e1d37b915..9acad5017fba 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -1662,7 +1662,7 @@ int afs_fs_give_up_all_callbacks(struct afs_net *net,= struct afs_server *server, ret =3D call->error; if (call->responded) set_bit(AFS_SERVER_FL_RESPONDING, &server->flags); - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_giveupcallbacks); return ret; } =20 @@ -1778,7 +1778,7 @@ bool afs_fs_get_capabilities(struct afs_net *net, str= uct afs_server *server, =20 trace_afs_make_fs_call(call, NULL); afs_make_call(call, GFP_NOFS); - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_get_capabilities); return true; } =20 diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e55363f1d5ab..4901d0acbe14 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1379,7 +1379,7 @@ extern struct workqueue_struct *afs_async_calls; extern int __net_init afs_open_socket(struct afs_net *); extern void __net_exit afs_close_socket(struct afs_net *); extern void afs_charge_preallocation(struct work_struct *); -extern void afs_put_call(struct afs_call *); +void afs_put_call(struct afs_call *call, enum afs_call_trace trace); void afs_make_call(struct afs_call *call, gfp_t gfp); void afs_deliver_to_call(struct afs_call *call); void afs_wait_for_call_to_complete(struct afs_call *call); @@ -1400,8 +1400,7 @@ static inline struct afs_call *afs_get_call(struct af= s_call *call, __refcount_inc(&call->ref, &r); =20 trace_afs_call(call->debug_id, why, r + 1, - atomic_read(&call->net->nr_outstanding_calls), - __builtin_return_address(0)); + atomic_read(&call->net->nr_outstanding_calls)); return call; } =20 @@ -1410,8 +1409,7 @@ static inline void afs_see_call(struct afs_call *call= , enum afs_call_trace why) int r =3D refcount_read(&call->ref); =20 trace_afs_call(call->debug_id, why, r, - atomic_read(&call->net->nr_outstanding_calls), - __builtin_return_address(0)); + atomic_read(&call->net->nr_outstanding_calls)); } =20 static inline void afs_make_op_call(struct afs_operation *op, struct afs_c= all *call, diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index a404b6f0cc7c..a1b9ced4e0f4 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -138,7 +138,7 @@ void afs_close_socket(struct afs_net *net) cancel_work_sync(&net->charge_preallocation_work); =20 if (net->spare_incoming_call) { - afs_put_call(net->spare_incoming_call); + afs_put_call(net->spare_incoming_call, afs_call_trace_put_spare_svc); net->spare_incoming_call =3D NULL; } =20 @@ -183,14 +183,14 @@ static struct afs_call *afs_alloc_call(struct afs_net= *net, call->iter =3D &call->def_iter; =20 o =3D atomic_inc_return(&net->nr_outstanding_calls); - trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o, - __builtin_return_address(0)); + trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o); return call; } =20 static void afs_free_call(struct afs_call *call) { struct afs_net *net =3D call->net; + unsigned int debug_id =3D call->debug_id; int o; =20 ASSERT(!work_pending(&call->async_work)); @@ -207,13 +207,10 @@ static void afs_free_call(struct afs_call *call) =20 afs_unuse_server_notime(call->net, call->server, afs_server_trace_unuse_c= all); kfree(call->request); - - o =3D atomic_read(&net->nr_outstanding_calls); - trace_afs_call(call->debug_id, afs_call_trace_free, 0, o, - __builtin_return_address(0)); kfree(call); =20 o =3D atomic_dec_return(&net->nr_outstanding_calls); + trace_afs_call(debug_id, afs_call_trace_free, 0, o); if (o =3D=3D 0) wake_up_var(&net->nr_outstanding_calls); } @@ -221,7 +218,7 @@ static void afs_free_call(struct afs_call *call) /* * Dispose of a reference on a call. */ -void afs_put_call(struct afs_call *call) +void afs_put_call(struct afs_call *call, enum afs_call_trace trace) { struct afs_net *net =3D call->net; unsigned int debug_id =3D call->debug_id; @@ -230,8 +227,7 @@ void afs_put_call(struct afs_call *call) =20 zero =3D __refcount_dec_and_test(&call->ref, &r); o =3D atomic_read(&net->nr_outstanding_calls); - trace_afs_call(debug_id, afs_call_trace_put, r - 1, o, - __builtin_return_address(0)); + trace_afs_call(debug_id, trace, r - 1, o); if (zero) afs_free_call(call); } @@ -276,7 +272,7 @@ struct afs_call *afs_alloc_flat_call(struct afs_net *ne= t, return call; =20 nomem_free: - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_oom); nomem_call: return NULL; } @@ -344,7 +340,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) * the call to hold itself so the caller need not hang on to its ref. */ if (call->async) - afs_get_call(call, afs_call_trace_get); + afs_get_call(call, afs_call_trace_get_make_async_call); =20 /* create a call */ rxcall =3D rxrpc_kernel_begin_call(call->net->socket, call->peer, call->k= ey, @@ -418,7 +414,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) RX_USER_ABORT, ret, afs_abort_send_data_error); if (call->async) { - afs_see_call(call, afs_call_trace_async_abort); + afs_see_call(call, afs_call_trace_see_async_abort); return; } =20 @@ -434,7 +430,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) trace_afs_call_done(call); error_kill_call: if (call->async) - afs_see_call(call, afs_call_trace_async_kill); + afs_see_call(call, afs_call_trace_see_async_kill); if (call->type->immediate_cancel) call->type->immediate_cancel(call); =20 @@ -675,11 +671,7 @@ static void afs_wake_up_async_call(struct sock *sk, st= ruct rxrpc_call *rxcall, trace_afs_notify_call(rxcall, call); call->need_attention =3D true; =20 - trace_afs_call(call->debug_id, afs_call_trace_wake, - refcount_read(&call->ref), - atomic_read(&call->net->nr_outstanding_calls), - __builtin_return_address(0)); - + afs_see_call(call, afs_call_trace_see_async_wake); queue_work(afs_async_calls, &call->async_work); } =20 @@ -693,10 +685,7 @@ static void afs_process_async_call(struct work_struct = *work) =20 _enter(""); =20 - trace_afs_call(call->debug_id, afs_call_trace_async_process, - refcount_read(&call->ref), - atomic_read(&call->net->nr_outstanding_calls), - __builtin_return_address(0)); + afs_see_call(call, afs_call_trace_see_async_process); =20 if (call->state < AFS_CALL_COMPLETE && call->need_attention) { call->need_attention =3D false; @@ -705,7 +694,7 @@ static void afs_process_async_call(struct work_struct *= work) =20 if (call->state =3D=3D AFS_CALL_COMPLETE) { cancel_work(&call->async_work); - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_async_complete); } _leave(""); } @@ -758,7 +747,7 @@ static void afs_rx_discard_new_call(struct rxrpc_call *= rxcall, struct afs_call *call =3D (struct afs_call *)user_call_ID; =20 call->rxcall =3D NULL; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_discard_prealloc); } =20 /* diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c index 3d2e0c925460..1d70887c9f31 100644 --- a/fs/afs/vl_probe.c +++ b/fs/afs/vl_probe.c @@ -186,7 +186,7 @@ static bool afs_do_probe_vlserver(struct afs_net *net, server_index); if (!IS_ERR(call)) { afs_prioritise_error(_e, call->error, call->abort_code); - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_vl_get_caps); in_progress =3D true; } else { afs_prioritise_error(_e, PTR_ERR(call), 0); diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index a40b43464cfa..8a4c8c9a1e39 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c @@ -153,7 +153,7 @@ struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struc= t afs_vl_cursor *vc, vc->call_abort_code =3D call->abort_code; vc->call_error =3D call->error; vc->call_responded =3D call->responded; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_vl_call); if (vc->call_error) { kfree(entry); return ERR_PTR(vc->call_error); @@ -303,7 +303,7 @@ struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_= cursor *vc, vc->call_error =3D call->error; vc->call_responded =3D call->responded; alist =3D call->ret_alist; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_vl_call); if (vc->call_error) { afs_put_addrlist(alist, afs_alist_trace_put_getaddru); return ERR_PTR(vc->call_error); @@ -666,7 +666,7 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct af= s_vl_cursor *vc, vc->call_error =3D call->error; vc->call_responded =3D call->responded; alist =3D call->ret_alist; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_vl_call); if (vc->call_error) { afs_put_addrlist(alist, afs_alist_trace_put_getaddru); return ERR_PTR(vc->call_error); @@ -784,7 +784,7 @@ char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc) vc->call_error =3D call->error; vc->call_responded =3D call->responded; cellname =3D call->ret_str; - afs_put_call(call); + afs_put_call(call, afs_call_trace_put_vl_call); if (vc->call_error) { kfree(cellname); return ERR_PTR(vc->call_error); diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 4f18a2a5b9f6..df397c11df85 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -120,15 +120,24 @@ enum yfs_cm_operation { * Declare tracing information enums and their string mappings for display. */ #define afs_call_traces \ - EM(afs_call_trace_alloc, "ALLOC") \ - EM(afs_call_trace_async_abort, "ASYAB") \ - EM(afs_call_trace_async_kill, "ASYKL") \ - EM(afs_call_trace_async_process, "ASYPR") \ - EM(afs_call_trace_free, "FREE ") \ - EM(afs_call_trace_get, "GET ") \ - EM(afs_call_trace_put, "PUT ") \ - EM(afs_call_trace_wake, "WAKE ") \ - E_(afs_call_trace_work, "QUEUE") + EM(afs_call_trace_alloc, "ALLOC ") \ + EM(afs_call_trace_free, "FREE ") \ + EM(afs_call_trace_get_make_async_call, "GET a-make ") \ + EM(afs_call_trace_put_async_complete, "PUT a-cmpl ") \ + EM(afs_call_trace_put_discard_prealloc, "PUT dis-pre") \ + EM(afs_call_trace_put_get_capabilities, "PUT get-cap") \ + EM(afs_call_trace_put_giveupcallbacks, "PUT gvup-cb") \ + EM(afs_call_trace_put_oom, "PUT oom ") \ + EM(afs_call_trace_put_read_complete, "PUT rd-cpl ") \ + EM(afs_call_trace_put_read_op, "PUT rd-op ") \ + EM(afs_call_trace_put_spare_svc, "PUT spare-s") \ + EM(afs_call_trace_put_vl_call, "PUT vl-call") \ + EM(afs_call_trace_put_vl_get_caps, "PUT vl-gcap") \ + EM(afs_call_trace_put_wait_op, "PUT wt-op ") \ + EM(afs_call_trace_see_async_abort, "SEE a-abort") \ + EM(afs_call_trace_see_async_kill, "SEE a-kill ") \ + EM(afs_call_trace_see_async_process, "SEE a-proc ") \ + E_(afs_call_trace_see_async_wake, "SEE a-wake ") =20 #define afs_server_traces \ EM(afs_server_trace_callback, "CALLBACK ") \ @@ -694,16 +703,15 @@ TRACE_EVENT(afs_cb_call, =20 TRACE_EVENT(afs_call, TP_PROTO(unsigned int call_debug_id, enum afs_call_trace op, - int ref, int outstanding, const void *where), + int ref, int outstanding), =20 - TP_ARGS(call_debug_id, op, ref, outstanding, where), + TP_ARGS(call_debug_id, op, ref, outstanding), =20 TP_STRUCT__entry( __field(unsigned int, call) __field(int, op) __field(int, ref) __field(int, outstanding) - __field(const void *, where) ), =20 TP_fast_assign( @@ -711,15 +719,13 @@ TRACE_EVENT(afs_call, __entry->op =3D op; __entry->ref =3D ref; __entry->outstanding =3D outstanding; - __entry->where =3D where; ), =20 - TP_printk("c=3D%08x %s r=3D%d o=3D%d sp=3D%pSR", + TP_printk("c=3D%08x %s r=3D%d o=3D%d", __entry->call, __print_symbolic(__entry->op, afs_call_traces), __entry->ref, - __entry->outstanding, - __entry->where) + __entry->outstanding) ); =20 TRACE_EVENT(afs_make_fs_call, From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 A3F4A3B14B6 for ; Mon, 13 Jul 2026 08:11:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930279; cv=none; b=gGeDX3sJfTcMNH+c6UVvK4+tKuo6uTAmnzrYRfkqAdSblkWmxzwgm53sOJMbqa3MShicumuzhdC7E4GI2XNcRkYAti32NuO+66+OuUEbSmQFqdzXScxOAhbOmlD1qyWF03hoQ6NNbeEdhsseemQx5pU0bA7N/gth63XuCChBwUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930279; c=relaxed/simple; bh=x68jmtgRi4WLvvhzlv8t4ufL4Lh9Zn5cECgSNdtwQ9M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WZLlR/ZjXwUaurRcQonpjFFzMt5ZT1Phop7UYv58RpCm2v5sNCxQR0av2+kGKcYvJpSV+FhXl4tYSFQYcg5rJLfcXC2FIkDg7JkCQxoqj/Qe858invjAZ/KdLzaxpn5HvMZmtkcq/ulGndrlA/TOcNyknJc2Pvb9Go6FRVBlAks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ROt4I6tr; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ROt4I6tr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PIgZcla1/YpoDmZ2ZqwvtibEJyua5l/6xD4lwXMlYlE=; b=ROt4I6trB/kBFDUzMaOR7RTChmqMuEXAKSPKvorQkM40dIEodAZYKVb2VGi/FcdA/7RNUu SmR+5WimOiAmZqEax3BA3Y/Rk/VeOKAJVWpa6k7lVMaKPMJ407iMEkOXcSY6rvGAqVt+Ui ErrmxdcpinFkZm4cr/6ByL4DoqpPCAw= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-67-mx3kNCz5Nam1wM_c3H7BlA-1; Mon, 13 Jul 2026 04:11:15 -0400 X-MC-Unique: mx3kNCz5Nam1wM_c3H7BlA-1 X-Mimecast-MFC-AGG-ID: mx3kNCz5Nam1wM_c3H7BlA_1783930274 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E6EA318052EA; Mon, 13 Jul 2026 08:11:13 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A0ED0195604B; Mon, 13 Jul 2026 08:11:10 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , stable@kernel.org Subject: [PATCH net v3 09/14] afs: Fix UAF in afs_make_call() Date: Mon, 13 Jul 2026 09:10:15 +0100 Message-ID: <20260713081022.2186481-10-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" There's a potential UAF in afs_make_call() in the event that an asynchronous call is being sent, but the call fails in some way (e.g. it gets aborted from the server). The problem is that afs_make_call() tries to abort a call if the rxrpc send fails, but the asynchronous notification from rxrpc may have caused the afs_call to be torn down. Fix this making afs_make_op_call() give the op->call its own ref rather than transferring the caller's ref to it and then dropping the ref when afs_make_call() returns. This also means that the afs_make_call() func never loses its ref on the call now. Fixes: e49c7b2f6de7 ("afs: Build an abstraction around an "operation" conce= pt") Link: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: linux-afs@lists.infradead.org cc: stable@kernel.org --- fs/afs/internal.h | 3 ++- fs/afs/rxrpc.c | 3 --- include/trace/events/afs.h | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 4901d0acbe14..645fe2f12dc5 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1417,7 +1417,7 @@ static inline void afs_make_op_call(struct afs_operat= ion *op, struct afs_call *c { struct afs_addr_list *alist =3D op->estate->addresses; =20 - op->call =3D call; + op->call =3D afs_get_call(call, afs_call_trace_get_op_call); op->type =3D call->type; call->op =3D op; call->key =3D op->key; @@ -1425,6 +1425,7 @@ static inline void afs_make_op_call(struct afs_operat= ion *op, struct afs_call *c call->peer =3D rxrpc_kernel_get_peer(alist->addrs[op->addr_index].peer); call->service_id =3D op->server->service_id; afs_make_call(call, gfp); + afs_put_call(call, afs_call_trace_put_made_call); } =20 static inline void afs_extract_begin(struct afs_call *call, void *buf, siz= e_t size) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index a1b9ced4e0f4..6dc6fd853832 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -382,8 +382,6 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) if (ret < 0) goto error_do_abort; =20 - /* We lost our ref on call if MSG_MORE was not set and ret >=3D 0. */ - if (write_iter) { msg.msg_iter =3D *call->write_iter; msg.msg_flags &=3D ~MSG_MORE; @@ -393,7 +391,6 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) call->rxcall, &msg, iov_iter_count(&msg.msg_iter), afs_notify_end_request_tx); - /* We lost our ref on call if ret >=3D 0. */ =20 trace_afs_sent_data(debug_id, &msg, ret); if (ret < 0) diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index df397c11df85..a1963e21f034 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -122,8 +122,10 @@ enum yfs_cm_operation { #define afs_call_traces \ EM(afs_call_trace_alloc, "ALLOC ") \ EM(afs_call_trace_free, "FREE ") \ + EM(afs_call_trace_get_op_call, "GET op ") \ EM(afs_call_trace_get_make_async_call, "GET a-make ") \ EM(afs_call_trace_put_async_complete, "PUT a-cmpl ") \ + EM(afs_call_trace_put_made_call, "PUT made ") \ EM(afs_call_trace_put_discard_prealloc, "PUT dis-pre") \ EM(afs_call_trace_put_get_capabilities, "PUT get-cap") \ EM(afs_call_trace_put_giveupcallbacks, "PUT gvup-cb") \ From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 2FBBE3B27F0 for ; Mon, 13 Jul 2026 08:11:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930288; cv=none; b=i3hQF+o5qC++wnd/8VlGXzrTvub8fqkQSKtUA10DPlW+cDoZnoqJfhjo8KKXQOvj6zvqfxnys2MqYggefB0P+meuU1m1xxEDoK+cwk7GJSQN4ONMt8jbgUAqYwiNmJS2JD6YR1H5e6MbKz+i+uAdWnIRIp9RAAeVvisOkGhlO6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930288; c=relaxed/simple; bh=8xYe1xVOymzfUL3FY35nN2xScs1Bzzf+To/adTMsX10=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pvSExaSuqujdMuFoOcn1juYnB/fT+SVJmXLjkSMSUaMgBkChaN/pFz1uAhy1j6kqN1bVWuirQ1XCyjhB4LnTR6I90mEfHpQ2eijTsz+CfAa0Gx9GWyLD2IjVM+pXPh1ynLYkz4dxlTNMBwwKrk3FBSoEa2pJ3087SUmis/zeSRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Kl9jkDNh; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Kl9jkDNh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930286; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6bsxuWrGjCNJ9G3R3V0fM/GxuviKNyJjBl9DCZXobyc=; b=Kl9jkDNhIPy891OdnSWdM6RlzbdofvWQqcWkCXZKm82knlR4/vT57HjznBLe53W5/uRxSX K5qhG4LwazBp/ZzMKcrICxk/H/LBhFYeehvh0md6ItQE6UA+O9vHSr43SZ8NGLlV0qsDQN L0Uv2aIF0D2QvgIA7RjcEMyviHy47vc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-225-uUD2OqNcNgqn2ob82L3oFQ-1; Mon, 13 Jul 2026 04:11:21 -0400 X-MC-Unique: uUD2OqNcNgqn2ob82L3oFQ-1 X-Mimecast-MFC-AGG-ID: uUD2OqNcNgqn2ob82L3oFQ_1783930279 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4C53418052F2; Mon, 13 Jul 2026 08:11:19 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 829F719560A0; Mon, 13 Jul 2026 08:11:15 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , Jarkko Sakkinen , keyrings@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 10/14] keys: Add refcounting to user-defined key type payload Date: Mon, 13 Jul 2026 09:10:16 +0100 Message-ID: <20260713081022.2186481-11-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Add refcounting to user-defined key type payload so that a kernel service wanting to use such a key can hold onto the payload without the RCU read lock held in order that it can do an allocation without having to be concerned with the key getting updated. This is the first part of the fix for the AF_RXRPC challenge response generation code. Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: Jarkko Sakkinen cc: linux-afs@lists.infradead.org cc: keyrings@vger.kernel.org cc: stable@kernel.org --- include/keys/user-type.h | 2 ++ net/dns_resolver/dns_key.c | 1 + security/keys/user_defined.c | 23 ++++++++++++++++------- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/include/keys/user-type.h b/include/keys/user-type.h index 386c31432789..7002a993a472 100644 --- a/include/keys/user-type.h +++ b/include/keys/user-type.h @@ -26,6 +26,7 @@ */ struct user_key_payload { struct rcu_head rcu; /* RCU destructor */ + refcount_t ref; unsigned short datalen; /* length of this data */ char data[] __aligned(__alignof__(u64)); /* actual data */ }; @@ -37,6 +38,7 @@ struct key_preparsed_payload; =20 extern int user_preparse(struct key_preparsed_payload *prep); extern void user_free_preparse(struct key_preparsed_payload *prep); +void put_user_key_payload(struct user_key_payload *payload); extern int user_update(struct key *key, struct key_preparsed_payload *prep= ); extern void user_revoke(struct key *key); extern void user_destroy(struct key *key); diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index c3c8c3240ef9..aa3c058f4095 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -208,6 +208,7 @@ dns_resolver_preparse(struct key_preparsed_payload *pre= p) kleave(" =3D -ENOMEM"); return -ENOMEM; } + refcount_set(&upayload->ref, 1); =20 upayload->datalen =3D result_len; memcpy(upayload->data, data, result_len); diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 6f88b507f927..90c1bd5d7dfe 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -67,6 +67,7 @@ int user_preparse(struct key_preparsed_payload *prep) upayload =3D kmalloc_flex(*upayload, data, datalen); if (!upayload) return -ENOMEM; + refcount_set(&upayload->ref, 1); =20 /* attach the data */ prep->quotalen =3D datalen; @@ -88,12 +89,22 @@ EXPORT_SYMBOL_GPL(user_free_preparse); =20 static void user_free_payload_rcu(struct rcu_head *head) { - struct user_key_payload *payload; + struct user_key_payload *payload =3D + container_of(head, struct user_key_payload, rcu); =20 - payload =3D container_of(head, struct user_key_payload, rcu); kfree_sensitive(payload); } =20 +/* + * Free a user defined key payload. + */ +void put_user_key_payload(struct user_key_payload *payload) +{ + if (payload && refcount_dec_and_test(&payload->ref)) + call_rcu(&payload->rcu, user_free_payload_rcu); +} +EXPORT_SYMBOL_GPL(put_user_key_payload); + /* * update a user defined key * - the key's semaphore is write-locked @@ -115,8 +126,7 @@ int user_update(struct key *key, struct key_preparsed_p= ayload *prep) rcu_assign_keypointer(key, prep->payload.data[0]); prep->payload.data[0] =3D NULL; =20 - if (zap) - call_rcu(&zap->rcu, user_free_payload_rcu); + put_user_key_payload(zap); return ret; } EXPORT_SYMBOL_GPL(user_update); @@ -134,7 +144,7 @@ void user_revoke(struct key *key) =20 if (upayload) { rcu_assign_keypointer(key, NULL); - call_rcu(&upayload->rcu, user_free_payload_rcu); + put_user_key_payload(upayload); } } =20 @@ -147,9 +157,8 @@ void user_destroy(struct key *key) { struct user_key_payload *upayload =3D key->payload.data[0]; =20 - kfree_sensitive(upayload); + put_user_key_payload(upayload); } - EXPORT_SYMBOL_GPL(user_destroy); =20 /* From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 D60273AA4EA for ; Mon, 13 Jul 2026 08:11:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930297; cv=none; b=gWztdP7FiSbGRgUjxz67LK0We5c+tD5mr0DeILFfpL6GBiRlAM7tZbj6cEx+02N2EMWUpOXwmWyDxcAbzcavqj9rhf/FtYusl7nUhKmix1cfW3kQb/41PmIj1EGVjC0loO8fPUDb2FfrPPBLrN1p010T8S04sRHDRqPZztnD4Jc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930297; c=relaxed/simple; bh=udmPVYKPVsXFcPfJiJHImVLewtIuCcJElDtxi6KNqYs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iUwupQ//756SXuGC8cVl9x053qTDeqDWVqK+ySaW0k9Yb0dSIIbS4yEIYPvFhy3YGfegmJKzAAsn8iOaQxGkd+FPeUnnEqyCH7JM1GII+ipQ1xRl1hr94xsQ8nTqUGF/5WI6aBHlp5THfUSsAfyLJwvmzqMjKKVf/MLWn85HE3w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Vyzqcs80; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Vyzqcs80" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930290; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Hh5ODOBVtLvyUTVkwW8KCZFUWQ5fc6kLpTC+yDp7g/I=; b=Vyzqcs80uxJmN9rn2BbS8wTAy6xvmxi/pm1eLKZvGcsNjiUppbkOZtkGLdy2eAPjgYnuO0 osXtFXVu6FCN78bdxIeawB5MvuQuZnpAQ075cqj3itTWKvOUI/TpqtoXHOOGSX0B5iRfxT M/9Der+p+mMDc52uWRXcfWwN1Z1dZwU= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-203-9zM9RAN3NkG1DoKYs1-X-Q-1; Mon, 13 Jul 2026 04:11:26 -0400 X-MC-Unique: 9zM9RAN3NkG1DoKYs1-X-Q-1 X-Mimecast-MFC-AGG-ID: 9zM9RAN3NkG1DoKYs1-X-Q_1783930284 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A5AAA1800A3C; Mon, 13 Jul 2026 08:11:24 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DD4021686; Mon, 13 Jul 2026 08:11:20 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , Jarkko Sakkinen , keyrings@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 11/14] afs: Create a server appdata key Date: Mon, 13 Jul 2026 09:10:17 +0100 Message-ID: <20260713081022.2186481-12-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" Currently, when a CHALLENGE packet comes in, it's queued in an OOB queue on the AF_RXRPC socket that generated one of the calls on that connection for the application (which might be in userspace) to service. The application then picks up the CHALLENGE and requests a RESPONSE packet be generated, allowing the app to include app-specific data in it if appropriate. There is, however, no actual limit on the capacity of the CHALLENGE queue, and this could be abused remotely - and also getting the OOB mechanism right has proven tricky. Further, by analogy with other AFS codebases, it's not actually necessary to generate the application data in response to the CHALLENGE. The reason I did this was to set the encryption on the app-data to be the same as that specified in the CHALLENGE as the server must be able to handle that. However, it's sufficient to use the encoding type set in the token that is going to be sent to the server; presumably the kerberos server knows that the fileserver can handle that type - otherwise why tell the client to use it? This is a part of the fix. With this, the AFS filesystem creates an appdata key for each fileserver it talks to with RxGK and attaches it to the afs_server record. Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for = a RESPONSE") Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: Jarkko Sakkinen cc: linux-afs@lists.infradead.org cc: keyrings@vger.kernel.org cc: stable@kernel.org --- fs/afs/cm_security.c | 232 +++++++++++++++++++++++++++++++++++++++++ fs/afs/fs_probe.c | 5 + fs/afs/internal.h | 2 + fs/afs/server.c | 1 + include/net/af_rxrpc.h | 2 + net/rxrpc/key.c | 37 +++++++ 6 files changed, 279 insertions(+) diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c index 103168c70dd4..36907a04efd0 100644 --- a/fs/afs/cm_security.c +++ b/fs/afs/cm_security.c @@ -6,7 +6,9 @@ */ =20 #include +#include #include +#include #include "internal.h" #include "afs_cm.h" #include "afs_fs.h" @@ -23,6 +25,236 @@ static int afs_create_yfs_cm_token(struct sk_buff *chal= lenge, struct afs_server *server); #endif =20 +#ifdef CONFIG_RXGK +/* + * As the YFS RxGK appdata to be passed in the YFS.FS-service RESPONSE pac= ket, + * create a GSS token to use as a ticket to the specified fileserver. + */ +static int afs_create_yfs_rxgk_cm_appdata(struct afs_server *server, u32 e= nctype) +{ + const struct krb5_enctype *conn_krb5, *token_krb5; + const struct krb5_buffer *token_key; + struct crypto_aead *aead; + struct scatterlist sg; + struct afs_net *net =3D server->cell->net; + const struct key *cm_key =3D net->fs_cm_token_key; + struct key *appdata_key =3D NULL; + size_t keysize, uuidsize, authsize, toksize, encsize, contsize; + size_t adatasize, offset; + __be32 caps[1] =3D { + [0] =3D htonl(AFS_CAP_ERROR_TRANSLATION), + }; + __be32 *xdr; + void *appdata, *K0, *encbase; + int ret; + + if (!cm_key) + return -ENOKEY; + + /* Assume that the fileserver is happy to use the same encoding type as + * we were told to use by the token obtained by the user. + */ + conn_krb5 =3D crypto_krb5_find_enctype(enctype); + if (!conn_krb5) + return -ENOPKG; + token_krb5 =3D cm_key->payload.data[0]; + token_key =3D (const struct krb5_buffer *)&cm_key->payload.data[2]; + + /* struct rxgk_key { + * afs_uint32 enctype; + * opaque key<>; + * }; + */ + keysize =3D 4 + xdr_len_object(conn_krb5->key_len); + + /* struct RXGK_AuthName { + * afs_int32 kind; + * opaque data; + * opaque display; + * }; + */ + uuidsize =3D sizeof(server->uuid); + authsize =3D 4 + xdr_len_object(uuidsize) + xdr_len_object(0); + + /* struct RXGK_Token { + * rxgk_key K0; + * RXGK_Level level; + * rxgkTime starttime; + * afs_int32 lifetime; + * afs_int32 bytelife; + * rxgkTime expirationtime; + * struct RXGK_AuthName identities<>; + * }; + */ + toksize =3D keysize + 8 + 4 + 4 + 8 + xdr_len_object(authsize); + + offset =3D 0; + encsize =3D crypto_krb5_how_much_buffer(token_krb5, KRB5_ENCRYPT_MODE, to= ksize, &offset); + + /* struct RXGK_TokenContainer { + * afs_int32 kvno; + * afs_int32 enctype; + * opaque encrypted_token<>; + * }; + */ + contsize =3D 4 + 4 + xdr_len_object(encsize); + + /* struct YFSAppData { + * opr_uuid initiatorUuid; + * opr_uuid acceptorUuid; + * Capabilities caps; + * afs_int32 enctype; + * opaque callbackKey<>; + * opaque callbackToken<>; + * }; + */ + adatasize =3D 16 + 16 + + xdr_len_object(sizeof(caps)) + + 4 + + xdr_len_object(conn_krb5->key_len) + + xdr_len_object(contsize); + + ret =3D -ENOMEM; + appdata =3D kzalloc(adatasize, GFP_KERNEL); + if (!appdata) + goto out; + xdr =3D appdata; + + memcpy(xdr, &net->uuid, 16); /* appdata.initiatorUuid */ + xdr +=3D 16 / 4; + memcpy(xdr, &server->uuid, 16); /* appdata.acceptorUuid */ + xdr +=3D 16 / 4; + *xdr++ =3D htonl(ARRAY_SIZE(caps)); /* appdata.caps.len */ + memcpy(xdr, &caps, sizeof(caps)); /* appdata.caps */ + xdr +=3D ARRAY_SIZE(caps); + *xdr++ =3D htonl(conn_krb5->etype); /* appdata.enctype */ + + *xdr++ =3D htonl(conn_krb5->key_len); /* appdata.callbackKey.len */ + K0 =3D xdr; + get_random_bytes(K0, conn_krb5->key_len); /* appdata.callbackKey.data */ + xdr +=3D xdr_round_up(conn_krb5->key_len) / 4; + + *xdr++ =3D htonl(contsize); /* appdata.callbackToken.len */ + *xdr++ =3D htonl(1); /* cont.kvno */ + *xdr++ =3D htonl(token_krb5->etype); /* cont.enctype */ + *xdr++ =3D htonl(encsize); /* cont.encrypted_token.len */ + + encbase =3D xdr; + xdr +=3D offset / 4; + *xdr++ =3D htonl(conn_krb5->etype); /* token.K0.enctype */ + *xdr++ =3D htonl(conn_krb5->key_len); /* token.K0.key.len */ + memcpy(xdr, K0, conn_krb5->key_len); /* token.K0.key.data */ + xdr +=3D xdr_round_up(conn_krb5->key_len) / 4; + + *xdr++ =3D htonl(RXRPC_SECURITY_ENCRYPT); /* token.level */ + *xdr++ =3D htonl(0); /* token.starttime */ + *xdr++ =3D htonl(0); /* " */ + *xdr++ =3D htonl(0); /* token.lifetime */ + *xdr++ =3D htonl(0); /* token.bytelife */ + *xdr++ =3D htonl(0); /* token.expirationtime */ + *xdr++ =3D htonl(0); /* " */ + *xdr++ =3D htonl(1); /* token.identities.count */ + *xdr++ =3D htonl(0); /* token.identities[0].kind */ + *xdr++ =3D htonl(uuidsize); /* token.identities[0].data.len */ + memcpy(xdr, &server->uuid, uuidsize); + xdr +=3D xdr_round_up(uuidsize) / 4; + *xdr++ =3D htonl(0); /* token.identities[0].display.len */ + + xdr =3D encbase + xdr_round_up(encsize); + + if ((unsigned long)xdr - (unsigned long)appdata !=3D adatasize) + pr_err("Appdata size incorrect %lx !=3D %zx\n", + (unsigned long)xdr - (unsigned long)appdata, adatasize); + + aead =3D crypto_krb5_prepare_encryption(token_krb5, token_key, RXGK_SERVE= R_ENC_TOKEN, + GFP_KERNEL); + if (IS_ERR(aead)) { + ret =3D PTR_ERR(aead); + goto out_token; + } + + sg_init_one(&sg, encbase, encsize); + ret =3D crypto_krb5_encrypt(token_krb5, aead, &sg, 1, encsize, offset, to= ksize, false); + if (ret < 0) + goto out_aead; + + appdata_key =3D key_alloc(&key_type_user, "rxrpc: afs rxgk appdata", + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), + KEY_POS_VIEW | KEY_POS_SEARCH | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (IS_ERR(appdata_key)) { + ret =3D PTR_ERR(appdata_key); + goto out_aead; + } + + ret =3D key_instantiate_and_link(appdata_key, appdata, adatasize, NULL, N= ULL); + if (ret < 0) { + key_put(appdata_key); + goto out_aead; + } + + /* Store the appdata before the key pointer */ + smp_store_release(&server->yfs_rxgk_appdata, appdata_key); + +out_aead: + crypto_free_aead(aead); +out_token: + kfree(appdata); +out: + return ret; +} +#endif /* CONFIG_RXGK */ + +/* + * Create the application data to go in a RESPONSE packet a server's CHALL= ENGE + * from the parameters contained in a key. The key specifies the security + * index and other appropriate parameters such as the encoding type for Rx= GK. + */ +int afs_create_server_appdata(struct afs_server *server, struct key *key) +{ + u32 krb5_enctype; + int ret; + u8 security_index; + + if (!key) + return 0; + + rxrpc_kernel_query_key(key, &security_index, &krb5_enctype); + + _enter("%u,%u", security_index, krb5_enctype); + + switch (security_index) { +#ifdef CONFIG_RXGK + case RXRPC_SECURITY_YFS_RXGK: + /* Read the key pointer before the appdata */ + if (smp_load_acquire(&server->yfs_rxgk_appdata)) + return 0; + break; +#endif + default: + return 0; + } + + ret =3D 0; + mutex_lock(&server->cm_token_lock); + + switch (security_index) { +#ifdef CONFIG_RXGK + case RXRPC_SECURITY_YFS_RXGK: + /* Read the key pointer before the appdata */ + if (smp_load_acquire(&server->yfs_rxgk_appdata)) + break; + ret =3D afs_create_yfs_rxgk_cm_appdata(server, krb5_enctype); + break; +#endif + default: + break; + } + + mutex_unlock(&server->cm_token_lock); + return ret; +} + /* * Respond to an RxGK challenge, adding appdata. */ diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index a91ad1938d07..e26f7f1e30a2 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c @@ -241,9 +241,14 @@ int afs_fs_probe_fileserver(struct afs_net *net, struc= t afs_server *server, struct afs_endpoint_state *estate, *old; struct afs_addr_list *old_alist =3D NULL, *alist; unsigned long unprobed; + int ret; =20 _enter("%pU", &server->uuid); =20 + ret =3D afs_create_server_appdata(server, key); + if (ret < 0) + return ret; + estate =3D kzalloc_obj(*estate); if (!estate) return -ENOMEM; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 645fe2f12dc5..d1c29593c5d0 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -548,6 +548,7 @@ struct afs_server { struct timer_list timer; /* Management timer */ struct mutex cm_token_lock; /* Lock governing creation of appdata */ struct krb5_buffer cm_rxgk_appdata; /* Appdata to be included in RESPONSE= packet */ + struct key *yfs_rxgk_appdata; /* Appdata to be included in RESPONSE pack= et */ time64_t unuse_time; /* Time at which last unused */ unsigned long flags; #define AFS_SERVER_FL_RESPONDING 0 /* The server is responding */ @@ -1088,6 +1089,7 @@ extern bool afs_cm_incoming_call(struct afs_call *); /* * cm_security.c */ +int afs_create_server_appdata(struct afs_server *server, struct key *key); void afs_process_oob_queue(struct work_struct *work); #ifdef CONFIG_RXGK int afs_create_token_key(struct afs_net *net, struct socket *socket); diff --git a/fs/afs/server.c b/fs/afs/server.c index 0fe162ea2a36..b08d9080b0c5 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c @@ -399,6 +399,7 @@ static void afs_server_rcu(struct rcu_head *rcu) afs_estate_trace_put_server); afs_put_cell(server->cell, afs_cell_trace_put_server); kfree(server->cm_rxgk_appdata.data); + key_put(server->yfs_rxgk_appdata); kfree(server); } =20 diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 0fb4c41c9bbf..c4b68049c06f 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -109,6 +109,8 @@ int rxkad_kernel_respond_to_challenge(struct sk_buff *c= hallenge); u32 rxgk_kernel_query_challenge(struct sk_buff *challenge); int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, struct krb5_buffer *appdata); +void rxrpc_kernel_query_key(const struct key *key, u8 *_security_index, + u32 *_krb5_enctype); u8 rxrpc_kernel_query_call_security(struct rxrpc_call *call, u16 *_service_id, u32 *_enctype); =20 diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c index a0aa78d89289..16bab72e6f07 100644 --- a/net/rxrpc/key.c +++ b/net/rxrpc/key.c @@ -893,3 +893,40 @@ static long rxrpc_read(const struct key *key, _leave(" =3D %zu", size); return size; } + +/** + * rxrpc_kernel_query_key - Query parameters from an rxrpc key + * @key: The key to query + * @_security_index: Where to return the security index + * @_krb5_enctype: Where to return the krb5 encryption type if applicable + * + * Query an rxrpc authentication key, extracting the security index from t= he + * first token therein. + */ +void rxrpc_kernel_query_key(const struct key *key, u8 *_security_index, + u32 *_krb5_enctype) +{ + const struct rxrpc_key_token *token; + + token =3D key->payload.data[0]; + if (!token) { + *_security_index =3D 0; + *_krb5_enctype =3D 0; + return; + } + + *_security_index =3D token->security_index; + switch (token->security_index) { + case RXRPC_SECURITY_RXKAD: + *_krb5_enctype =3D 0; + break; + case RXRPC_SECURITY_YFS_RXGK: + *_krb5_enctype =3D token->rxgk->enctype; + break; + default: + WARN_ON_ONCE(1); + *_krb5_enctype =3D 0; + break; + } +} +EXPORT_SYMBOL(rxrpc_kernel_query_key); From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 1D9CA3976A9 for ; Mon, 13 Jul 2026 08:13:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930384; cv=none; b=UCEV9Zh2658VsCK6FR5LztvOGiJDilQVJYtW2EiPErqqcWLsyUbRfjp7WSO+LIfzo+pyv4vpE7slGXPFkXLlYowCPQokYPDPylu0MTnXDSC+J8Cy6P+zX6B27cKV88x1DWN/WwjXwoL6u1ZkZr8UxtvbkZ2vNVB9XJIhwcAFhDY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930384; c=relaxed/simple; bh=hjblG8rYj5TurNeBosr/cb3t+768FiNWOJchBQ1RHWc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J5/kO3ZtlhawFN4Ca6QDCBbnKis44G/JsfFTwJ6Bajicr/52u+AoTLVHny6voUJRbWlEH2adu+0qKlmGfQNOCiHeN/9QlrEjvG16HmasFVM+WAkhlHi3wqBXeXo4nOVysMIaZ1W56TefutU3HWUXQeL9ZS3/vZ5sIrJTJxirx6s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=hFlDWMzT; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hFlDWMzT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930381; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6BC3CTSn22J1gLHfKAYR8Fk6H4HwrsCRZq+Yw3ufvMk=; b=hFlDWMzTARH84y7vDB+/XIeBpScYhjGhYOyu/J/YTrj+NPO8mmr2yED/dmnERAGU+KHmwn 4sU+tI84+SD5At76MxwtnK4X63WvsZId5BtURoXI1J+fSFa2iNETsyLAKfxyLv1x6Vktjz Yga6GCdtvhW2K5192Q5YhWY054OuRXE= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-335-7P4A0BZ6Pb-qyrCy6KpPhQ-1; Mon, 13 Jul 2026 04:11:32 -0400 X-MC-Unique: 7P4A0BZ6Pb-qyrCy6KpPhQ-1 X-Mimecast-MFC-AGG-ID: 7P4A0BZ6Pb-qyrCy6KpPhQ_1783930290 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3178D1955E7D; Mon, 13 Jul 2026 08:11:30 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6B987180058F; Mon, 13 Jul 2026 08:11:26 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , Jarkko Sakkinen , keyrings@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 12/14] rxrpc: Pass appdata key to rxrpc_call and thence to rxrpc_bundle Date: Mon, 13 Jul 2026 09:10:18 +0100 Message-ID: <20260713081022.2186481-13-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Currently, when a CHALLENGE packet comes in, it's queued in an OOB queue on the AF_RXRPC socket that generated one of the calls on that connection for the application (which might be in userspace) to service. The application then picks up the CHALLENGE and requests a RESPONSE packet be generated, allowing the app to include app-specific data in it if appropriate. There is, however, no actual limit on the capacity of the CHALLENGE queue, and this could be abused remotely - and also getting the OOB mechanism right has proven tricky. Further, by analogy with other AFS codebases, it's not actually necessary to generate the application data in response to the CHALLENGE. The reason I did this was to set the encryption on the app-data to be the same as that specified in the CHALLENGE as the server must be able to handle that. However, it's sufficient to use the encoding type set in the token that is going to be sent to the server; presumably the kerberos server knows that the fileserver can handle that type - otherwise why tell the client to use it? This is a part of the fix. With this, the appdata key created by the AFS filesystem or passed in via sendmsg CMSG to a user AF_RXRPC socket is added to an rxrpc_call struct and will then be added to an rxrpc_bundle struct. Note that afs_make_op_call() has to be moved so that it can call afs_use_server(). afs_operation-based calls did not heretofore 'use' the server and server will be 'un-used' by afs_free_call(). Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for = a RESPONSE") Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: Jarkko Sakkinen cc: linux-afs@lists.infradead.org cc: keyrings@vger.kernel.org cc: stable@kernel.org --- fs/afs/internal.h | 33 +++++++++++++++++---------------- fs/afs/rxrpc.c | 21 ++++++++++++++++++++- include/net/af_rxrpc.h | 1 + include/trace/events/afs.h | 1 + include/uapi/linux/rxrpc.h | 1 + net/rxrpc/af_rxrpc.c | 3 +++ net/rxrpc/ar-internal.h | 3 +++ net/rxrpc/call_object.c | 2 ++ net/rxrpc/conn_client.c | 2 ++ net/rxrpc/sendmsg.c | 25 ++++++++++++++++++++++++- 10 files changed, 74 insertions(+), 18 deletions(-) diff --git a/fs/afs/internal.h b/fs/afs/internal.h index d1c29593c5d0..57519888b978 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1414,22 +1414,6 @@ static inline void afs_see_call(struct afs_call *cal= l, enum afs_call_trace why) atomic_read(&call->net->nr_outstanding_calls)); } =20 -static inline void afs_make_op_call(struct afs_operation *op, struct afs_c= all *call, - gfp_t gfp) -{ - struct afs_addr_list *alist =3D op->estate->addresses; - - op->call =3D afs_get_call(call, afs_call_trace_get_op_call); - op->type =3D call->type; - call->op =3D op; - call->key =3D op->key; - call->intr =3D !(op->flags & AFS_OPERATION_UNINTR); - call->peer =3D rxrpc_kernel_get_peer(alist->addrs[op->addr_index].peer); - call->service_id =3D op->server->service_id; - afs_make_call(call, gfp); - afs_put_call(call, afs_call_trace_put_made_call); -} - static inline void afs_extract_begin(struct afs_call *call, void *buf, siz= e_t size) { call->iov_len =3D size; @@ -1749,6 +1733,23 @@ static inline struct inode *AFS_VNODE_TO_I(struct af= s_vnode *vnode) return &vnode->netfs.inode; } =20 +static inline void afs_make_op_call(struct afs_operation *op, struct afs_c= all *call, + gfp_t gfp) +{ + struct afs_addr_list *alist =3D op->estate->addresses; + + op->call =3D afs_get_call(call, afs_call_trace_get_op_call); + op->type =3D call->type; + call->op =3D op; + call->server =3D afs_use_server(op->server, false, afs_server_trace_use_c= all); + call->key =3D op->key; + call->intr =3D !(op->flags & AFS_OPERATION_UNINTR); + call->peer =3D rxrpc_kernel_get_peer(alist->addrs[op->addr_index].peer); + call->service_id =3D op->server->service_id; + afs_make_call(call, gfp); + afs_put_call(call, afs_call_trace_put_made_call); +} + /* * Note that a dentry got changed. We need to set d_fsdata to the data ve= rsion * number derived from the result of the operation. It doesn't matter if diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 6dc6fd853832..1a110448dbdb 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -312,6 +312,7 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) struct msghdr msg; struct kvec iov[1]; unsigned int debug_id =3D call->debug_id; + struct key *app_data =3D NULL; size_t len; bool write_iter =3D call->write_iter; s64 tx_total_len; @@ -342,8 +343,26 @@ void afs_make_call(struct afs_call *call, gfp_t gfp) if (call->async) afs_get_call(call, afs_call_trace_get_make_async_call); =20 + if (call->key && call->server) { + u32 krb5_enctype =3D 0; + u8 security_index =3D 0; + + rxrpc_kernel_query_key(call->key, &security_index, &krb5_enctype); + switch (security_index) { +#ifdef CONFIG_RXGK + case RXRPC_SECURITY_YFS_RXGK: + /* Read the key pointer before the appdata */ + app_data =3D smp_load_acquire(&call->server->yfs_rxgk_appdata); + break; +#endif + default: + break; + } + } + /* create a call */ - rxcall =3D rxrpc_kernel_begin_call(call->net->socket, call->peer, call->k= ey, + rxcall =3D rxrpc_kernel_begin_call(call->net->socket, call->peer, + call->key, app_data, (unsigned long)call, tx_total_len, call->max_lifespan, diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index c4b68049c06f..19c61a2f5af3 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -55,6 +55,7 @@ void rxrpc_kernel_set_notifications(struct socket *sock, struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, struct rxrpc_peer *peer, struct key *key, + struct key *app_data, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index a1963e21f034..a4f57414d527 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -160,6 +160,7 @@ enum yfs_cm_operation { EM(afs_server_trace_unuse_slist_isort, "UNU isort") \ EM(afs_server_trace_update, "UPDATE ") \ EM(afs_server_trace_use_by_uuid, "USE uuid ") \ + EM(afs_server_trace_use_call, "USE call ") \ EM(afs_server_trace_use_cm_call, "USE cm-cl") \ EM(afs_server_trace_use_get_caps, "USE gcaps") \ EM(afs_server_trace_use_give_up_cb, "USE gvupc") \ diff --git a/include/uapi/linux/rxrpc.h b/include/uapi/linux/rxrpc.h index d9735abd4c79..bcdfdf9c67a1 100644 --- a/include/uapi/linux/rxrpc.h +++ b/include/uapi/linux/rxrpc.h @@ -63,6 +63,7 @@ enum rxrpc_cmsg_type { RXRPC_RESPOND =3D 17, /* Cs-: Respond to a challenge */ RXRPC_RESPONDED =3D 18, /* S-r: Data received in RESPONSE */ RXRPC_RESP_RXGK_APPDATA =3D 19, /* Cs-: RESPONSE: RxGK app data to includ= e */ + RXRPC_RESPONSE_APPDATA =3D 20, /* Cs-: User key holding app data for RESP= ONSE */ RXRPC__SUPPORTED }; =20 diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 9ab0f22c881e..a19c0fd3c51a 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -318,6 +318,7 @@ EXPORT_SYMBOL(rxrpc_kernel_put_peer); * @sock: The socket on which to make the call * @peer: The peer to contact * @key: The security context to use (defaults to socket setting) + * @app_data: The security response application data (or NULL) * @user_call_ID: The ID to use * @tx_total_len: Total length of data to transmit during the call (or -1) * @hard_timeout: The maximum lifespan of the call in sec @@ -340,6 +341,7 @@ EXPORT_SYMBOL(rxrpc_kernel_put_peer); struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, struct rxrpc_peer *peer, struct key *key, + struct key *app_data, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, @@ -368,6 +370,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socke= t *sock, key =3D NULL; /* a no-security key */ =20 memset(&p, 0, sizeof(p)); + p.app_data =3D app_data; p.user_call_ID =3D user_call_ID; p.tx_total_len =3D tx_total_len; p.interruptibility =3D interruptibility; diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index b6e7e8c5e96f..20c10428a50e 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -516,6 +516,7 @@ struct rxrpc_bundle { struct rxrpc_local *local; /* Representation of local endpoint */ struct rxrpc_peer *peer; /* Remote endpoint */ struct key *key; /* Security details */ + struct key *app_data; /* Security response app data */ struct list_head proc_link; /* Link in net->bundle_proc_list */ const struct rxrpc_security *security; /* applied security module */ refcount_t ref; @@ -720,6 +721,7 @@ struct rxrpc_call { struct rxrpc_sock __rcu *socket; /* socket responsible */ struct rxrpc_net *rxnet; /* Network namespace to which call belongs */ struct key *key; /* Security details */ + struct key *app_data; /* Security response app data */ const struct rxrpc_security *security; /* applied security module */ struct mutex user_mutex; /* User access mutex */ struct sockaddr_rxrpc dest_srx; /* Destination address */ @@ -914,6 +916,7 @@ enum rxrpc_command { }; =20 struct rxrpc_call_params { + struct key *app_data; /* Security response app data */ s64 tx_total_len; /* Total Tx data length (if send data) */ unsigned long user_call_ID; /* User's call ID */ struct { diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 817ed9acb91e..9f6130d90c4c 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -211,6 +211,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struc= t rxrpc_sock *rx, call->interruptibility =3D p->interruptibility; call->tx_total_len =3D p->tx_total_len; call->key =3D key_get(cp->key); + call->app_data =3D key_get(p->app_data); call->peer =3D rxrpc_get_peer(cp->peer, rxrpc_peer_get_call); call->local =3D rxrpc_get_local(cp->local, rxrpc_local_get_call); call->security_level =3D cp->security_level; @@ -697,6 +698,7 @@ static void rxrpc_destroy_call(struct work_struct *work) rxrpc_put_peer(call->peer, rxrpc_peer_put_call); rxrpc_put_local(call->local, rxrpc_local_put_call); key_put(call->key); + key_put(call->app_data); call_rcu(&call->rcu, rxrpc_rcu_free_call); } =20 diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 48519f0de185..5cbfa7b223e0 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c @@ -81,6 +81,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxr= pc_call *call, bundle->local =3D call->local; bundle->peer =3D rxrpc_get_peer(call->peer, rxrpc_peer_get_bundle); bundle->key =3D key_get(call->key); + bundle->app_data =3D key_get(call->app_data); bundle->security =3D call->security; bundle->exclusive =3D test_bit(RXRPC_CALL_EXCLUSIVE, &call->flags); bundle->upgrade =3D test_bit(RXRPC_CALL_UPGRADE, &call->flags); @@ -118,6 +119,7 @@ static void rxrpc_free_bundle(struct rxrpc_bundle *bund= le) write_unlock(&bundle->local->rxnet->conn_lock); rxrpc_put_peer(bundle->peer, rxrpc_peer_put_bundle); key_put(bundle->key); + key_put(bundle->app_data); kfree(bundle); } =20 diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 71343998b87d..cdf35440317d 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -12,6 +12,7 @@ #include #include #include +#include =20 #include #include @@ -530,6 +531,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params= *p) { struct cmsghdr *cmsg; + key_serial_t key_id; + key_ref_t key; bool got_user_ID =3D false; int len; =20 @@ -614,6 +617,22 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, stru= ct rxrpc_send_params *p) return -ERANGE; break; =20 + case RXRPC_RESPONSE_APPDATA: + if (len !=3D sizeof(key_serial_t)) + return -EINVAL; + if (p->call.app_data) + return -EINVAL; + key_id =3D *(key_serial_t *)CMSG_DATA(cmsg); + key =3D lookup_user_key(key_id, 0, KEY_NEED_SEARCH); + if (IS_ERR(key)) + return PTR_ERR(key); + if (key_ref_to_ptr(key)->type =3D=3D &key_type_user) { + key_ref_put(key); + return -EINVAL; + } + p->call.app_data =3D key_ref_to_ptr(key); + break; + default: return -EINVAL; } @@ -722,8 +741,10 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msg= hdr *msg, size_t len) goto error_release_sock; call =3D rxrpc_new_client_call_for_sendmsg(rx, msg, &p); /* The socket is now unlocked... */ - if (IS_ERR(call)) + if (IS_ERR(call)) { + key_put(p.call.app_data); return PTR_ERR(call); + } /* ... and we have the call lock. */ p.call.nr_timeouts =3D 0; ret =3D 0; @@ -808,11 +829,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct ms= ghdr *msg, size_t len) mutex_unlock(&call->user_mutex); error_put: rxrpc_put_call(call, rxrpc_call_put_sendmsg); + key_put(p.call.app_data); _leave(" =3D %d", ret); return ret; =20 error_release_sock: release_sock(&rx->sk); + key_put(p.call.app_data); return ret; } From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 083BD3AE6E2 for ; Mon, 13 Jul 2026 08:11:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930304; cv=none; b=X7A0tnO1vhWMtipCWj17UktuuN84sECpQLt1XH3vMZobhtVcFTBi0e0CaQia8UWfurMixw43GeBmj6WdY6DFsHb+F2vZqlXBiZ+t1Vna5a55uLj+xAGWfl96X2R/jfj7Sn18vlm9pOwNRVUEB28T6qlVMycDcLaelY3lX09S59A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930304; c=relaxed/simple; bh=6guoQXDxMm7F31VXmZjPZiL+ySmq78h0iE6of3yYXPA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OvkNcxlxo9eH2IN4V6jnZdtkTRWgH/OuivFrxO6Hl0xeJM9Y1Sy/8GEV01A2PzW66zxG1x1jT8S41GRWrgLnkGoj3QThub9huljDi+NpNjY8qwr2CPQfic0bv4CHl9Ya/In5Zid1SzhzSP7q4/Mw2KDq7h2KcfC5GxOXKp0LvBg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=TZr/gD2I; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="TZr/gD2I" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930301; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eq7llsTmsWlajzQqjB1qgWIWN4J/21bO/XvtzoPCw4c=; b=TZr/gD2IcK467MuzaC+rguBXIvJ5wSykEy/leh1aIlM0cCVXRS9MGnV7jZlArUzQdeV/rr ymlcosb3UXTbU2a0jz6AJXJ1RkXHCSc/m/xAcMM88NyIWpq1mRGGZekiNZrEooachmFCIF kY+wFpPTokSIe/SVVUqhrn0I8ffGle0= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-347-bP9J2-YHOUq-DyM1wuBrSA-1; Mon, 13 Jul 2026 04:11:37 -0400 X-MC-Unique: bP9J2-YHOUq-DyM1wuBrSA-1 X-Mimecast-MFC-AGG-ID: bP9J2-YHOUq-DyM1wuBrSA_1783930295 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8D6FD19560A1; Mon, 13 Jul 2026 08:11:35 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C5E1919560A6; Mon, 13 Jul 2026 08:11:31 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , Jarkko Sakkinen , keyrings@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 13/14] rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation Date: Mon, 13 Jul 2026 09:10:19 +0100 Message-ID: <20260713081022.2186481-14-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Currently, when a CHALLENGE packet comes in, it's queued in an OOB queue on the AF_RXRPC socket that generated one of the calls on that connection for the application (which might be in userspace) to service. The application then picks up the CHALLENGE and requests a RESPONSE packet be generated, allowing the app to include app-specific data in it if appropriate. There is, however, no actual limit on the capacity of the CHALLENGE queue, and this could be abused remotely - and also getting the OOB mechanism right has proven tricky. Further, by analogy with other AFS codebases, it's not actually necessary to generate the application data in response to the CHALLENGE. The reason I did this was to set the encryption on the app-data to be the same as that specified in the CHALLENGE as the server must be able to handle that. However, it's sufficient to use the encoding type set in the token that is going to be sent to the server; presumably the kerberos server knows that the fileserver can handle that type - otherwise why tell the client to use it? This is the main part of the fix. It switches the code over from using the OOB communication mechanism to get the appdata on the fly from the application (either the AFS filesystem or userspace) to using the appdata key preemptively provided by the application. The following changes are made: (1) Revert to making the connection event processor work item parse the CHALLENGE and generate the RESPONSE directly. (2) Add another (optional) parameter that is passed in when an rxrpc client call is created and ends up attached to the connection bundle and is a user-type key containing the application data. (3) RESPONSE generation looks at the bundle and if the app-data is there, it will include it (if the security class is YFS-RxGK; RxKAD ignores it). The AFS filesystem driver creates an app-data key when it probes a fileserver and attaches it to the afs_server struct. This is picked up when a call is made to that server and thence passed to rxrpc. Direct userspace users of AF_RXRPC can partake by creating a user-type key containing the app-data they want to use and passing its serial ID in a CMSG of type RXRPC_RESPONSE_APPDATA in the initial sendmsg() of a call. Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for = a RESPONSE") Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: Jarkko Sakkinen cc: linux-afs@lists.infradead.org cc: keyrings@vger.kernel.org cc: stable@kernel.org --- net/rxrpc/af_rxrpc.c | 5 +--- net/rxrpc/conn_event.c | 68 ++---------------------------------------- net/rxrpc/recvmsg.c | 2 +- net/rxrpc/rxgk.c | 57 +++++++++++++++++++++-------------- 4 files changed, 39 insertions(+), 93 deletions(-) diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index a19c0fd3c51a..9eb6ca3c5ebf 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -598,10 +598,7 @@ static int rxrpc_sendmsg(struct socket *sock, struct m= sghdr *m, size_t len) fallthrough; case RXRPC_SERVER_BOUND: case RXRPC_SERVER_LISTENING: - if (m->msg_flags & MSG_OOB) - ret =3D rxrpc_sendmsg_oob(rx, m, len); - else - ret =3D rxrpc_do_sendmsg(rx, m, len); + ret =3D rxrpc_do_sendmsg(rx, m, len); /* The socket has been unlocked */ goto out; default: diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index 611c790bc6d0..9146b9d4c2ac 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c @@ -279,10 +279,7 @@ static int rxrpc_process_event(struct rxrpc_connection= *conn, =20 switch (sp->hdr.type) { case RXRPC_PACKET_TYPE_CHALLENGE: - ret =3D conn->security->respond_to_challenge(conn, skb); - sp->chall.conn =3D NULL; - rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input); - return ret; + return conn->security->respond_to_challenge(conn, skb); =20 case RXRPC_PACKET_TYPE_RESPONSE: spin_lock_irq(&conn->state_lock); @@ -425,66 +422,6 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_con= nection *conn, rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work); } =20 -/* - * Post a CHALLENGE packet to the socket of one of a connection's calls so= that - * it can get application data to include in the packet, possibly querying - * userspace. - */ -static bool rxrpc_post_challenge(struct rxrpc_connection *conn, - struct sk_buff *skb) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(skb); - struct rxrpc_call *call =3D NULL; - struct rxrpc_sock *rx; - bool respond =3D false, queued =3D false; - - sp->chall.conn =3D - rxrpc_get_connection(conn, rxrpc_conn_get_challenge_input); - - if (!conn->security->challenge_to_recvmsg) { - rxrpc_post_packet_to_conn(conn, skb); - return true; - } - - rcu_read_lock(); - - for (int i =3D 0; i < ARRAY_SIZE(conn->channels); i++) { - if (conn->channels[i].call) { - call =3D conn->channels[i].call; - rx =3D rcu_dereference(call->socket); - if (!rx) { - call =3D NULL; - continue; - } - - respond =3D true; - if (test_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags)) - break; - call =3D NULL; - } - } - - if (!respond) { - rcu_read_unlock(); - rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input); - sp->chall.conn =3D NULL; - return false; - } - - if (call) - queued =3D rxrpc_notify_socket_oob(call, skb); - rcu_read_unlock(); - if (call && !queued) { - rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input); - sp->chall.conn =3D NULL; - return false; - } - - if (!call) - rxrpc_post_packet_to_conn(conn, skb); - return true; -} - /* * Input a connection-level packet. */ @@ -513,7 +450,8 @@ bool rxrpc_input_conn_packet(struct rxrpc_connection *c= onn, struct sk_buff *skb) } if (!conn->security->validate_challenge(conn, skb)) return false; - return rxrpc_post_challenge(conn, skb); + rxrpc_post_packet_to_conn(conn, skb); + return true; =20 case RXRPC_PACKET_TYPE_RESPONSE: if (rxrpc_is_conn_aborted(conn)) { diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 28b2148b5693..33577522ec02 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -405,7 +405,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *m= sg, size_t len, =20 trace_rxrpc_recvmsg(0, rxrpc_recvmsg_enter, 0); =20 - if (flags & (MSG_OOB | MSG_TRUNC)) + if (flags & MSG_TRUNC) return -EOPNOTSUPP; =20 timeo =3D sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT); diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c index 77a67ace1d24..f3e085b64502 100644 --- a/net/rxrpc/rxgk.c +++ b/net/rxrpc/rxgk.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "ar-internal.h" #include "rxgk_common.h" =20 @@ -837,7 +838,7 @@ static noinline ssize_t rxgk_insert_response_header(str= uct rxrpc_connection *con */ static ssize_t rxgk_construct_authenticator(struct rxrpc_connection *conn, struct sk_buff *challenge, - const struct krb5_buffer *appdata, + const struct user_key_payload *appdata, struct sk_buff *response, size_t offset) { @@ -859,20 +860,20 @@ static ssize_t rxgk_construct_authenticator(struct rx= rpc_connection *conn, if (ret < 0) return -EPROTO; =20 - a.appdata_len =3D htonl(appdata->len); + a.appdata_len =3D htonl(appdata->datalen); =20 ret =3D skb_store_bits(response, offset, &a, sizeof(a)); if (ret < 0) return ret; offset +=3D sizeof(a); =20 - if (appdata->len) { - ret =3D skb_store_bits(response, offset, appdata->data, appdata->len); + if (appdata->datalen) { + ret =3D skb_store_bits(response, offset, appdata->data, appdata->datalen= ); if (ret < 0) return ret; - offset +=3D appdata->len; + offset +=3D appdata->datalen; =20 - ret =3D rxgk_pad_out(response, appdata->len, offset); + ret =3D rxgk_pad_out(response, appdata->datalen, offset); if (ret < 0) return ret; offset +=3D ret; @@ -890,7 +891,7 @@ static ssize_t rxgk_construct_authenticator(struct rxrp= c_connection *conn, ret =3D skb_store_bits(response, offset, &b, sizeof(b)); if (ret < 0) return ret; - return sizeof(a) + xdr_round_up(appdata->len) + sizeof(b); + return sizeof(a) + xdr_round_up(appdata->datalen) + sizeof(b); } =20 static ssize_t rxgk_encrypt_authenticator(struct rxrpc_connection *conn, @@ -923,7 +924,7 @@ static ssize_t rxgk_encrypt_authenticator(struct rxrpc_= connection *conn, */ static int rxgk_construct_response(struct rxrpc_connection *conn, struct sk_buff *challenge, - struct krb5_buffer *appdata) + const struct user_key_payload *appdata) { struct rxrpc_skb_priv *csp, *rsp; struct rxgk_context *gk; @@ -936,7 +937,7 @@ static int rxgk_construct_response(struct rxrpc_connect= ion *conn, if (IS_ERR(gk)) return PTR_ERR(gk); =20 - auth_len =3D 20 + (4 + appdata->len) + 12 + (1 + 4) * 4; + auth_len =3D 20 + (4 + appdata->datalen) + 12 + (1 + 4) * 4; authx_len =3D crypto_krb5_how_much_buffer(gk->krb5, KRB5_ENCRYPT_MODE, auth_len, &auth_offset); len =3D sizeof(struct rxrpc_wire_header) + @@ -1011,24 +1012,36 @@ static int rxgk_construct_response(struct rxrpc_con= nection *conn, * Respond to a challenge packet. */ static int rxgk_respond_to_challenge(struct rxrpc_connection *conn, - struct sk_buff *challenge, - struct krb5_buffer *appdata) + struct sk_buff *challenge) { - _enter("{%d,%x}", conn->debug_id, key_serial(conn->key)); + struct user_key_payload dummy =3D {}, *appdata =3D &dummy; + int ret; + + _enter("{%d,%u,%x,%x}", + conn->debug_id, conn->service_id, + key_serial(conn->key), key_serial(conn->bundle->app_data)); =20 if (key_validate(conn->key) < 0) return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EPROTO, rxgk_abort_chall_key_expired); =20 - return rxgk_construct_response(conn, challenge, appdata); -} + if (conn->bundle->app_data) { + rcu_read_lock(); + appdata =3D (struct user_key_payload *) + user_key_payload_rcu(conn->bundle->app_data); + if (appdata && !refcount_inc_not_zero(&appdata->ref)) + appdata =3D NULL; + rcu_read_unlock(); + if (!appdata) + return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EKEYREVOKED, + rxgk_abort_chall_key_expired); + } =20 -static int rxgk_respond_to_challenge_no_appdata(struct rxrpc_connection *c= onn, - struct sk_buff *challenge) -{ - struct krb5_buffer appdata =3D {}; + ret =3D rxgk_construct_response(conn, challenge, appdata); =20 - return rxgk_respond_to_challenge(conn, challenge, &appdata); + if (appdata !=3D &dummy) + put_user_key_payload(appdata); + return ret; } =20 /** @@ -1044,9 +1057,7 @@ static int rxgk_respond_to_challenge_no_appdata(struc= t rxrpc_connection *conn, int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, struct krb5_buffer *appdata) { - struct rxrpc_skb_priv *csp =3D rxrpc_skb(challenge); - - return rxgk_respond_to_challenge(csp->chall.conn, challenge, appdata); + return -EINVAL; } EXPORT_SYMBOL(rxgk_kernel_respond_to_challenge); =20 @@ -1348,7 +1359,7 @@ const struct rxrpc_security rxgk_yfs =3D { .validate_challenge =3D rxgk_validate_challenge, .challenge_to_recvmsg =3D rxgk_challenge_to_recvmsg, .sendmsg_respond_to_challenge =3D rxgk_sendmsg_respond_to_challenge, - .respond_to_challenge =3D rxgk_respond_to_challenge_no_appdata, + .respond_to_challenge =3D rxgk_respond_to_challenge, .verify_response =3D rxgk_verify_response, .clear =3D rxgk_clear, .default_decode_ticket =3D rxgk_yfs_decode_ticket, From nobody Sat Jul 25 22:03:06 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 50C6F3A5E97 for ; Mon, 13 Jul 2026 08:11:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930313; cv=none; b=d+c6J7fOPwJ0AFBItKHRKoEEZNKj/MJVpOnPFV3/ABa6xRjecLZweDQZEiBDZrxNzW+RZRMhhe6iU9FHcQuZZYafHfI2faE3OtlJBz9xoEeeHb4Ye3Vo+ycJe6tF9DDKGh5MIgi1lqsVsTO+IbrPEtpQt3T/Vt0IXyrwsIG4gP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783930313; c=relaxed/simple; bh=TfQaVtT/FW+kTbxJ2TnriDXc0tQS/NqNt9yuWEZaayo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RGl2RPAWMLniyoOgVubh+LuvWuDTH0Tj+wYTZAPzLdXCXysZYoW3unqug9JF3skuKO9ANJzxPFdR6gvZ0qEWaJ1fLPemi5a49G1PDbBEwx+Sng14X8I+4WCQ/s4t/16qbUG2X/DwfqOKqZAUFr5WmuV+/8D4BQb4Tr6ssq3rRcc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MCMYRwR3; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MCMYRwR3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783930309; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lPbJLKojtqChersHmPMPuesLkjZ3DrJaObEVkz5GVz0=; b=MCMYRwR3BvnrTMRUmMHsZctTn0ocB4QrgYIJ8VQTZoyqszN1I/R/qxbVRNeB+n4xYO3ICD axVCutXfeWrGfhvnIGVsspMKJYzzrujcsWShA4SPpl7qJFaK+gHaqCbzvqKU3ZqpbA2tdn VzoBmnjfTCt143DkDxUoFd2zvg9klAE= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-678-Gj_xcE-aNAekCjgvuCxNgA-1; Mon, 13 Jul 2026 04:11:43 -0400 X-MC-Unique: Gj_xcE-aNAekCjgvuCxNgA-1 X-Mimecast-MFC-AGG-ID: Gj_xcE-aNAekCjgvuCxNgA_1783930301 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7A31A18001FB; Mon, 13 Jul 2026 08:11:41 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.33.159]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3E28830001A1; Mon, 13 Jul 2026 08:11:37 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org, Jeffrey Altman , Jarkko Sakkinen , keyrings@vger.kernel.org, stable@kernel.org Subject: [PATCH net v3 14/14] rxrpc: Remove OOB challenge/response code Date: Mon, 13 Jul 2026 09:10:20 +0100 Message-ID: <20260713081022.2186481-15-dhowells@redhat.com> In-Reply-To: <20260713081022.2186481-1-dhowells@redhat.com> References: <20260713081022.2186481-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Currently, when a CHALLENGE packet comes in, it's queued in an OOB queue on the AF_RXRPC socket that generated one of the calls on that connection for the application (which might be in userspace) to service. The application then picks up the CHALLENGE and requests a RESPONSE packet be generated, allowing the app to include app-specific data in it if appropriate. There is, however, no actual limit on the capacity of the CHALLENGE queue, and this could be abused remotely - and also getting the OOB mechanism right has proven tricky. Further, by analogy with other AFS codebases, it's not actually necessary to generate the application data in response to the CHALLENGE. The reason I did this was to set the encryption on the app-data to be the same as that specified in the CHALLENGE as the server must be able to handle that. However, it's sufficient to use the encoding type set in the token that is going to be sent to the server; presumably the kerberos server knows that the fileserver can handle that type - otherwise why tell the client to use it? This is the final part of the fix. It removes all the OOB communication stuff along with the UAPI elements related to them. Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for = a RESPONSE") Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Marc Dionne cc: Jeffrey Altman cc: Eric Dumazet cc: "David S. Miller" cc: Jakub Kicinski cc: Paolo Abeni cc: Simon Horman cc: Jarkko Sakkinen cc: linux-afs@lists.infradead.org cc: keyrings@vger.kernel.org cc: stable@kernel.org --- fs/afs/cm_security.c | 259 ----------------------- fs/afs/internal.h | 3 - fs/afs/main.c | 1 - fs/afs/rxrpc.c | 19 -- fs/afs/server.c | 1 - include/net/af_rxrpc.h | 18 -- include/trace/events/rxrpc.h | 2 - include/uapi/linux/rxrpc.h | 5 - net/rxrpc/Makefile | 1 - net/rxrpc/af_rxrpc.c | 41 +--- net/rxrpc/ar-internal.h | 19 -- net/rxrpc/oob.c | 387 ----------------------------------- net/rxrpc/recvmsg.c | 82 +------- net/rxrpc/rxgk.c | 73 ------- net/rxrpc/rxkad.c | 27 --- net/rxrpc/server_key.c | 40 ---- 16 files changed, 5 insertions(+), 973 deletions(-) delete mode 100644 net/rxrpc/oob.c diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c index 36907a04efd0..f0fec3a76522 100644 --- a/fs/afs/cm_security.c +++ b/fs/afs/cm_security.c @@ -20,11 +20,6 @@ #define xdr_round_up(x) (round_up((x), sizeof(__be32))) #define xdr_len_object(x) (4 + round_up((x), sizeof(__be32))) =20 -#ifdef CONFIG_RXGK -static int afs_create_yfs_cm_token(struct sk_buff *challenge, - struct afs_server *server); -#endif - #ifdef CONFIG_RXGK /* * As the YFS RxGK appdata to be passed in the YFS.FS-service RESPONSE pac= ket, @@ -255,95 +250,6 @@ int afs_create_server_appdata(struct afs_server *serve= r, struct key *key) return ret; } =20 -/* - * Respond to an RxGK challenge, adding appdata. - */ -static int afs_respond_to_challenge(struct sk_buff *challenge) -{ -#ifdef CONFIG_RXGK - struct krb5_buffer appdata =3D {}; - struct afs_server *server; -#endif - struct rxrpc_peer *peer; - unsigned long peer_data; - u16 service_id; - u8 security_index; - - rxrpc_kernel_query_challenge(challenge, &peer, &peer_data, - &service_id, &security_index); - - _enter("%u,%u", service_id, security_index); - - switch (service_id) { - /* We don't send CM_SERVICE RPCs, so don't expect a challenge - * therefrom. - */ - case FS_SERVICE: - case VL_SERVICE: - case YFS_FS_SERVICE: - case YFS_VL_SERVICE: - break; - default: - pr_warn("Can't respond to unknown challenge %u:%u", - service_id, security_index); - return rxrpc_kernel_reject_challenge(challenge, RX_USER_ABORT, -EPROTO, - afs_abort_unsupported_sec_class); - } - - switch (security_index) { -#ifdef CONFIG_RXKAD - case RXRPC_SECURITY_RXKAD: - return rxkad_kernel_respond_to_challenge(challenge); -#endif - -#ifdef CONFIG_RXGK - case RXRPC_SECURITY_RXGK: - return rxgk_kernel_respond_to_challenge(challenge, &appdata); - - case RXRPC_SECURITY_YFS_RXGK: - switch (service_id) { - case FS_SERVICE: - case YFS_FS_SERVICE: - server =3D (struct afs_server *)peer_data; - if (!server->cm_rxgk_appdata.data) { - mutex_lock(&server->cm_token_lock); - if (!server->cm_rxgk_appdata.data) - afs_create_yfs_cm_token(challenge, server); - mutex_unlock(&server->cm_token_lock); - } - if (server->cm_rxgk_appdata.data) - appdata =3D server->cm_rxgk_appdata; - break; - } - return rxgk_kernel_respond_to_challenge(challenge, &appdata); -#endif - - default: - return rxrpc_kernel_reject_challenge(challenge, RX_USER_ABORT, -EPROTO, - afs_abort_unsupported_sec_class); - } -} - -/* - * Process the OOB message queue, processing challenge packets. - */ -void afs_process_oob_queue(struct work_struct *work) -{ - struct afs_net *net =3D container_of(work, struct afs_net, rx_oob_work); - struct sk_buff *oob; - enum rxrpc_oob_type type; - - while (READ_ONCE(net->live) && - (oob =3D rxrpc_kernel_dequeue_oob(net->socket, &type))) { - switch (type) { - case RXRPC_OOB_CHALLENGE: - afs_respond_to_challenge(oob); - break; - } - rxrpc_kernel_free_oob(oob); - } -} - #ifdef CONFIG_RXGK /* * Create a securities keyring for the cache manager and attach a key to i= t for @@ -405,169 +311,4 @@ int afs_create_token_key(struct afs_net *net, struct = socket *socket) key_put(ring); return ret; } - -/* - * Create an YFS RxGK GSS token to use as a ticket to the specified filese= rver. - */ -static int afs_create_yfs_cm_token(struct sk_buff *challenge, - struct afs_server *server) -{ - const struct krb5_enctype *conn_krb5, *token_krb5; - const struct krb5_buffer *token_key; - struct crypto_aead *aead; - struct scatterlist sg; - struct afs_net *net =3D server->cell->net; - const struct key *key =3D net->fs_cm_token_key; - size_t keysize, uuidsize, authsize, toksize, encsize, contsize, adatasize= , offset; - __be32 caps[1] =3D { - [0] =3D htonl(AFS_CAP_ERROR_TRANSLATION), - }; - __be32 *xdr; - void *appdata, *K0, *encbase; - u32 enctype; - int ret; - - if (!key) - return -ENOKEY; - - /* Assume that the fileserver is happy to use the same encoding type as - * we were told to use by the token obtained by the user. - */ - enctype =3D rxgk_kernel_query_challenge(challenge); - - conn_krb5 =3D crypto_krb5_find_enctype(enctype); - if (!conn_krb5) - return -ENOPKG; - token_krb5 =3D key->payload.data[0]; - token_key =3D (const struct krb5_buffer *)&key->payload.data[2]; - - /* struct rxgk_key { - * afs_uint32 enctype; - * opaque key<>; - * }; - */ - keysize =3D 4 + xdr_len_object(conn_krb5->key_len); - - /* struct RXGK_AuthName { - * afs_int32 kind; - * opaque data; - * opaque display; - * }; - */ - uuidsize =3D sizeof(server->uuid); - authsize =3D 4 + xdr_len_object(uuidsize) + xdr_len_object(0); - - /* struct RXGK_Token { - * rxgk_key K0; - * RXGK_Level level; - * rxgkTime starttime; - * afs_int32 lifetime; - * afs_int32 bytelife; - * rxgkTime expirationtime; - * struct RXGK_AuthName identities<>; - * }; - */ - toksize =3D keysize + 8 + 4 + 4 + 8 + xdr_len_object(authsize); - - offset =3D 0; - encsize =3D crypto_krb5_how_much_buffer(token_krb5, KRB5_ENCRYPT_MODE, to= ksize, &offset); - - /* struct RXGK_TokenContainer { - * afs_int32 kvno; - * afs_int32 enctype; - * opaque encrypted_token<>; - * }; - */ - contsize =3D 4 + 4 + xdr_len_object(encsize); - - /* struct YFSAppData { - * opr_uuid initiatorUuid; - * opr_uuid acceptorUuid; - * Capabilities caps; - * afs_int32 enctype; - * opaque callbackKey<>; - * opaque callbackToken<>; - * }; - */ - adatasize =3D 16 + 16 + - xdr_len_object(sizeof(caps)) + - 4 + - xdr_len_object(conn_krb5->key_len) + - xdr_len_object(contsize); - - ret =3D -ENOMEM; - appdata =3D kzalloc(adatasize, GFP_KERNEL); - if (!appdata) - goto out; - xdr =3D appdata; - - memcpy(xdr, &net->uuid, 16); /* appdata.initiatorUuid */ - xdr +=3D 16 / 4; - memcpy(xdr, &server->uuid, 16); /* appdata.acceptorUuid */ - xdr +=3D 16 / 4; - *xdr++ =3D htonl(ARRAY_SIZE(caps)); /* appdata.caps.len */ - memcpy(xdr, &caps, sizeof(caps)); /* appdata.caps */ - xdr +=3D ARRAY_SIZE(caps); - *xdr++ =3D htonl(conn_krb5->etype); /* appdata.enctype */ - - *xdr++ =3D htonl(conn_krb5->key_len); /* appdata.callbackKey.len */ - K0 =3D xdr; - get_random_bytes(K0, conn_krb5->key_len); /* appdata.callbackKey.data */ - xdr +=3D xdr_round_up(conn_krb5->key_len) / 4; - - *xdr++ =3D htonl(contsize); /* appdata.callbackToken.len */ - *xdr++ =3D htonl(1); /* cont.kvno */ - *xdr++ =3D htonl(token_krb5->etype); /* cont.enctype */ - *xdr++ =3D htonl(encsize); /* cont.encrypted_token.len */ - - encbase =3D xdr; - xdr +=3D offset / 4; - *xdr++ =3D htonl(conn_krb5->etype); /* token.K0.enctype */ - *xdr++ =3D htonl(conn_krb5->key_len); /* token.K0.key.len */ - memcpy(xdr, K0, conn_krb5->key_len); /* token.K0.key.data */ - xdr +=3D xdr_round_up(conn_krb5->key_len) / 4; - - *xdr++ =3D htonl(RXRPC_SECURITY_ENCRYPT); /* token.level */ - *xdr++ =3D htonl(0); /* token.starttime */ - *xdr++ =3D htonl(0); /* " */ - *xdr++ =3D htonl(0); /* token.lifetime */ - *xdr++ =3D htonl(0); /* token.bytelife */ - *xdr++ =3D htonl(0); /* token.expirationtime */ - *xdr++ =3D htonl(0); /* " */ - *xdr++ =3D htonl(1); /* token.identities.count */ - *xdr++ =3D htonl(0); /* token.identities[0].kind */ - *xdr++ =3D htonl(uuidsize); /* token.identities[0].data.len */ - memcpy(xdr, &server->uuid, uuidsize); - xdr +=3D xdr_round_up(uuidsize) / 4; - *xdr++ =3D htonl(0); /* token.identities[0].display.len */ - - xdr =3D encbase + xdr_round_up(encsize); - - if ((unsigned long)xdr - (unsigned long)appdata !=3D adatasize) - pr_err("Appdata size incorrect %lx !=3D %zx\n", - (unsigned long)xdr - (unsigned long)appdata, adatasize); - - aead =3D crypto_krb5_prepare_encryption(token_krb5, token_key, RXGK_SERVE= R_ENC_TOKEN, - GFP_KERNEL); - if (IS_ERR(aead)) { - ret =3D PTR_ERR(aead); - goto out_token; - } - - sg_init_one(&sg, encbase, encsize); - ret =3D crypto_krb5_encrypt(token_krb5, aead, &sg, 1, encsize, offset, to= ksize, false); - if (ret < 0) - goto out_aead; - - server->cm_rxgk_appdata.len =3D adatasize; - server->cm_rxgk_appdata.data =3D appdata; - appdata =3D NULL; - -out_aead: - crypto_free_aead(aead); -out_token: - kfree(appdata); -out: - return ret; -} #endif /* CONFIG_RXGK */ diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 57519888b978..9322234ce7f7 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -282,7 +282,6 @@ struct afs_net { struct socket *socket; struct afs_call *spare_incoming_call; struct work_struct charge_preallocation_work; - struct work_struct rx_oob_work; struct mutex socket_mutex; atomic_t nr_outstanding_calls; atomic_t nr_superblocks; @@ -547,7 +546,6 @@ struct afs_server { struct work_struct destroyer; /* Work item to try and destroy a server */ struct timer_list timer; /* Management timer */ struct mutex cm_token_lock; /* Lock governing creation of appdata */ - struct krb5_buffer cm_rxgk_appdata; /* Appdata to be included in RESPONSE= packet */ struct key *yfs_rxgk_appdata; /* Appdata to be included in RESPONSE pack= et */ time64_t unuse_time; /* Time at which last unused */ unsigned long flags; @@ -1090,7 +1088,6 @@ extern bool afs_cm_incoming_call(struct afs_call *); * cm_security.c */ int afs_create_server_appdata(struct afs_server *server, struct key *key); -void afs_process_oob_queue(struct work_struct *work); #ifdef CONFIG_RXGK int afs_create_token_key(struct afs_net *net, struct socket *socket); #else diff --git a/fs/afs/main.c b/fs/afs/main.c index 7a883c59976f..6353feaa5fb4 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c @@ -73,7 +73,6 @@ static int __net_init afs_net_init(struct net *net_ns) generate_random_uuid((unsigned char *)&net->uuid); =20 INIT_WORK(&net->charge_preallocation_work, afs_charge_preallocation); - INIT_WORK(&net->rx_oob_work, afs_process_oob_queue); mutex_init(&net->socket_mutex); =20 net->cells =3D RB_ROOT; diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 1a110448dbdb..4f6d699b5d22 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -25,14 +25,12 @@ static void afs_process_async_call(struct work_struct *= ); static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned l= ong); static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long); static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_ca= ll_ID); -static void afs_rx_notify_oob(struct sock *sk, struct sk_buff *oob); static int afs_deliver_cm_op_id(struct afs_call *); =20 static const struct rxrpc_kernel_ops afs_rxrpc_callback_ops =3D { .notify_new_call =3D afs_rx_new_call, .discard_new_call =3D afs_rx_discard_new_call, .user_attach_call =3D afs_rx_attach, - .notify_oob =3D afs_rx_notify_oob, }; =20 /* asynchronous incoming call initial processing */ @@ -74,10 +72,6 @@ int afs_open_socket(struct afs_net *net) if (ret < 0) goto error_2; =20 - ret =3D rxrpc_sock_set_manage_response(socket->sk, true); - if (ret < 0) - goto error_2; - ret =3D afs_create_token_key(net, socket); if (ret < 0) pr_err("Couldn't create RxGK CM key: %d\n", ret); @@ -128,7 +122,6 @@ void afs_close_socket(struct afs_net *net) _enter(""); =20 cancel_work_sync(&net->charge_preallocation_work); - cancel_work_sync(&net->rx_oob_work); /* Future work items should now see ->live is false. */ =20 kernel_listen(net->socket, 0); @@ -149,7 +142,6 @@ void afs_close_socket(struct afs_net *net) =20 kernel_sock_shutdown(net->socket, SHUT_RDWR); flush_workqueue(afs_async_calls); - cancel_work_sync(&net->rx_oob_work); net->socket->sk->sk_user_data =3D NULL; sock_release(net->socket); key_put(net->fs_cm_token_key); @@ -963,14 +955,3 @@ noinline int afs_protocol_error(struct afs_call *call, call->unmarshalling_error =3D true; return -EBADMSG; } - -/* - * Wake up OOB notification processing. - */ -static void afs_rx_notify_oob(struct sock *sk, struct sk_buff *oob) -{ - struct afs_net *net =3D sk->sk_user_data; - - if (READ_ONCE(net->live)) - queue_work(afs_wq, &net->rx_oob_work); -} diff --git a/fs/afs/server.c b/fs/afs/server.c index b08d9080b0c5..4c3a7bd0f7d8 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c @@ -398,7 +398,6 @@ static void afs_server_rcu(struct rcu_head *rcu) afs_put_endpoint_state(rcu_access_pointer(server->endpoint_state), afs_estate_trace_put_server); afs_put_cell(server->cell, afs_cell_trace_put_server); - kfree(server->cm_rxgk_appdata.data); key_put(server->yfs_rxgk_appdata); kfree(server); } diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 19c61a2f5af3..a9b8e1ba67ef 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -92,24 +92,6 @@ bool rxrpc_kernel_check_life(const struct socket *, cons= t struct rxrpc_call *); =20 int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val); int rxrpc_sock_set_security_keyring(struct sock *, struct key *); -int rxrpc_sock_set_manage_response(struct sock *sk, bool set); - -enum rxrpc_oob_type rxrpc_kernel_query_oob(struct sk_buff *oob, - struct rxrpc_peer **_peer, - unsigned long *_peer_appdata); -struct sk_buff *rxrpc_kernel_dequeue_oob(struct socket *sock, - enum rxrpc_oob_type *_type); -void rxrpc_kernel_free_oob(struct sk_buff *oob); -void rxrpc_kernel_query_challenge(struct sk_buff *challenge, - struct rxrpc_peer **_peer, - unsigned long *_peer_appdata, - u16 *_service_id, u8 *_security_index); -int rxrpc_kernel_reject_challenge(struct sk_buff *challenge, u32 abort_cod= e, - int error, enum rxrpc_abort_reason why); -int rxkad_kernel_respond_to_challenge(struct sk_buff *challenge); -u32 rxgk_kernel_query_challenge(struct sk_buff *challenge); -int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, - struct krb5_buffer *appdata); void rxrpc_kernel_query_key(const struct key *key, u8 *_security_index, u32 *_krb5_enctype); u8 rxrpc_kernel_query_call_security(struct rxrpc_call *call, diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index d7c7b04d69fc..45e4550a18ed 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -263,7 +263,6 @@ EM(rxrpc_conn_free, "FREE ") \ EM(rxrpc_conn_get_activate_call, "GET act-call") \ EM(rxrpc_conn_get_call_input, "GET inp-call") \ - EM(rxrpc_conn_get_challenge_input, "GET inp-chal") \ EM(rxrpc_conn_get_conn_input, "GET inp-conn") \ EM(rxrpc_conn_get_idle, "GET idle ") \ EM(rxrpc_conn_get_poke_abort, "GET pk-abort") \ @@ -275,7 +274,6 @@ EM(rxrpc_conn_new_service, "NEW service ") \ EM(rxrpc_conn_put_call, "PUT call ") \ EM(rxrpc_conn_put_call_input, "PUT inp-call") \ - EM(rxrpc_conn_put_challenge_input, "PUT inp-chal") \ EM(rxrpc_conn_put_conn_input, "PUT inp-conn") \ EM(rxrpc_conn_put_discard_idle, "PUT disc-idl") \ EM(rxrpc_conn_put_local_dead, "PUT loc-dead") \ diff --git a/include/uapi/linux/rxrpc.h b/include/uapi/linux/rxrpc.h index bcdfdf9c67a1..7d6a50151931 100644 --- a/include/uapi/linux/rxrpc.h +++ b/include/uapi/linux/rxrpc.h @@ -58,11 +58,6 @@ enum rxrpc_cmsg_type { RXRPC_TX_LENGTH =3D 12, /* -s-: Total length of Tx data */ RXRPC_SET_CALL_TIMEOUT =3D 13, /* -s-: Set one or more call timeouts */ RXRPC_CHARGE_ACCEPT =3D 14, /* Ss-: Charge the accept pool with a user ca= ll ID */ - RXRPC_OOB_ID =3D 15, /* -sr: OOB message ID */ - RXRPC_CHALLENGED =3D 16, /* C-r: Info on a received CHALLENGE */ - RXRPC_RESPOND =3D 17, /* Cs-: Respond to a challenge */ - RXRPC_RESPONDED =3D 18, /* S-r: Data received in RESPONSE */ - RXRPC_RESP_RXGK_APPDATA =3D 19, /* Cs-: RESPONSE: RxGK app data to includ= e */ RXRPC_RESPONSE_APPDATA =3D 20, /* Cs-: User key holding app data for RESP= ONSE */ RXRPC__SUPPORTED }; diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index f994f9f30a29..f7a5e0a592ee 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile @@ -24,7 +24,6 @@ rxrpc-y :=3D \ local_object.o \ misc.o \ net_ns.o \ - oob.o \ output.o \ peer_event.o \ peer_object.o \ diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 9eb6ca3c5ebf..9d5ce1c7ad0d 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -633,7 +633,7 @@ static int rxrpc_setsockopt(struct socket *sock, int le= vel, int optname, sockptr_t optval, unsigned int optlen) { struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); - unsigned int min_sec_level, val; + unsigned int min_sec_level; u16 service_upgrade[2]; int ret; =20 @@ -710,23 +710,7 @@ static int rxrpc_setsockopt(struct socket *sock, int l= evel, int optname, =20 case RXRPC_MANAGE_RESPONSE: ret =3D -EINVAL; - if (optlen !=3D sizeof(unsigned int)) - goto error; - ret =3D -EISCONN; - if (rx->sk.sk_state !=3D RXRPC_UNBOUND) - goto error; - ret =3D copy_safe_from_sockptr(&val, sizeof(val), - optval, optlen); - if (ret) - goto error; - ret =3D -EINVAL; - if (val > 1) - goto error; - if (val) - set_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags); - else - clear_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags); - goto success; + goto error; =20 default: break; @@ -835,8 +819,6 @@ static int rxrpc_create(struct net *net, struct socket = *sock, int protocol, rx->calls =3D RB_ROOT; =20 spin_lock_init(&rx->incoming_lock); - skb_queue_head_init(&rx->recvmsg_oobq); - rx->pending_oobq =3D RB_ROOT; INIT_LIST_HEAD(&rx->sock_calls); INIT_LIST_HEAD(&rx->to_be_accepted); INIT_LIST_HEAD(&rx->recvmsg_q); @@ -884,23 +866,6 @@ static int rxrpc_shutdown(struct socket *sock, int fla= gs) return ret; } =20 -/* - * Purge the out-of-band queue. - */ -static void rxrpc_purge_oob_queue(struct sock *sk) -{ - struct rxrpc_sock *rx =3D rxrpc_sk(sk); - struct sk_buff *skb; - - while ((skb =3D skb_dequeue(&rx->recvmsg_oobq))) - rxrpc_kernel_free_oob(skb); - while (!RB_EMPTY_ROOT(&rx->pending_oobq)) { - skb =3D rb_entry(rx->pending_oobq.rb_node, struct sk_buff, rbnode); - rb_erase(&skb->rbnode, &rx->pending_oobq); - rxrpc_kernel_free_oob(skb); - } -} - /* * RxRPC socket destructor */ @@ -908,7 +873,6 @@ static void rxrpc_sock_destructor(struct sock *sk) { _enter("%p", sk); =20 - rxrpc_purge_oob_queue(sk); rxrpc_purge_queue(&sk->sk_receive_queue); =20 WARN_ON(refcount_read(&sk->sk_wmem_alloc)); @@ -961,7 +925,6 @@ static int rxrpc_release_sock(struct sock *sk) rxrpc_discard_prealloc(rx); rxrpc_release_calls_on_socket(rx); flush_workqueue(rxrpc_workqueue); - rxrpc_purge_oob_queue(sk); rxrpc_purge_queue(&sk->sk_receive_queue); =20 rxrpc_unuse_local(rx->local, rxrpc_local_unuse_release_sock); diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 20c10428a50e..1c6f4a279034 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -171,9 +171,6 @@ struct rxrpc_sock { const struct rxrpc_kernel_ops *app_ops; /* Table of kernel app notificati= on funcs */ struct rxrpc_local *local; /* local endpoint */ struct rxrpc_backlog *backlog; /* Preallocation for services */ - struct sk_buff_head recvmsg_oobq; /* OOB messages for recvmsg to pick up = */ - struct rb_root pending_oobq; /* OOB messages awaiting userspace to respo= nd to */ - u64 oob_id_counter; /* OOB message ID counter */ spinlock_t incoming_lock; /* Incoming call vs service shutdown lock */ struct list_head sock_calls; /* List of calls owned by this socket */ struct list_head to_be_accepted; /* calls awaiting acceptance */ @@ -184,7 +181,6 @@ struct rxrpc_sock { struct rb_root calls; /* User ID -> call mapping */ unsigned long flags; #define RXRPC_SOCK_CONNECTED 0 /* connect_srx is set */ -#define RXRPC_SOCK_MANAGE_RESPONSE 1 /* User wants to manage RESPONSE pack= ets */ rwlock_t call_lock; /* lock for calls */ u32 min_sec_level; /* minimum security level */ #define RXRPC_SECURITY_MAX RXRPC_SECURITY_ENCRYPT @@ -241,7 +237,6 @@ struct rxrpc_skb_priv { u8 reason; /* Reason for ack */ } ack; struct { - struct rxrpc_connection *conn; /* Connection referred to */ union { u32 rxkad_nonce; }; @@ -310,13 +305,6 @@ struct rxrpc_security { bool (*validate_challenge)(struct rxrpc_connection *conn, struct sk_buff *skb); =20 - /* Fill out the cmsg for recvmsg() to pass on a challenge to userspace. - * The security class gets to add additional information. - */ - int (*challenge_to_recvmsg)(struct rxrpc_connection *conn, - struct sk_buff *challenge, - struct msghdr *msg); - /* Parse sendmsg() control message and respond to challenge. */ int (*sendmsg_respond_to_challenge)(struct sk_buff *challenge, struct msghdr *msg); @@ -1379,13 +1367,6 @@ static inline struct rxrpc_net *rxrpc_net(struct net= *net) return net_generic(net, rxrpc_net_id); } =20 -/* - * oob.c - */ -bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb); -void rxrpc_add_pending_oob(struct rxrpc_sock *rx, struct sk_buff *skb); -int rxrpc_sendmsg_oob(struct rxrpc_sock *rx, struct msghdr *msg, size_t le= n); - /* * output.c */ diff --git a/net/rxrpc/oob.c b/net/rxrpc/oob.c deleted file mode 100644 index c80ee2487d09..000000000000 --- a/net/rxrpc/oob.c +++ /dev/null @@ -1,387 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Out of band message handling (e.g. challenge-response) - * - * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include "ar-internal.h" - -enum rxrpc_oob_command { - RXRPC_OOB_CMD_UNSET, - RXRPC_OOB_CMD_RESPOND, -} __mode(byte); - -struct rxrpc_oob_params { - u64 oob_id; /* ID number of message if reply */ - s32 abort_code; - enum rxrpc_oob_command command; - bool have_oob_id:1; -}; - -/* - * Post an out-of-band message for attention by the socket or kernel servi= ce - * associated with a reference call. - */ -bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(skb); - struct rxrpc_sock *rx; - struct sock *sk; - bool queued =3D false; - - rcu_read_lock(); - - rx =3D rcu_dereference(call->socket); - if (rx) { - sk =3D &rx->sk; - spin_lock_irq(&rx->recvmsg_lock); - - if (sk->sk_state < RXRPC_CLOSE) { - skb->skb_mstamp_ns =3D rx->oob_id_counter++; - rxrpc_get_skb(skb, rxrpc_skb_get_post_oob); - skb_queue_tail(&rx->recvmsg_oobq, skb); - queued =3D true; - - trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial); - if (rx->app_ops) - rx->app_ops->notify_oob(sk, skb); - } - - spin_unlock_irq(&rx->recvmsg_lock); - if (queued && !rx->app_ops && !sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk); - } - - rcu_read_unlock(); - return queued; -} - -/* - * Locate the OOB message to respond to by its ID. - */ -static struct sk_buff *rxrpc_find_pending_oob(struct rxrpc_sock *rx, u64 o= ob_id) -{ - struct rb_node *p; - struct sk_buff *skb; - - p =3D rx->pending_oobq.rb_node; - while (p) { - skb =3D rb_entry(p, struct sk_buff, rbnode); - - if (oob_id < skb->skb_mstamp_ns) - p =3D p->rb_left; - else if (oob_id > skb->skb_mstamp_ns) - p =3D p->rb_right; - else - return skb; - } - - return NULL; -} - -/* - * Add an OOB message into the pending-response set. We always assign the= next - * value from a 64-bit counter to the oob_id, so just assume we're always = going - * to be on the right-hand edge of the tree and that the counter won't wra= p. - * The tree is also given a ref to the message. - */ -void rxrpc_add_pending_oob(struct rxrpc_sock *rx, struct sk_buff *skb) -{ - struct rb_node **pp =3D &rx->pending_oobq.rb_node, *p =3D NULL; - - while (*pp) { - p =3D *pp; - pp =3D &(*pp)->rb_right; - } - - rb_link_node(&skb->rbnode, p, pp); - rb_insert_color(&skb->rbnode, &rx->pending_oobq); -} - -/* - * Extract control messages from the sendmsg() control buffer. - */ -static int rxrpc_sendmsg_oob_cmsg(struct msghdr *msg, struct rxrpc_oob_par= ams *p) -{ - struct cmsghdr *cmsg; - int len; - - if (msg->msg_controllen =3D=3D 0) - return -EINVAL; - - for_each_cmsghdr(cmsg, msg) { - if (!CMSG_OK(msg, cmsg)) - return -EINVAL; - - len =3D cmsg->cmsg_len - sizeof(struct cmsghdr); - _debug("CMSG %d, %d, %d", - cmsg->cmsg_level, cmsg->cmsg_type, len); - - if (cmsg->cmsg_level !=3D SOL_RXRPC) - continue; - - switch (cmsg->cmsg_type) { - case RXRPC_OOB_ID: - if (len !=3D sizeof(p->oob_id) || p->have_oob_id) - return -EINVAL; - memcpy(&p->oob_id, CMSG_DATA(cmsg), sizeof(p->oob_id)); - p->have_oob_id =3D true; - break; - case RXRPC_RESPOND: - if (p->command !=3D RXRPC_OOB_CMD_UNSET) - return -EINVAL; - p->command =3D RXRPC_OOB_CMD_RESPOND; - break; - case RXRPC_ABORT: - if (len !=3D sizeof(p->abort_code) || p->abort_code) - return -EINVAL; - memcpy(&p->abort_code, CMSG_DATA(cmsg), sizeof(p->abort_code)); - if (p->abort_code =3D=3D 0) - return -EINVAL; - break; - case RXRPC_RESP_RXGK_APPDATA: - if (p->command !=3D RXRPC_OOB_CMD_RESPOND) - return -EINVAL; - break; - default: - return -EINVAL; - } - } - - switch (p->command) { - case RXRPC_OOB_CMD_RESPOND: - if (!p->have_oob_id) - return -EBADSLT; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Allow userspace to respond to an OOB using sendmsg(). - */ -static int rxrpc_respond_to_oob(struct rxrpc_sock *rx, - struct rxrpc_oob_params *p, - struct msghdr *msg) -{ - struct rxrpc_connection *conn; - struct rxrpc_skb_priv *sp; - struct sk_buff *skb; - int ret; - - skb =3D rxrpc_find_pending_oob(rx, p->oob_id); - if (skb) - rb_erase(&skb->rbnode, &rx->pending_oobq); - release_sock(&rx->sk); - if (!skb) - return -EBADSLT; - - sp =3D rxrpc_skb(skb); - - switch (p->command) { - case RXRPC_OOB_CMD_RESPOND: - ret =3D -EPROTO; - if (skb->mark !=3D RXRPC_OOB_CHALLENGE) - break; - conn =3D sp->chall.conn; - ret =3D -EOPNOTSUPP; - if (!conn->security->sendmsg_respond_to_challenge) - break; - if (p->abort_code) { - rxrpc_abort_conn(conn, NULL, p->abort_code, -ECONNABORTED, - rxrpc_abort_response_sendmsg); - ret =3D 0; - } else { - ret =3D conn->security->sendmsg_respond_to_challenge(skb, msg); - } - break; - default: - ret =3D -EINVAL; - break; - } - - switch (skb->mark) { - case RXRPC_OOB_CHALLENGE: - rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob); - break; - } - rxrpc_free_skb(skb, rxrpc_skb_put_oob); - return ret; -} - -/* - * Send an out-of-band message or respond to a received out-of-band messag= e. - * - caller gives us the socket lock - * - the socket may be either a client socket or a server socket - */ -int rxrpc_sendmsg_oob(struct rxrpc_sock *rx, struct msghdr *msg, size_t le= n) -{ - struct rxrpc_oob_params p =3D {}; - int ret; - - _enter(""); - - ret =3D rxrpc_sendmsg_oob_cmsg(msg, &p); - if (ret < 0) - goto error_release_sock; - - if (p.have_oob_id) - return rxrpc_respond_to_oob(rx, &p, msg); - - release_sock(&rx->sk); - - switch (p.command) { - default: - ret =3D -EINVAL; - break; - } - - _leave(" =3D %d", ret); - return ret; - -error_release_sock: - release_sock(&rx->sk); - return ret; -} - -/** - * rxrpc_kernel_query_oob - Query the parameters of an out-of-band message - * @oob: The message to query - * @_peer: Where to return the peer record - * @_peer_appdata: The application data attached to a peer record - * - * Extract useful parameters from an out-of-band message. The source peer - * parameters are returned through the argument list and the message type = is - * returned. - * - * Return: - * * %RXRPC_OOB_CHALLENGE - Challenge wanting a response. - */ -enum rxrpc_oob_type rxrpc_kernel_query_oob(struct sk_buff *oob, - struct rxrpc_peer **_peer, - unsigned long *_peer_appdata) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(oob); - enum rxrpc_oob_type type =3D oob->mark; - - switch (type) { - case RXRPC_OOB_CHALLENGE: - *_peer =3D sp->chall.conn->peer; - *_peer_appdata =3D sp->chall.conn->peer->app_data; - break; - default: - WARN_ON_ONCE(1); - *_peer =3D NULL; - *_peer_appdata =3D 0; - break; - } - - return type; -} -EXPORT_SYMBOL(rxrpc_kernel_query_oob); - -/** - * rxrpc_kernel_dequeue_oob - Dequeue and return the front OOB message - * @sock: The socket to query - * @_type: Where to return the message type - * - * Dequeue the front OOB message, if there is one, and return it and - * its type. - * - * Return: The sk_buff representing the OOB message or %NULL if the queue = was - * empty. - */ -struct sk_buff *rxrpc_kernel_dequeue_oob(struct socket *sock, - enum rxrpc_oob_type *_type) -{ - struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); - struct sk_buff *oob; - - oob =3D skb_dequeue(&rx->recvmsg_oobq); - if (oob) - *_type =3D oob->mark; - return oob; -} -EXPORT_SYMBOL(rxrpc_kernel_dequeue_oob); - -/** - * rxrpc_kernel_free_oob - Free an out-of-band message - * @oob: The OOB message to free - * - * Free an OOB message along with any resources it holds. - */ -void rxrpc_kernel_free_oob(struct sk_buff *oob) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(oob); - - switch (oob->mark) { - case RXRPC_OOB_CHALLENGE: - rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob); - break; - } - - rxrpc_free_skb(oob, rxrpc_skb_put_purge_oob); -} -EXPORT_SYMBOL(rxrpc_kernel_free_oob); - -/** - * rxrpc_kernel_query_challenge - Query the parameters of a challenge - * @challenge: The challenge to query - * @_peer: Where to return the peer record - * @_peer_appdata: The application data attached to a peer record - * @_service_id: Where to return the connection service ID - * @_security_index: Where to return the connection security index - * - * Extract useful parameters from a CHALLENGE message. - */ -void rxrpc_kernel_query_challenge(struct sk_buff *challenge, - struct rxrpc_peer **_peer, - unsigned long *_peer_appdata, - u16 *_service_id, u8 *_security_index) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(challenge); - - *_peer =3D sp->chall.conn->peer; - *_peer_appdata =3D sp->chall.conn->peer->app_data; - *_service_id =3D sp->hdr.serviceId; - *_security_index =3D sp->hdr.securityIndex; -} -EXPORT_SYMBOL(rxrpc_kernel_query_challenge); - -/** - * rxrpc_kernel_reject_challenge - Allow a kernel service to reject a chal= lenge - * @challenge: The challenge to be rejected - * @abort_code: The abort code to stick into the ABORT packet - * @error: Local error value - * @why: Indication as to why. - * - * Allow a kernel service to reject a challenge by aborting the connection= if - * it's still in an abortable state. The error is returned so this functi= on - * can be used with a return statement. - * - * Return: The %error parameter. - */ -int rxrpc_kernel_reject_challenge(struct sk_buff *challenge, u32 abort_cod= e, - int error, enum rxrpc_abort_reason why) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(challenge); - - _enter("{%x},%d,%d,%u", sp->hdr.serial, abort_code, error, why); - - rxrpc_abort_conn(sp->chall.conn, NULL, abort_code, error, why); - return error; -} -EXPORT_SYMBOL(rxrpc_kernel_reject_challenge); diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 33577522ec02..5b8c7f573b7f 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -201,61 +201,6 @@ static int rxrpc_recvmsg_user_id(struct rxrpc_call *ca= ll, struct msghdr *msg, } } =20 -/* - * Deal with a CHALLENGE packet. - */ -static int rxrpc_recvmsg_challenge(struct socket *sock, struct msghdr *msg, - struct sk_buff *challenge, unsigned int flags) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(challenge); - struct rxrpc_connection *conn =3D sp->chall.conn; - - return conn->security->challenge_to_recvmsg(conn, challenge, msg); -} - -/* - * Process OOB packets. Called with the socket locked. - */ -static int rxrpc_recvmsg_oob(struct socket *sock, struct msghdr *msg, - unsigned int flags) -{ - struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); - struct sk_buff *skb; - bool need_response =3D false; - int ret; - - skb =3D skb_peek(&rx->recvmsg_oobq); - if (!skb) - return -EAGAIN; - rxrpc_see_skb(skb, rxrpc_skb_see_recvmsg); - - ret =3D put_cmsg(msg, SOL_RXRPC, RXRPC_OOB_ID, sizeof(u64), - &skb->skb_mstamp_ns); - if (ret < 0) - return ret; - - switch ((enum rxrpc_oob_type)skb->mark) { - case RXRPC_OOB_CHALLENGE: - need_response =3D true; - ret =3D rxrpc_recvmsg_challenge(sock, msg, skb, flags); - break; - default: - WARN_ONCE(1, "recvmsg() can't process unknown OOB type %u\n", - skb->mark); - ret =3D -EIO; - break; - } - - 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); - } - return ret; -} - /* * Deliver messages to a call. This keeps processing packets until the bu= ffer * is filled and we find either more DATA (returns 0) or the end of the DA= TA @@ -267,7 +212,6 @@ static int rxrpc_recvmsg_data(struct socket *sock, stru= ct rxrpc_call *call, size_t len, int flags, size_t *_offset) { struct rxrpc_skb_priv *sp; - struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); struct sk_buff *skb; rxrpc_seq_t seq =3D 0; size_t remain; @@ -362,13 +306,6 @@ static int rxrpc_recvmsg_data(struct socket *sock, str= uct rxrpc_call *call, =20 if (!(flags & MSG_PEEK)) rxrpc_rotate_rx_window(call); - - if (!rx->app_ops && - !skb_queue_empty_lockless(&rx->recvmsg_oobq)) { - trace_rxrpc_recvdata(call, rxrpc_recvmsg_oobq, seq, - rx_pkt_offset, rx_pkt_len, ret); - break; - } } =20 out: @@ -416,14 +353,12 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr = *msg, size_t len, /* Return immediately if a client socket has no outstanding calls */ if (RB_EMPTY_ROOT(&rx->calls) && list_empty(&rx->recvmsg_q) && - skb_queue_empty_lockless(&rx->recvmsg_oobq) && rx->sk.sk_state !=3D RXRPC_SERVER_LISTENING) { release_sock(&rx->sk); return -EAGAIN; } =20 - if (list_empty(&rx->recvmsg_q) && - skb_queue_empty_lockless(&rx->recvmsg_oobq)) { + if (list_empty(&rx->recvmsg_q)) { ret =3D -EWOULDBLOCK; if (timeo =3D=3D 0) { call =3D NULL; @@ -439,8 +374,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *m= sg, size_t len, if (ret) goto wait_error; =20 - if (list_empty(&rx->recvmsg_q) && - skb_queue_empty_lockless(&rx->recvmsg_oobq)) { + if (list_empty(&rx->recvmsg_q)) { if (signal_pending(current)) goto wait_interrupted; trace_rxrpc_recvmsg(0, rxrpc_recvmsg_wait, 0); @@ -450,15 +384,6 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *= msg, size_t len, goto try_again; } =20 - /* Deal with OOB messages before we consider getting normal data. */ - if (!skb_queue_empty_lockless(&rx->recvmsg_oobq)) { - ret =3D rxrpc_recvmsg_oob(sock, msg, flags); - release_sock(&rx->sk); - if (ret =3D=3D -EAGAIN) - goto try_again; - goto error_trace; - } - /* Find the next call and dequeue it if we're not just peeking. If we * do dequeue it, that comes with a ref that we will need to release. * We also want to weed out calls that got requeued whilst we were @@ -469,8 +394,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *m= sg, size_t len, call =3D list_entry(l, struct rxrpc_call, recvmsg_link); =20 if (!rxrpc_call_is_complete(call) && - skb_queue_empty(&call->recvmsg_queue) && - skb_queue_empty(&rx->recvmsg_oobq)) { + skb_queue_empty(&call->recvmsg_queue)) { list_del_init(&call->recvmsg_link); spin_unlock_irq(&rx->recvmsg_lock); release_sock(&rx->sk); diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c index f3e085b64502..b9efeec145dd 100644 --- a/net/rxrpc/rxgk.c +++ b/net/rxrpc/rxgk.c @@ -735,37 +735,6 @@ static bool rxgk_validate_challenge(struct rxrpc_conne= ction *conn, return true; } =20 -/** - * rxgk_kernel_query_challenge - Query RxGK-specific challenge parameters - * @challenge: The challenge packet to query - * - * Return: The Kerberos 5 encoding type for the challenged connection. - */ -u32 rxgk_kernel_query_challenge(struct sk_buff *challenge) -{ - struct rxrpc_skb_priv *sp =3D rxrpc_skb(challenge); - - return sp->chall.conn->rxgk.enctype; -} -EXPORT_SYMBOL(rxgk_kernel_query_challenge); - -/* - * Fill out the control message to pass to userspace to inform about the - * challenge. - */ -static int rxgk_challenge_to_recvmsg(struct rxrpc_connection *conn, - struct sk_buff *challenge, - struct msghdr *msg) -{ - struct rxgk_challenge chall; - - chall.base.service_id =3D conn->service_id; - chall.base.security_index =3D conn->security_ix; - chall.enctype =3D conn->rxgk.enctype; - - return put_cmsg(msg, SOL_RXRPC, RXRPC_CHALLENGED, sizeof(chall), &chall); -} - /* * Insert the requisite amount of XDR padding for the length given. */ @@ -1044,46 +1013,6 @@ static int rxgk_respond_to_challenge(struct rxrpc_co= nnection *conn, return ret; } =20 -/** - * rxgk_kernel_respond_to_challenge - Respond to a challenge with appdata - * @challenge: The challenge to respond to - * @appdata: The application data to include in the RESPONSE authenticator - * - * Allow a kernel application to respond to a CHALLENGE with application d= ata - * to be included in the RxGK RESPONSE Authenticator. - * - * Return: %0 if successful and a negative error code otherwise. - */ -int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, - struct krb5_buffer *appdata) -{ - return -EINVAL; -} -EXPORT_SYMBOL(rxgk_kernel_respond_to_challenge); - -/* - * Parse sendmsg() control message and respond to challenge. We need to s= ee if - * there's an appdata to fish out. - */ -static int rxgk_sendmsg_respond_to_challenge(struct sk_buff *challenge, - struct msghdr *msg) -{ - struct krb5_buffer appdata =3D {}; - struct cmsghdr *cmsg; - - for_each_cmsghdr(cmsg, msg) { - if (cmsg->cmsg_level !=3D SOL_RXRPC || - cmsg->cmsg_type !=3D RXRPC_RESP_RXGK_APPDATA) - continue; - if (appdata.data) - return -EINVAL; - appdata.data =3D CMSG_DATA(cmsg); - appdata.len =3D cmsg->cmsg_len - sizeof(struct cmsghdr); - } - - return rxgk_kernel_respond_to_challenge(challenge, &appdata); -} - /* * Verify the authenticator. * @@ -1357,8 +1286,6 @@ const struct rxrpc_security rxgk_yfs =3D { .free_call_crypto =3D rxgk_free_call_crypto, .issue_challenge =3D rxgk_issue_challenge, .validate_challenge =3D rxgk_validate_challenge, - .challenge_to_recvmsg =3D rxgk_challenge_to_recvmsg, - .sendmsg_respond_to_challenge =3D rxgk_sendmsg_respond_to_challenge, .respond_to_challenge =3D rxgk_respond_to_challenge, .verify_response =3D rxgk_verify_response, .clear =3D rxgk_clear, diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index ca9f0e82cb9a..e55bfca10e1a 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -748,32 +748,6 @@ static int rxkad_respond_to_challenge(struct rxrpc_con= nection *conn, return ret; } =20 -/* - * RxKAD does automatic response only as there's nothing to manage that is= n't - * already in the key. - */ -static int rxkad_sendmsg_respond_to_challenge(struct sk_buff *challenge, - struct msghdr *msg) -{ - return -EINVAL; -} - -/** - * rxkad_kernel_respond_to_challenge - Respond to a challenge with appdata - * @challenge: The challenge to respond to - * - * Allow a kernel application to respond to a CHALLENGE. - * - * Return: %0 if successful and a negative error code otherwise. - */ -int rxkad_kernel_respond_to_challenge(struct sk_buff *challenge) -{ - struct rxrpc_skb_priv *csp =3D rxrpc_skb(challenge); - - return rxkad_respond_to_challenge(csp->chall.conn, challenge); -} -EXPORT_SYMBOL(rxkad_kernel_respond_to_challenge); - /* Decrypt data in-place using DES-PCBC. @len must be a multiple of 8. */ VISIBLE_IF_KUNIT void des_pcbc_decrypt_inplace(const struct des_ctx *key, __le64 iv, u8 *data, size_t len) @@ -1134,7 +1108,6 @@ const struct rxrpc_security rxkad =3D { .free_call_crypto =3D rxkad_free_call_crypto, .issue_challenge =3D rxkad_issue_challenge, .validate_challenge =3D rxkad_validate_challenge, - .sendmsg_respond_to_challenge =3D rxkad_sendmsg_respond_to_challenge, .respond_to_challenge =3D rxkad_respond_to_challenge, .verify_response =3D rxkad_verify_response, .clear =3D rxkad_clear, diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c index 3efe104b1930..fc6f478e1762 100644 --- a/net/rxrpc/server_key.c +++ b/net/rxrpc/server_key.c @@ -173,43 +173,3 @@ int rxrpc_sock_set_security_keyring(struct sock *sk, s= truct key *keyring) return ret; } EXPORT_SYMBOL(rxrpc_sock_set_security_keyring); - -/** - * rxrpc_sock_set_manage_response - Set the manage-response flag for a ker= nel service - * @sk: The socket to set the keyring on - * @set: True to set, false to clear the flag - * - * Set the flag on an rxrpc socket to say that the caller wants to manage = the - * RESPONSE packet and the user-defined data it may contain. Setting this - * means that recvmsg() will return messages with RXRPC_CHALLENGED in the - * control message buffer containing information about the challenge. - * - * The user should respond to the challenge by passing RXRPC_RESPOND or - * RXRPC_RESPOND_ABORT control messages with sendmsg() to the same call. - * Supplementary control messages, such as RXRPC_RESP_RXGK_APPDATA, may be - * included to indicate the parts the user wants to supply. - * - * The server will be passed the response data with a RXRPC_RESPONDED cont= rol - * message when it gets the first data from each call. - * - * Note that this is only honoured by security classes that need auxiliary= data - * (e.g. RxGK). Those that don't offer the facility (e.g. RxKAD) respond - * without consulting userspace. - * - * Return: The previous setting. - */ -int rxrpc_sock_set_manage_response(struct sock *sk, bool set) -{ - struct rxrpc_sock *rx =3D rxrpc_sk(sk); - int ret; - - lock_sock(sk); - ret =3D !!test_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags); - if (set) - set_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags); - else - clear_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags); - release_sock(sk); - return ret; -} -EXPORT_SYMBOL(rxrpc_sock_set_manage_response);