From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D59773A5995; Thu, 2 Jul 2026 16:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783009468; cv=none; b=azSPsFSu8Hxu1j+I6Ht52vRy7nV8J9/g/GV27vRZog+wqG8H14tO8Lc4fXyIjYWvggTo2yAMUrWLJXmTrJXftKFjgdIDItxePqZ7DxLL7bazCUvReQQ6EsppVLnMAKuwYqmZgh9s3eQWjz70ommEDjg57p8wt7xQNvL4fl5npio= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783009468; c=relaxed/simple; bh=uSAqYkNKVtdlzgfykwa+fzKhBauuKT2U1wpK2U+NDgQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SXBVMZ7Gy7DpfodhI4AJL8i3tsEF/WQnonZxkjCEk3CNvLrVuF2Cuh2QVh1iCkyAw/ipsx/lZ5TYhqTqlGVdVr9zEhTFrtVayvKMYcfKQDWzliOYoQfL07op7z0kCY3l4QCfwHrGbfVZHO8n6sfX3yASe/1rwxk1XZh96ofXfHk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=k7TUo/dD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="k7TUo/dD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 406EB1F00A3E; Thu, 2 Jul 2026 16:24:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1783009465; bh=pLGl+y0N58KDqPkNE/iKzcUW3WLUNjfk12edEXZkkvg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=k7TUo/dDGSugORN0jIGXzskiwljPpZ3lOAVYwkOcJ/kvTzBVRz8WiFdN9/fEkPb7O Ay93T0Bd3o3YGdfLCYUOaN1oHqn+RNHG1duYsS8tOBGvRPDs39vXrOVU8C+dIs6NHD rIe5Ky3EHIjZfRLOpTsCBAhMama9bDbaLJsvQD3Y= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Shaomin Chen , Jarkko Sakkinen Subject: [PATCH 5.10 63/96] keys: Pin request_key_auth payload in instantiate paths Date: Thu, 2 Jul 2026 18:19:55 +0200 Message-ID: <20260702155110.305394833@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260702155108.949633242@linuxfoundation.org> References: <20260702155108.949633242@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 5.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Shaomin Chen commit fd15b457a86939c38aa12116adabd8ff686c5e51 upstream. A: request_key() B: KEYCTL_INSTANTIATE_IOV ================ ========================= create auth key store rka in auth key wait for helper get auth key load rka from auth key copy user payload sleep on #PF helper completed detach and free rka destroy auth key wake up use rka->target_key **USE-AFTER-FREE** Give request_key_auth payloads a refcount. Take a payload reference while authkey->sem stabilizes the payload and revocation state. Hold that reference across the instantiate and reject paths. Drop the auth key owning reference from revoke and destroy. [jarkko: Replaced the first two paragraphs of text with an actual concurrency scenario.] Cc: stable@vger.kernel.org # v5.10+ Fixes: b5f545c880a2 ("[PATCH] keys: Permit running process to instantiate keys") Reported-by: Shaomin Chen Closes: https://lore.kernel.org/r/20260519144403.436694-1-eeesssooo020@gmail.com Signed-off-by: Shaomin Chen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- include/keys/request_key_auth-type.h | 2 ++ security/keys/internal.h | 2 ++ security/keys/keyctl.c | 24 ++++++++++++++++++------ security/keys/request_key_auth.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 8 deletions(-) --- a/include/keys/request_key_auth-type.h +++ b/include/keys/request_key_auth-type.h @@ -9,12 +9,14 @@ #define _KEYS_REQUEST_KEY_AUTH_TYPE_H #include +#include /* * Authorisation record for request_key(). */ struct request_key_auth { struct rcu_head rcu; + refcount_t usage; struct key *target_key; struct key *dest_keyring; const struct cred *cred; --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -217,6 +217,8 @@ extern struct key *request_key_auth_new( const void *callout_info, size_t callout_len, struct key *dest_keyring); +struct request_key_auth *request_key_auth_get(struct key *authkey); +void request_key_auth_put(struct request_key_auth *rka); extern struct key *key_get_instantiation_authkey(key_serial_t target_id); --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1196,9 +1196,13 @@ static long keyctl_instantiate_key_commo if (!instkey) goto error; - rka = instkey->payload.data[0]; - if (rka->target_key->serial != id) + rka = request_key_auth_get(instkey); + if (!rka) { + ret = -EKEYREVOKED; goto error; + } + if (rka->target_key->serial != id) + goto error_put_rka; /* pull the payload in if one was supplied */ payload = NULL; @@ -1207,7 +1211,7 @@ static long keyctl_instantiate_key_commo ret = -ENOMEM; payload = kvmalloc(plen, GFP_KERNEL); if (!payload) - goto error; + goto error_put_rka; ret = -EFAULT; if (!copy_from_iter_full(payload, plen, from)) @@ -1233,6 +1237,8 @@ static long keyctl_instantiate_key_commo error2: kvfree_sensitive(payload, plen); +error_put_rka: + request_key_auth_put(rka); error: return ret; } @@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id, if (!instkey) goto error; - rka = instkey->payload.data[0]; - if (rka->target_key->serial != id) + rka = request_key_auth_get(instkey); + if (!rka) { + ret = -EKEYREVOKED; goto error; + } + if (rka->target_key->serial != id) + goto error_put_rka; /* find the destination keyring if present (which must also be * writable) */ ret = get_instantiation_keyring(ringid, rka, &dest_keyring); if (ret < 0) - goto error; + goto error_put_rka; /* instantiate the key and link it into a keyring */ ret = key_reject_and_link(rka->target_key, timeout, error, @@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id, if (ret == 0) keyctl_change_reqkey_auth(NULL); +error_put_rka: + request_key_auth_put(rka); error: return ret; } --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -23,6 +23,7 @@ static void request_key_auth_describe(co static void request_key_auth_revoke(struct key *); static void request_key_auth_destroy(struct key *); static long request_key_auth_read(const struct key *, char *, size_t); +static void request_key_auth_rcu_disposal(struct rcu_head *); /* * The request-key authorisation key type definition. @@ -116,6 +117,31 @@ static void free_request_key_auth(struct } /* + * Take a reference to the request-key authorisation payload so callers can + * drop authkey->sem before doing operations that may sleep. + */ +struct request_key_auth *request_key_auth_get(struct key *authkey) +{ + struct request_key_auth *rka; + + down_read(&authkey->sem); + rka = dereference_key_locked(authkey); + if (rka && !test_bit(KEY_FLAG_REVOKED, &authkey->flags)) + refcount_inc(&rka->usage); + else + rka = NULL; + up_read(&authkey->sem); + + return rka; +} + +void request_key_auth_put(struct request_key_auth *rka) +{ + if (rka && refcount_dec_and_test(&rka->usage)) + call_rcu(&rka->rcu, request_key_auth_rcu_disposal); +} + +/* * Dispose of the request_key_auth record under RCU conditions */ static void request_key_auth_rcu_disposal(struct rcu_head *rcu) @@ -136,8 +162,10 @@ static void request_key_auth_revoke(stru struct request_key_auth *rka = dereference_key_locked(key); kenter("{%d}", key->serial); + if (!rka) + return; rcu_assign_keypointer(key, NULL); - call_rcu(&rka->rcu, request_key_auth_rcu_disposal); + request_key_auth_put(rka); } /* @@ -150,7 +178,7 @@ static void request_key_auth_destroy(str kenter("{%d}", key->serial); if (rka) { rcu_assign_keypointer(key, NULL); - call_rcu(&rka->rcu, request_key_auth_rcu_disposal); + request_key_auth_put(rka); } } @@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct rka = kzalloc(sizeof(*rka), GFP_KERNEL); if (!rka) goto error; + refcount_set(&rka->usage, 1); rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL); if (!rka->callout_info) goto error_free_rka;