linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
To: zohar@linux.ibm.com, dhowells@redhat.com, casey@schaufler-ca.com,
	sashal@kernel.org, jamorris@linux.microsoft.com,
	linux-security-module@vger.kernel.org,
	linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org,
	keyrings@vger.kernel.org
Cc: nramas@linux.microsoft.com
Subject: [PATCH v1 4/6] KEYS: ima functions to queue and dequeue keys to measure
Date: Tue, 22 Oct 2019 17:18:16 -0700	[thread overview]
Message-ID: <20191023001818.3684-5-nramas@linux.microsoft.com> (raw)
In-Reply-To: <20191023001818.3684-1-nramas@linux.microsoft.com>

Implement functions to queue a key for measurement if ima is not yet
initialized. And, when ima initialization is complete, process
any queued key measurement requests.

This change set implements the functions to queue and de-queue requests.
The change to actually measure the keys is in another patch.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 security/integrity/ima/ima.h       |  15 ++++
 security/integrity/ima/ima_init.c  |  11 ++-
 security/integrity/ima/ima_queue.c | 128 +++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 0d2908036882..7e4d4169798d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -21,6 +21,7 @@
 #include <linux/tpm.h>
 #include <linux/audit.h>
 #include <crypto/hash_info.h>
+#include <keys/asymmetric-type.h>
 
 #include "../integrity.h"
 
@@ -52,6 +53,7 @@ extern int ima_policy_flag;
 extern int ima_hash_algo;
 extern int ima_appraise;
 extern struct tpm_chip *ima_tpm_chip;
+extern bool ima_initialized;
 
 /* IMA event related data */
 struct ima_event_data {
@@ -158,6 +160,8 @@ void ima_init_template_list(void);
 int __init ima_init_digests(void);
 int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
 			  void *lsm_data);
+int ima_measure_key(struct key *keyring, struct key *key);
+void ima_measure_queued_trusted_keys(void);
 
 /*
  * used to protect h_table and sha_table
@@ -197,6 +201,17 @@ enum ima_hooks {
 	__ima_hooks(__ima_hook_enumify)
 };
 
+/*
+ * To track trusted keys that need to be measured when IMA is initialized.
+ */
+struct ima_trusted_key_entry {
+	struct list_head list;
+	void *public_key;
+	u32  public_key_len;
+	char *key_description;
+	enum ima_hooks func;
+};
+
 /* LIM API function definitions */
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
 		   int mask, enum ima_hooks func, int *pcr,
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 5d55ade5f3b9..32b9147fe410 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -23,6 +23,7 @@
 /* name for boot aggregate entry */
 static const char boot_aggregate_name[] = "boot_aggregate";
 struct tpm_chip *ima_tpm_chip;
+bool ima_initialized;
 
 /* Add the boot aggregate to the IMA measurement list and extend
  * the PCR register.
@@ -131,5 +132,13 @@ int __init ima_init(void)
 
 	ima_init_policy();
 
-	return ima_fs_init();
+	rc = ima_fs_init();
+	if (rc != 0)
+		return rc;
+
+	ima_initialized = true;
+
+	ima_measure_queued_trusted_keys();
+
+	return 0;
 }
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 1ce8b1701566..a262e289615b 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -19,6 +19,8 @@
 
 #include <linux/rculist.h>
 #include <linux/slab.h>
+#include <crypto/public_key.h>
+#include <keys/system_keyring.h>
 #include "ima.h"
 
 #define AUDIT_CAUSE_LEN_MAX 32
@@ -46,6 +48,13 @@ struct ima_h_table ima_htable = {
  */
 static DEFINE_MUTEX(ima_extend_list_mutex);
 
+/*
+ * Used to synchronize access to the list of trusted keys (ima_trusted_keys)
+ * that need to be measured when IMA is initialized.
+ */
+static DEFINE_MUTEX(ima_trusted_keys_mutex);
+static LIST_HEAD(ima_trusted_keys);
+
 /* lookup up the digest value in the hash table, and return the entry */
 static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 						       int pcr)
@@ -232,3 +241,122 @@ int __init ima_init_digests(void)
 
 	return 0;
 }
