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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/workqueue.h> 14 #include <keys/asymmetric-type.h> 15 #include "ima.h" 16 17 /* 18 * Flag to indicate whether a key can be processed 19 * right away or should be queued for processing later. 20 */ 21 static bool ima_process_keys; 22 23 /* 24 * To synchronize access to the list of keys that need to be measured 25 */ 26 static DEFINE_MUTEX(ima_keys_lock); 27 static LIST_HEAD(ima_keys); 28 29 /* 30 * If custom IMA policy is not loaded then keys queued up 31 * for measurement should be freed. This worker is used 32 * for handling this scenario. 33 */ 34 static long ima_key_queue_timeout = 300000; /* 5 Minutes */ 35 static void ima_keys_handler(struct work_struct *work); 36 static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler); 37 static bool timer_expired; 38 39 /* 40 * This worker function frees keys that may still be 41 * queued up in case custom IMA policy was not loaded. 42 */ 43 static void ima_keys_handler(struct work_struct *work) 44 { 45 timer_expired = true; 46 ima_process_queued_keys(); 47 } 48 49 /* 50 * This function sets up a worker to free queued keys in case 51 * custom IMA policy was never loaded. 52 */ 53 void ima_init_key_queue(void) 54 { 55 schedule_delayed_work(&ima_keys_delayed_work, 56 msecs_to_jiffies(ima_key_queue_timeout)); 57 } 58 59 static void ima_free_key_entry(struct ima_key_entry *entry) 60 { 61 if (entry) { 62 kfree(entry->payload); 63 kfree(entry->keyring_name); 64 kfree(entry); 65 } 66 } 67 68 static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring, 69 const void *payload, 70 size_t payload_len) 71 { 72 int rc = 0; 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 91 out: 92 if (rc) { 93 ima_free_key_entry(entry); 94 entry = NULL; 95 } 96 97 return entry; 98 } 99 100 bool ima_queue_key(struct key *keyring, const void *payload, 101 size_t payload_len) 102 { 103 bool queued = false; 104 struct ima_key_entry *entry; 105 106 entry = ima_alloc_key_entry(keyring, payload, payload_len); 107 if (!entry) 108 return false; 109 110 mutex_lock(&ima_keys_lock); 111 if (!ima_process_keys) { 112 list_add_tail(&entry->list, &ima_keys); 113 queued = true; 114 } 115 mutex_unlock(&ima_keys_lock); 116 117 if (!queued) 118 ima_free_key_entry(entry); 119 120 return queued; 121 } 122 123 /* 124 * ima_process_queued_keys() - process keys queued for measurement 125 * 126 * This function sets ima_process_keys to true and processes queued keys. 127 * From here on keys will be processed right away (not queued). 128 */ 129 void ima_process_queued_keys(void) 130 { 131 struct ima_key_entry *entry, *tmp; 132 bool process = false; 133 134 if (ima_process_keys) 135 return; 136 137 /* 138 * Since ima_process_keys is set to true, any new key will be 139 * processed immediately and not be queued to ima_keys list. 140 * First one setting the ima_process_keys flag to true will 141 * process the queued keys. 142 */ 143 mutex_lock(&ima_keys_lock); 144 if (!ima_process_keys) { 145 ima_process_keys = true; 146 process = true; 147 } 148 mutex_unlock(&ima_keys_lock); 149 150 if (!process) 151 return; 152 153 if (!timer_expired) 154 cancel_delayed_work_sync(&ima_keys_delayed_work); 155 156 list_for_each_entry_safe(entry, tmp, &ima_keys, list) { 157 if (!timer_expired) 158 process_buffer_measurement(entry->payload, 159 entry->payload_len, 160 entry->keyring_name, 161 KEY_CHECK, 0, 162 entry->keyring_name); 163 list_del(&entry->list); 164 ima_free_key_entry(entry); 165 } 166 } 167 168 inline bool ima_should_queue_key(void) 169 { 170 return !ima_process_keys; 171 } 172