From mboxrd@z Thu Jan 1 00:00:00 1970 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 B0436363C53 for ; Mon, 24 Aug 2026 09:17:43 +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=1787563069; cv=none; b=T5Csn0EFrYGt+CZqlbve4k8nirDF0PtrePpb0krgkYBXH77UmlQjnFsGf1CbEf0sJPdOpFiELiVvH/GQNYAKQtVn9Gsw9F33gsyFrY2uHf01YBVbK7Wr7dt5ZrHRWM0P/QpZyXoLhFaSKmiJ1wfhFF/9Tmxb+5TyuAjRFVMLVBg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787563069; c=relaxed/simple; bh=ouwgzn1LcTBs6HIDIKNKoIWdDvRxutElnIPpcYrqmXY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i5/UbLYwtubke+7DV3acvstdtAmJyNTO5qKvFgy+uF/gvEkQtZXT8t68mXLU1vRSsIhLD4TE2cm0/bomjpjo8rjgVI3/gO/tta4JjIrv29G+fEgDNU272Gntvjtmt8w6cq9VLYveXmvdypEt67BUQJJp8/KWW5fq3eIMQ2czoNw= 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=LeO1blw0; 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="LeO1blw0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787563061; 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=Q38lwKfFiydZiaJ4KBp/+2vpGGcK2zkfYXc/D2z2I0M=; b=LeO1blw0LYsbkGO/egyFnap9YZZQ+/QREwLYGJMvFdhsIYfxLE5db/30EmzkYj0hYX31xR vamMzL5CVtOpAjzL7Jg73KotTq0Pa0EZ4a2wmtxDuFc91qcYQ7YExeHGYzH3BDot35yTa3 oUEciQj2ztOypXa8kawOexChDmcelh0= 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-634-7x5nXaJCPKG3rSCRFcKd6Q-1; Mon, 24 Aug 2026 05:17:37 -0400 X-MC-Unique: 7x5nXaJCPKG3rSCRFcKd6Q-1 X-Mimecast-MFC-AGG-ID: 7x5nXaJCPKG3rSCRFcKd6Q_1787563055 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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 147EE1944DE3; Mon, 24 Aug 2026 09:17:35 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 661741955F0A; Mon, 24 Aug 2026 09:17: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, Jarkko Sakkinen , Jeffrey Altman , keyrings@vger.kernel.org Subject: [PATCH net v8 08/12] keys: Add refcounting to user-defined key type payload Date: Mon, 24 Aug 2026 10:16:40 +0100 Message-ID: <20260824091645.415423-9-dhowells@redhat.com> In-Reply-To: <20260824091645.415423-1-dhowells@redhat.com> References: <20260824091645.415423-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: 8bit X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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%40redhat.com Signed-off-by: David Howells Reviewed-by: Jarkko Sakkinen 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: keyrings@vger.kernel.org --- include/keys/user-type.h | 10 +++++++--- net/dns_resolver/dns_key.c | 1 + security/keys/user_defined.c | 23 ++++++++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/keys/user-type.h b/include/keys/user-type.h index 386c31432789..63846439596b 100644 --- a/include/keys/user-type.h +++ b/include/keys/user-type.h @@ -13,19 +13,22 @@ #ifdef CONFIG_KEYS -/*****************************************************************************/ /* * the payload for a key of type "user" or "logon" * - once filled in and attached to a key: * - the payload struct is invariant may not be changed, only replaced - * - the payload must be read with RCU procedures or with the key semaphore - * held + * - To access the payload, the caller must be holding the key semaphore or + * the RCU read lock or must have first taken a ref on the payload. + * - a ref may be taken on the payload only if the RCU read lock or key + * semaphore is held. refcount_inc_not_zero() needs to be used to get the + * ref under RCU. * - the payload may only be replaced with the key semaphore write-locked * - the key's data length is the size of the actual data, not including the * payload wrapper */ struct user_key_payload { struct rcu_head rcu; /* RCU destructor */ + refcount_t ref; /* Reference count */ unsigned short datalen; /* length of this data */ char data[] __aligned(__alignof__(u64)); /* actual data */ }; @@ -37,6 +40,7 @@ struct key_preparsed_payload; 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 451247864a63..2bd3fb3c19f1 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 *prep) kleave(" = -ENOMEM"); return -ENOMEM; } + refcount_set(&upayload->ref, 1); upayload->datalen = result_len; memcpy(upayload->data, data, result_len); diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 6f88b507f927..55d5ed97b36e 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 = kmalloc_flex(*upayload, data, datalen); if (!upayload) return -ENOMEM; + refcount_set(&upayload->ref, 1); /* attach the data */ prep->quotalen = datalen; @@ -88,12 +89,22 @@ EXPORT_SYMBOL_GPL(user_free_preparse); static void user_free_payload_rcu(struct rcu_head *head) { - struct user_key_payload *payload; + struct user_key_payload *payload = + container_of(head, struct user_key_payload, rcu); - payload = container_of(head, struct user_key_payload, rcu); kfree_sensitive(payload); } +/* + * Drop a ref to a user defined key payload, freeing it once all refs are gone. + */ +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_payload *prep) rcu_assign_keypointer(key, prep->payload.data[0]); prep->payload.data[0] = NULL; - 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) if (upayload) { rcu_assign_keypointer(key, NULL); - call_rcu(&upayload->rcu, user_free_payload_rcu); + put_user_key_payload(upayload); } } @@ -147,9 +157,8 @@ void user_destroy(struct key *key) { struct user_key_payload *upayload = key->payload.data[0]; - kfree_sensitive(upayload); + put_user_key_payload(upayload); } - EXPORT_SYMBOL_GPL(user_destroy); /*