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

ima_queue_keys.c (4120B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2019 Microsoft Corporation
      4 *
      5 * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
      6 *
      7 * File: ima_queue_keys.c
      8 *       Enables deferred processing of keys
      9 */
     10
     11#include <linux/user_namespace.h>
     12#include <linux/workqueue.h>
     13#include <keys/asymmetric-type.h>
     14#include "ima.h"
     15
     16/*
     17 * Flag to indicate whether a key can be processed
     18 * right away or should be queued for processing later.
     19 */
     20static bool ima_process_keys;
     21
     22/*
     23 * To synchronize access to the list of keys that need to be measured
     24 */
     25static DEFINE_MUTEX(ima_keys_lock);
     26static LIST_HEAD(ima_keys);
     27
     28/*
     29 * If custom IMA policy is not loaded then keys queued up
     30 * for measurement should be freed. This worker is used
     31 * for handling this scenario.
     32 */
     33static long ima_key_queue_timeout = 300000; /* 5 Minutes */
     34static void ima_keys_handler(struct work_struct *work);
     35static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler);
     36static bool timer_expired;
     37
     38/*
     39 * This worker function frees keys that may still be
     40 * queued up in case custom IMA policy was not loaded.
     41 */
     42static void ima_keys_handler(struct work_struct *work)
     43{
     44	timer_expired = true;
     45	ima_process_queued_keys();
     46}
     47
     48/*
     49 * This function sets up a worker to free queued keys in case
     50 * custom IMA policy was never loaded.
     51 */
     52void ima_init_key_queue(void)
     53{
     54	schedule_delayed_work(&ima_keys_delayed_work,
     55			      msecs_to_jiffies(ima_key_queue_timeout));
     56}
     57
     58static void ima_free_key_entry(struct ima_key_entry *entry)
     59{
     60	if (entry) {
     61		kfree(entry->payload);
     62		kfree(entry->keyring_name);
     63		kfree(entry);
     64	}
     65}
     66
     67static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring,
     68						 const void *payload,
     69						 size_t payload_len)
     70{
     71	int rc = 0;
     72	const char *audit_cause = "ENOMEM";
     73	struct ima_key_entry *entry;
     74
     75	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
     76	if (entry) {
     77		entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
     78		entry->keyring_name = kstrdup(keyring->description,
     79					      GFP_KERNEL);
     80		entry->payload_len = payload_len;
     81	}
     82
     83	if ((entry == NULL) || (entry->payload == NULL) ||
     84	    (entry->keyring_name == NULL)) {
     85		rc = -ENOMEM;
     86		goto out;
     87	}
     88
     89	INIT_LIST_HEAD(&entry->list);
     90
     91out:
     92	if (rc) {
     93		integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL,
     94					keyring->description,
     95					func_measure_str(KEY_CHECK),
     96					audit_cause, rc, 0, rc);
     97		ima_free_key_entry(entry);
     98		entry = NULL;
     99	}
    100
    101	return entry;
    102}
    103
    104bool ima_queue_key(struct key *keyring, const void *payload,
    105		   size_t payload_len)
    106{
    107	bool queued = false;
    108	struct ima_key_entry *entry;
    109
    110	entry = ima_alloc_key_entry(keyring, payload, payload_len);
    111	if (!entry)
    112		return false;
    113
    114	mutex_lock(&ima_keys_lock);
    115	if (!ima_process_keys) {
    116		list_add_tail(&entry->list, &ima_keys);
    117		queued = true;
    118	}
    119	mutex_unlock(&ima_keys_lock);
    120
    121	if (!queued)
    122		ima_free_key_entry(entry);
    123
    124	return queued;
    125}
    126
    127/*
    128 * ima_process_queued_keys() - process keys queued for measurement
    129 *
    130 * This function sets ima_process_keys to true and processes queued keys.
    131 * From here on keys will be processed right away (not queued).
    132 */
    133void ima_process_queued_keys(void)
    134{
    135	struct ima_key_entry *entry, *tmp;
    136	bool process = false;
    137
    138	if (ima_process_keys)
    139		return;
    140
    141	/*
    142	 * Since ima_process_keys is set to true, any new key will be
    143	 * processed immediately and not be queued to ima_keys list.
    144	 * First one setting the ima_process_keys flag to true will
    145	 * process the queued keys.
    146	 */
    147	mutex_lock(&ima_keys_lock);
    148	if (!ima_process_keys) {
    149		ima_process_keys = true;
    150		process = true;
    151	}
    152	mutex_unlock(&ima_keys_lock);
    153
    154	if (!process)
    155		return;
    156
    157	if (!timer_expired)
    158		cancel_delayed_work_sync(&ima_keys_delayed_work);
    159
    160	list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
    161		if (!timer_expired)
    162			process_buffer_measurement(&init_user_ns, NULL,
    163						   entry->payload,
    164						   entry->payload_len,
    165						   entry->keyring_name,
    166						   KEY_CHECK, 0,
    167						   entry->keyring_name,
    168						   false, NULL, 0);
    169		list_del(&entry->list);
    170		ima_free_key_entry(entry);
    171	}
    172}
    173
    174inline bool ima_should_queue_key(void)
    175{
    176	return !ima_process_keys;
    177}