+
+/*
+ * Maps the given keyring to a IMA Hook.
+ * @keyring: A keyring to which a key maybe linked to.
+ *
+ * This function currently handles only builtin_trusted_keys.
+ * To handle more keyrings, this function, ima hook and
+ * ima policy handler need to be updated.
+ */
+static enum ima_hooks keyring_policy_map(struct key *keyring)
+{
+	enum ima_hooks func = NONE;
+
+	if (is_builtin_trusted_keyring(keyring))
+		func = BUILTIN_TRUSTED_KEYS;
+
+	return func;
+}
+
+static void ima_free_trusted_key_entry(struct ima_trusted_key_entry *entry)
+{
+	if (entry != NULL) {
+		if (entry->public_key != NULL)
+			kzfree(entry->public_key);
+		if (entry->key_description != NULL)
+			kzfree(entry->key_description);
+		kzfree(entry);
+	}
+}
+
+static struct ima_trusted_key_entry *ima_alloc_trusted_queue_entry(
+	struct key *key,
+	enum ima_hooks func)
+{
+	int rc = 0;
+	const struct public_key *pk;
+	size_t key_description_len;
+	struct ima_trusted_key_entry *entry = NULL;
+
+	pk = key->payload.data[asym_crypto];
+	key_description_len = strlen(key->description) + 1;
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (entry != NULL) {
+		entry->public_key = kzalloc(pk->keylen, GFP_KERNEL);
+		entry->key_description =
+			kzalloc(key_description_len, GFP_KERNEL);
+	}
+
+	if ((entry == NULL) || (entry->public_key == NULL) ||
+	    (entry->key_description == NULL)) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	strcpy(entry->key_description, key->description);
+	memcpy(entry->public_key, pk->key, pk->keylen);
+	entry->public_key_len = pk->keylen;
+	entry->func = func;
+	rc = 0;
+
+out:
+	if (rc) {
+		ima_free_trusted_key_entry(entry);
+		entry = NULL;
+	}
+
+	return entry;
+}
+
+/*
+ * ima_measure_key
+ *     @keyring the keyring to which the key is linked to.
+ *     @key the key being created or updated
+ * Measure keys created or updated in the system
+ *
+ * On success return 0.
+ * Return appropriate error code on error
+ */
+int ima_measure_key(struct key *keyring, struct key *key)
+{
+	int rc = 0;
+	struct ima_trusted_key_entry *entry = NULL;
+	enum ima_hooks func;
+	bool queued = false;
+
+	func = keyring_policy_map(keyring);
+	if (func == NONE)
+		return 0;
+
+	mutex_lock(&ima_trusted_keys_mutex);
+
+	if (!ima_initialized) {
+		entry = ima_alloc_trusted_queue_entry(key, func);
+		if (entry != NULL) {
+			INIT_LIST_HEAD(&entry->list);
+			list_add_tail(&entry->list, &ima_trusted_keys);
+			queued = true;
+		} else
+			rc = -ENOMEM;
+	}
+
+	mutex_unlock(&ima_trusted_keys_mutex);
+
+	return rc;
+}
+
+void ima_measure_queued_trusted_keys(void)
+{
+	struct ima_trusted_key_entry *entry, *tmp;
+
+	mutex_lock(&ima_trusted_keys_mutex);
+
+	list_for_each_entry_safe(entry, tmp, &ima_trusted_keys, list) {
+		list_del(&entry->list);
+		ima_free_trusted_key_entry(entry);
+	}
+
+	mutex_unlock(&ima_trusted_keys_mutex);
+}
-- 
2.17.1


  parent reply	other threads:[~2019-10-23  0:18 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-23  0:18 [PATCH v1 0/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
2019-10-23  0:18 ` [PATCH v1 1/6] KEYS: Helper function to check if the given keyring is builtin_trusted_keys Lakshmi Ramasubramanian
2019-10-23  0:18 ` [PATCH v1 2/6] KEYS: ima: Refactored process_buffer_measurement function so that it can measure any buffer (and not just KEXEC_CMDLINE one) Lakshmi Ramasubramanian
2019-10-23 13:21   ` Mimi Zohar
2019-10-23  0:18 ` [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys Lakshmi Ramasubramanian
2019-10-23 13:22   ` Mimi Zohar
2019-10-23 14:49     ` Lakshmi Ramasubramanian
2019-10-23 17:03       ` Mimi Zohar
2019-10-23  0:18 ` Lakshmi Ramasubramanian [this message]
2019-10-23  0:18 ` [PATCH v1 5/6] KEYS: measure queued keys Lakshmi Ramasubramanian
2019-10-23 13:23   ` Mimi Zohar
2019-10-23 17:34     ` Lakshmi Ramasubramanian
2019-10-23 17:52       ` Mimi Zohar
2019-10-23 18:49         ` Mimi Zohar
2019-10-23  0:18 ` [PATCH v1 6/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
2019-10-23 18:09   ` Mimi Zohar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191023001818.3684-5-nramas@linux.microsoft.com \
    --to=nramas@linux.microsoft.com \
    --cc=casey@schaufler-ca.com \
    --cc=dhowells@redhat.com \
    --cc=jamorris@linux.microsoft.com \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=sashal@kernel.org \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).