cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

request_key_auth.c (7308B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* Request key authorisation token key definition.
      3 *
      4 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
      5 * Written by David Howells (dhowells@redhat.com)
      6 *
      7 * See Documentation/security/keys/request-key.rst
      8 */
      9
     10#include <linux/sched.h>
     11#include <linux/err.h>
     12#include <linux/seq_file.h>
     13#include <linux/slab.h>
     14#include <linux/uaccess.h>
     15#include "internal.h"
     16#include <keys/request_key_auth-type.h>
     17
     18static int request_key_auth_preparse(struct key_preparsed_payload *);
     19static void request_key_auth_free_preparse(struct key_preparsed_payload *);
     20static int request_key_auth_instantiate(struct key *,
     21					struct key_preparsed_payload *);
     22static void request_key_auth_describe(const struct key *, struct seq_file *);
     23static void request_key_auth_revoke(struct key *);
     24static void request_key_auth_destroy(struct key *);
     25static long request_key_auth_read(const struct key *, char *, size_t);
     26
     27/*
     28 * The request-key authorisation key type definition.
     29 */
     30struct key_type key_type_request_key_auth = {
     31	.name		= ".request_key_auth",
     32	.def_datalen	= sizeof(struct request_key_auth),
     33	.preparse	= request_key_auth_preparse,
     34	.free_preparse	= request_key_auth_free_preparse,
     35	.instantiate	= request_key_auth_instantiate,
     36	.describe	= request_key_auth_describe,
     37	.revoke		= request_key_auth_revoke,
     38	.destroy	= request_key_auth_destroy,
     39	.read		= request_key_auth_read,
     40};
     41
     42static int request_key_auth_preparse(struct key_preparsed_payload *prep)
     43{
     44	return 0;
     45}
     46
     47static void request_key_auth_free_preparse(struct key_preparsed_payload *prep)
     48{
     49}
     50
     51/*
     52 * Instantiate a request-key authorisation key.
     53 */
     54static int request_key_auth_instantiate(struct key *key,
     55					struct key_preparsed_payload *prep)
     56{
     57	rcu_assign_keypointer(key, (struct request_key_auth *)prep->data);
     58	return 0;
     59}
     60
     61/*
     62 * Describe an authorisation token.
     63 */
     64static void request_key_auth_describe(const struct key *key,
     65				      struct seq_file *m)
     66{
     67	struct request_key_auth *rka = dereference_key_rcu(key);
     68
     69	if (!rka)
     70		return;
     71
     72	seq_puts(m, "key:");
     73	seq_puts(m, key->description);
     74	if (key_is_positive(key))
     75		seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
     76}
     77
     78/*
     79 * Read the callout_info data (retrieves the callout information).
     80 * - the key's semaphore is read-locked
     81 */
     82static long request_key_auth_read(const struct key *key,
     83				  char *buffer, size_t buflen)
     84{
     85	struct request_key_auth *rka = dereference_key_locked(key);
     86	size_t datalen;
     87	long ret;
     88
     89	if (!rka)
     90		return -EKEYREVOKED;
     91
     92	datalen = rka->callout_len;
     93	ret = datalen;
     94
     95	/* we can return the data as is */
     96	if (buffer && buflen > 0) {
     97		if (buflen > datalen)
     98			buflen = datalen;
     99
    100		memcpy(buffer, rka->callout_info, buflen);
    101	}
    102
    103	return ret;
    104}
    105
    106static void free_request_key_auth(struct request_key_auth *rka)
    107{
    108	if (!rka)
    109		return;
    110	key_put(rka->target_key);
    111	key_put(rka->dest_keyring);
    112	if (rka->cred)
    113		put_cred(rka->cred);
    114	kfree(rka->callout_info);
    115	kfree(rka);
    116}
    117
    118/*
    119 * Dispose of the request_key_auth record under RCU conditions
    120 */
    121static void request_key_auth_rcu_disposal(struct rcu_head *rcu)
    122{
    123	struct request_key_auth *rka =
    124		container_of(rcu, struct request_key_auth, rcu);
    125
    126	free_request_key_auth(rka);
    127}
    128
    129/*
    130 * Handle revocation of an authorisation token key.
    131 *
    132 * Called with the key sem write-locked.
    133 */
    134static void request_key_auth_revoke(struct key *key)
    135{
    136	struct request_key_auth *rka = dereference_key_locked(key);
    137
    138	kenter("{%d}", key->serial);
    139	rcu_assign_keypointer(key, NULL);
    140	call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
    141}
    142
    143/*
    144 * Destroy an instantiation authorisation token key.
    145 */
    146static void request_key_auth_destroy(struct key *key)
    147{
    148	struct request_key_auth *rka = rcu_access_pointer(key->payload.rcu_data0);
    149
    150	kenter("{%d}", key->serial);
    151	if (rka) {
    152		rcu_assign_keypointer(key, NULL);
    153		call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
    154	}
    155}
    156
    157/*
    158 * Create an authorisation token for /sbin/request-key or whoever to gain
    159 * access to the caller's security data.
    160 */
    161struct key *request_key_auth_new(struct key *target, const char *op,
    162				 const void *callout_info, size_t callout_len,
    163				 struct key *dest_keyring)
    164{
    165	struct request_key_auth *rka, *irka;
    166	const struct cred *cred = current_cred();
    167	struct key *authkey = NULL;
    168	char desc[20];
    169	int ret = -ENOMEM;
    170
    171	kenter("%d,", target->serial);
    172
    173	/* allocate a auth record */
    174	rka = kzalloc(sizeof(*rka), GFP_KERNEL);
    175	if (!rka)
    176		goto error;
    177	rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL);
    178	if (!rka->callout_info)
    179		goto error_free_rka;
    180	rka->callout_len = callout_len;
    181	strlcpy(rka->op, op, sizeof(rka->op));
    182
    183	/* see if the calling process is already servicing the key request of
    184	 * another process */
    185	if (cred->request_key_auth) {
    186		/* it is - use that instantiation context here too */
    187		down_read(&cred->request_key_auth->sem);
    188
    189		/* if the auth key has been revoked, then the key we're
    190		 * servicing is already instantiated */
    191		if (test_bit(KEY_FLAG_REVOKED,
    192			     &cred->request_key_auth->flags)) {
    193			up_read(&cred->request_key_auth->sem);
    194			ret = -EKEYREVOKED;
    195			goto error_free_rka;
    196		}
    197
    198		irka = cred->request_key_auth->payload.data[0];
    199		rka->cred = get_cred(irka->cred);
    200		rka->pid = irka->pid;
    201
    202		up_read(&cred->request_key_auth->sem);
    203	}
    204	else {
    205		/* it isn't - use this process as the context */
    206		rka->cred = get_cred(cred);
    207		rka->pid = current->pid;
    208	}
    209
    210	rka->target_key = key_get(target);
    211	rka->dest_keyring = key_get(dest_keyring);
    212
    213	/* allocate the auth key */
    214	sprintf(desc, "%x", target->serial);
    215
    216	authkey = key_alloc(&key_type_request_key_auth, desc,
    217			    cred->fsuid, cred->fsgid, cred,
    218			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | KEY_POS_LINK |
    219			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL);
    220	if (IS_ERR(authkey)) {
    221		ret = PTR_ERR(authkey);
    222		goto error_free_rka;
    223	}
    224
    225	/* construct the auth key */
    226	ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
    227	if (ret < 0)
    228		goto error_put_authkey;
    229
    230	kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage));
    231	return authkey;
    232
    233error_put_authkey:
    234	key_put(authkey);
    235error_free_rka:
    236	free_request_key_auth(rka);
    237error:
    238	kleave("= %d", ret);
    239	return ERR_PTR(ret);
    240}
    241
    242/*
    243 * Search the current process's keyrings for the authorisation key for
    244 * instantiation of a key.
    245 */
    246struct key *key_get_instantiation_authkey(key_serial_t target_id)
    247{
    248	char description[16];
    249	struct keyring_search_context ctx = {
    250		.index_key.type		= &key_type_request_key_auth,
    251		.index_key.description	= description,
    252		.cred			= current_cred(),
    253		.match_data.cmp		= key_default_cmp,
    254		.match_data.raw_data	= description,
    255		.match_data.lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
    256		.flags			= (KEYRING_SEARCH_DO_STATE_CHECK |
    257					   KEYRING_SEARCH_RECURSE),
    258	};
    259	struct key *authkey;
    260	key_ref_t authkey_ref;
    261
    262	ctx.index_key.desc_len = sprintf(description, "%x", target_id);
    263
    264	rcu_read_lock();
    265	authkey_ref = search_process_keyrings_rcu(&ctx);
    266	rcu_read_unlock();
    267
    268	if (IS_ERR(authkey_ref)) {
    269		authkey = ERR_CAST(authkey_ref);
    270		if (authkey == ERR_PTR(-EAGAIN))
    271			authkey = ERR_PTR(-ENOKEY);
    272		goto error;
    273	}
    274
    275	authkey = key_ref_to_ptr(authkey_ref);
    276	if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {
    277		key_put(authkey);
    278		authkey = ERR_PTR(-EKEYREVOKED);
    279	}
    280
    281error:
    282	return authkey;
    283}