linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/6] KEYS: measure keys when they are created or updated
@ 2019-10-23  0:18 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
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

Problem Statement:

Keys created or updated in the system are currently not being measured.
Therefore an attestation service, for instance, would not be able to
attest whether or not the trusted keys keyring(s), for instance, contain
only known good (trusted) keys.

ima measures system files, command line arguments passed to kexec, and
boot aggregate. It can be used to measure keys as well. But there is
no mechanism available in the kernel for ima to know when a key is
created or updated.

This change aims to address measuring keys created or updated
in the system.

To achieve the above the following changes have been made:

 - A new LSM function namely, security_key_create_or_update, has
   been added. This function is called by key_create_or_update
   function when a new key is created or an existing key is updated.
   This call is made when the key has been instantiated and linked
   to the target keyring.

   security_key_create_or_update is passed the target keyring, key,
   key creation flags, and a boolean flag indicating whether
   the key was newly created or an existing key was updated.

 - Added a new ima hook namely, ima_post_key_create_or_update, which
   measures the key. The measurement can be controlled through ima policy.

   In this change set a new ima policy BUILTIN_TRUSTED_KEYS has been
   added to measure keys added to the builtin_trusted_keys keyring.
   In future, this can be extended to measure keys added to
   other keyrings.

Change Log:

  v1:

  => LSM function for key_create_or_update. It calls ima.
  => Added ima hook for measuring keys
  => ima measures keys based on ima policy.

  v0:

  => Added LSM hook for key_create_or_update.
  => Measure keys added to builtin or secondary trusted keys keyring.

Background:

Currently ima measures file hashes and .ima signatures. ima signatures
are validated against keys in the ".ima" keyring. If the kernel is built
with CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY enabled,
then all keys in ".ima" keyring must be signed by a key in
".builtin_trusted_keys" or ".secondary_trusted_keys" keyrings.

Although ima supports the above configuration, not having an insight
into what keys are present in these trusted keys keyrings would prevent
an attestation service from validating a client machine.
 
On systems with CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
enabled, measuring keys in the  ".builtin_trusted_keys" keyring provides
a mechanism to attest that the client's system binaries are indeed signed
by signers that chain to known trusted keys.

Without this change, to attest the clients one needs to maintain
an "allowed list" of file hashes of all versions of all client binaries
that are deployed on the clients in the enterprise. That is a huge
operational challenge in a large scale environment of clients with
heterogenous builds. This also limits scalability and agility of
rolling out frequent client binary updates.

Testing performed:

  * Booted the kernel with this change.
  * Executed keyctl tests from the Linux Test Project (LTP)
  * Added a new key to a keyring and verified "key create" code path.
    => In this case added a key to builtin_trusted_keys keyring.
    => Verified ima measured this key only when a policy is set.
  * Added the same key again and verified "key update" code path.
    => Add the same key to builtin_trusted_keys keyring.
    => Verified ima measured the key only when a policy is set.
  * Forced the LSM function security_key_create_or_update to
    return an error and verified that the key was not added to
    the keyring ("keyctl list <keyring>" does not list the key).

Questions and concerns raised by reviewers on this patch set:

Question 1:
Is "Signed with a trusted key" equal to "Trusted file"?
Doesn't the service need the hashes of the system files to determine
whether a file is trusted or not?
"Signed with a trusted key" does not equal "Trusted"

Answer:
Agree "Signed with a trusted key" may not equal "Trusted".
To address this, the attesting service can maintain a small
manageable set of bad hashes (a "Blocked list") and a list of
trusted keys expected in client's .builtin_trusted_keys" keyring.
Using this data, the service can detect the presence of
"Disallowed (untrusted) version of client binaries".

Question 2:
Providing more data to the service (such as ".builtin_trusted_keys"),
empowers the service  to deny access to clients (block clients).
IMA walks a fine line in enforcing and measuring file integrity.
This patchset breaches that fine line and in doing so brings back
the fears of trusted computing.

Answer:
Any new measurement we add in IMA will provide more data to service
and can enable it to deny access to clients. It is not clear why this patch
set would breach the fine line between measuring and enforcing.
Since this patch set is disabled by default and enabled through
CONFIG_IMA_MEASURE_TRUSTED_KEYS, only those enterprises that
require this new measurement can opt-in for it. Since it is disabled
by default, it does not restrict the autonomy of independent users
who are unaffected by attestation.

Question 3:
IMA log already contains a pointer to the IMA keys used for signature
verification. Why does the service need to care what keys were used
to sign (install) the IMA keys? What is gained by measuring the keys
in the ".builtin_trusted_keys"


Answer:
To attest the clients using the current IMA log, service needs to maintain
hashes of all the deployed versions of all the system binaries for their
enterprise. This will introduce a very high operational overhead in
a large scale environment of clients with heterogenous builds.
This limits scalability and agility of rolling out frequent client
binary updates.


On the other hand, with the current patch set, we will have IMA
validate the file signature on the clients and the service validate
that the IMA keys were installed using trusted keys.


This provides a chain of trust:
    => IMA Key validates file signature on the client
    => Built-In trusted key attests IMA key on the client
    => Attestation service attests the Built-In trusted keys
         reported by the client in the IMA log


This approach, therefore, would require the service to maintain
a manageble set of trusted keys that it receives from a trusted source.
And, verify if the clients only have keys from that set of trusted keys.

Question 4:
Where will the attestation service receive the keys to validate against?

Answer:
Attestation service will receive the keys from a trusted source such as
the enterprise build services that provides the client builds.
The service will use this set of keys to verify that the keys reported by
the clients in the IMA log contains only keys from this trusted list.


Question 5:
What is changing in the IMA log through this patch set?


Answer:
This patch set does not remove any data that is currently included
in the IMA log. It only adds more data to the IMA log - the data on
".builtin_trusted_keys"

Lakshmi Ramasubramanian (6):
  KEYS: Helper function to check if the given keyring is
    builtin_trusted_keys
  ima: Refactored process_buffer_measurement function so that it can
    measure any buffer (and not just KEXEC_CMDLINE one)
  KEYS: ima hook to measure builtin_trusted_keys
  KEYS: ima functions to queue and dequeue keys to measure
  KEYS: measure queued keys
  KEYS: measure keys when they are created or updated

 Documentation/ABI/testing/ima_policy |   1 +
 certs/system_keyring.c               |   5 +
 include/keys/system_keyring.h        |   2 +
 include/linux/ima.h                  |  15 ++-
 include/linux/security.h             |  13 ++-
 security/integrity/ima/ima.h         |  19 ++++
 security/integrity/ima/ima_api.c     |   1 +
 security/integrity/ima/ima_init.c    |  11 +-
 security/integrity/ima/ima_main.c    |  52 ++++++---
 security/integrity/ima/ima_policy.c  |   5 +-
 security/integrity/ima/ima_queue.c   | 160 +++++++++++++++++++++++++++
 security/keys/key.c                  |  78 +++++++++++--
 security/security.c                  |  10 ++
 13 files changed, 344 insertions(+), 28 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v1 1/6] KEYS: Helper function to check if the given keyring is builtin_trusted_keys
  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 ` 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
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

Helper function to check if the given keyring is
the builtin_trusted_keys keyring.

This function is used by ima to determine if a key is
added to the builtin_trusted_keys keyring.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 certs/system_keyring.c        | 5 +++++
 include/keys/system_keyring.h | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 1eba08a1af82..5533c7f92fef 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -283,3 +283,8 @@ void __init set_platform_trusted_keys(struct key *keyring)
 	platform_trusted_keys = keyring;
 }
 #endif
+
+inline bool is_builtin_trusted_keyring(struct key *keyring)
+{
+	return (keyring == builtin_trusted_keys);
+}
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index c1a96fdf598b..2bc0aaa07f05 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -66,4 +66,6 @@ static inline void set_platform_trusted_keys(struct key *keyring)
 }
 #endif
 
+extern bool is_builtin_trusted_keyring(struct key *keyring);
+
 #endif /* _KEYS_SYSTEM_KEYRING_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 2/6] KEYS: ima: Refactored process_buffer_measurement function so that it can measure any buffer (and not just KEXEC_CMDLINE one)
  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 ` 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
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

process_buffer_measurement currently supports measuring kexec command line
only. This function has been refactored to support more than kexec_cmdline.
With this change this function can be used for measuring any buffer.
This function is now also used by ima to measure keys besides used for
measuring kexec command line.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 security/integrity/ima/ima.h      |  3 +++
 security/integrity/ima/ima_main.c | 29 ++++++++++++++---------------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 011b91c79351..b6847ee1f47a 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -209,6 +209,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
 			   struct evm_ima_xattr_data *xattr_value,
 			   int xattr_len, int pcr,
 			   struct ima_template_desc *template_desc);
+void process_buffer_measurement(const void *buf, int size,
+				const char *eventname, int pcr,
+				struct ima_template_desc *template_desc);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
 			   const unsigned char *filename);
 int ima_alloc_init_template(struct ima_event_data *event_data,
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 584019728660..8e965d18fb21 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -610,14 +610,14 @@ int ima_load_data(enum kernel_load_data_id id)
  * @buf: pointer to the buffer that needs to be added to the log.
  * @size: size of buffer(in bytes).
  * @eventname: event name to be used for the buffer entry.
- * @cred: a pointer to a credentials structure for user validation.
- * @secid: the secid of the task to be validated.
+ * @pcr: pcr to extend the measurement
+ * @template_desc: template description
  *
  * Based on policy, the buffer is measured into the ima log.
  */
-static void process_buffer_measurement(const void *buf, int size,
-				       const char *eventname,
-				       const struct cred *cred, u32 secid)
+void process_buffer_measurement(const void *buf, int size,
+				const char *eventname, int pcr,
+				struct ima_template_desc *template_desc)
 {
 	int ret = 0;
 	struct ima_template_entry *entry = NULL;
@@ -626,19 +626,11 @@ static void process_buffer_measurement(const void *buf, int size,
 					    .filename = eventname,
 					    .buf = buf,
 					    .buf_len = size};
-	struct ima_template_desc *template_desc = NULL;
 	struct {
 		struct ima_digest_data hdr;
 		char digest[IMA_MAX_DIGEST_SIZE];
 	} hash = {};
 	int violation = 0;
-	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
-	int action = 0;
-
-	action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, &pcr,
-				&template_desc);
-	if (!(action & IMA_MEASURE))
-		return;
 
 	iint.ima_hash = &hash.hdr;
 	iint.ima_hash->algo = ima_hash_algo;
@@ -670,12 +662,19 @@ static void process_buffer_measurement(const void *buf, int size,
  */
 void ima_kexec_cmdline(const void *buf, int size)
 {
+	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+	struct ima_template_desc *template_desc = ima_template_desc_current();
+	int action;
 	u32 secid;
 
 	if (buf && size != 0) {
 		security_task_getsecid(current, &secid);
-		process_buffer_measurement(buf, size, "kexec-cmdline",
-					   current_cred(), secid);
+		action = ima_get_action(NULL, current_cred(), secid, 0,
+					KEXEC_CMDLINE, &pcr, &template_desc);
+		if (!(action & IMA_MEASURE))
+			return;
+		process_buffer_measurement(buf, size, "kexec-cmdline", pcr,
+					   template_desc);
 	}
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys
  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  0:18 ` Lakshmi Ramasubramanian
  2019-10-23 13:22   ` Mimi Zohar
  2019-10-23  0:18 ` [PATCH v1 4/6] KEYS: ima functions to queue and dequeue keys to measure Lakshmi Ramasubramanian
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

Add a new ima hook to measure keys added to builtin_trusted_keys
keyring.

Updated ima_match_rules function to handle the new ima hook.
This is used to determine if ima policy requires measurement
of keys added to builtin_trusted_keys keyring.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 Documentation/ABI/testing/ima_policy | 1 +
 security/integrity/ima/ima.h         | 1 +
 security/integrity/ima/ima_api.c     | 1 +
 security/integrity/ima/ima_policy.c  | 5 ++++-
 4 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index fc376a323908..25566c74e679 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -29,6 +29,7 @@ Description:
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
 				[KEXEC_CMDLINE]
+				[BUILTIN_TRUSTED_KEYS]
 			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
 			       [[^]MAY_EXEC]
 			fsmagic:= hex value
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b6847ee1f47a..0d2908036882 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -189,6 +189,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
 	hook(KEXEC_INITRAMFS_CHECK)	\
 	hook(POLICY_CHECK)		\
 	hook(KEXEC_CMDLINE)		\
+	hook(BUILTIN_TRUSTED_KEYS)	\
 	hook(MAX_CHECK)
 #define __ima_hook_enumify(ENUM)	ENUM,
 
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index f614e22bf39f..cc04706b7e7a 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -175,6 +175,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
  *	subj,obj, and type: are LSM specific.
  *	func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
  *	| KEXEC_CMDLINE
+ *	| BUILTIN_TRUSTED_KEYS
  *	mask: contains the permission mask
  *	fsmagic: hex value
  *
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 6df7f641ff66..944636076152 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -370,7 +370,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 {
 	int i;
 
-	if (func == KEXEC_CMDLINE) {
+	if ((func == KEXEC_CMDLINE) || (func == BUILTIN_TRUSTED_KEYS)) {
 		if ((rule->flags & IMA_FUNC) && (rule->func == func))
 			return true;
 		return false;
@@ -959,6 +959,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 				entry->func = POLICY_CHECK;
 			else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
 				entry->func = KEXEC_CMDLINE;
+			else if (strcmp(args[0].from,
+					"BUILTIN_TRUSTED_KEYS") == 0)
+				entry->func = BUILTIN_TRUSTED_KEYS;
 			else
 				result = -EINVAL;
 			if (!result)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 4/6] KEYS: ima functions to queue and dequeue keys to measure
  2019-10-23  0:18 [PATCH v1 0/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
                   ` (2 preceding siblings ...)
  2019-10-23  0:18 ` [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys Lakshmi Ramasubramanian
@ 2019-10-23  0:18 ` Lakshmi Ramasubramanian
  2019-10-23  0:18 ` [PATCH v1 5/6] KEYS: measure queued keys Lakshmi Ramasubramanian
  2019-10-23  0:18 ` [PATCH v1 6/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
  5 siblings, 0 replies; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

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


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 5/6] KEYS: measure queued keys
  2019-10-23  0:18 [PATCH v1 0/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
                   ` (3 preceding siblings ...)
  2019-10-23  0:18 ` [PATCH v1 4/6] KEYS: ima functions to queue and dequeue keys to measure Lakshmi Ramasubramanian
@ 2019-10-23  0:18 ` Lakshmi Ramasubramanian
  2019-10-23 13:23   ` Mimi Zohar
  2019-10-23  0:18 ` [PATCH v1 6/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
  5 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

Call process_buffer_measurement to measure keys that
are added and updated in the system.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 security/integrity/ima/ima_main.c  | 23 +++++++++++++++++++++
 security/integrity/ima/ima_queue.c | 32 ++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 8e965d18fb21..7c2afb954f19 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -678,6 +678,29 @@ void ima_kexec_cmdline(const void *buf, int size)
 	}
 }
 
+/*
+ * ima_post_key_create_or_update
+ * @keyring points to the keyring to which the key belongs
+ * @key points to the key being created or updated
+ * @cred cred structure
+ * @flags flags passed to key_create_or_update function
+ * @create flag to indicate whether the key was created or updated
+ *
+ * IMA hook called when a new key is created or updated.
+ *
+ * On success return 0.
+ * Return appropriate error code on error
+ */
+int ima_post_key_create_or_update(struct key *keyring, struct key *key,
+				  const struct cred *cred,
+				  unsigned long flags, bool create)
+{
+	if (key->type != &key_type_asymmetric)
+		return 0;
+
+	return ima_measure_key(keyring, key);
+}
+
 static int __init init_ima(void)
 {
 	int error;
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index a262e289615b..0da11a292f99 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -322,7 +322,12 @@ static struct ima_trusted_key_entry *ima_alloc_trusted_queue_entry(
 int ima_measure_key(struct key *keyring, struct key *key)
 {
 	int rc = 0;
+	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+	struct ima_template_desc *template_desc = ima_template_desc_current();
+	int action;
 	struct ima_trusted_key_entry *entry = NULL;
+	const struct public_key *pk;
+	u32 secid;
 	enum ima_hooks func;
 	bool queued = false;
 
@@ -344,16 +349,43 @@ int ima_measure_key(struct key *keyring, struct key *key)
 
 	mutex_unlock(&ima_trusted_keys_mutex);
 
+	if ((rc == 0) && !queued) {
+		security_task_getsecid(current, &secid);
+		action = ima_get_action(NULL, current_cred(), secid, 0,
+					func, &pcr, &template_desc);
+		if (action & IMA_MEASURE) {
+			pk = key->payload.data[asym_crypto];
+			process_buffer_measurement(pk->key, pk->keylen,
+						   key->description,
+						   pcr, template_desc);
+		}
+	}
+
 	return rc;
 }
 
 void ima_measure_queued_trusted_keys(void)
 {
 	struct ima_trusted_key_entry *entry, *tmp;
+	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+	struct ima_template_desc *template_desc = ima_template_desc_current();
+	int action;
+	u32 secid;
 
 	mutex_lock(&ima_trusted_keys_mutex);
 
 	list_for_each_entry_safe(entry, tmp, &ima_trusted_keys, list) {
+		security_task_getsecid(current, &secid);
+		action = ima_get_action(NULL, current_cred(), secid, 0,
+					entry->func, &pcr,
+					&template_desc);
+		if (action & IMA_MEASURE) {
+			process_buffer_measurement(entry->public_key,
+						   entry->public_key_len,
+						   entry->key_description,
+						   pcr,
+						   template_desc);
+		}
 		list_del(&entry->list);
 		ima_free_trusted_key_entry(entry);
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 6/6] KEYS: measure keys when they are created or updated
  2019-10-23  0:18 [PATCH v1 0/6] KEYS: measure keys when they are created or updated Lakshmi Ramasubramanian
                   ` (4 preceding siblings ...)
  2019-10-23  0:18 ` [PATCH v1 5/6] KEYS: measure queued keys Lakshmi Ramasubramanian
@ 2019-10-23  0:18 ` Lakshmi Ramasubramanian
  2019-10-23 18:09   ` Mimi Zohar
  5 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23  0:18 UTC (permalink / raw)
  To: zohar, dhowells, casey, sashal, jamorris, linux-security-module,
	linux-integrity, linux-kernel, keyrings
  Cc: nramas

A new LSM function namely, security_key_create_or_update, has
been added. This function is called by key_create_or_update
function when a new key is created or an existing key is updated.
This call is made when the key has been instantiated and linked
to the target keyring.

security_key_create_or_update is passed the target keyring, key,
key creation flags, and a boolean flag indicating whether
the key was newly created or an existing key was updated.
This function calls the ima function ima_post_key_create_or_update
to measure the key.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 include/linux/ima.h      | 15 +++++++-
 include/linux/security.h | 13 ++++++-
 security/keys/key.c      | 78 +++++++++++++++++++++++++++++++++++-----
 security/security.c      | 10 ++++++
 4 files changed, 105 insertions(+), 11 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index a20ad398d260..ce763901380d 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -24,7 +24,11 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
 			      enum kernel_read_file_id id);
 extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_kexec_cmdline(const void *buf, int size);
-
+extern int ima_post_key_create_or_update(struct key *keyring,
+					 struct key *key,
+					 const struct cred *cred,
+					 unsigned long flags,
+					 bool create);
 #ifdef CONFIG_IMA_KEXEC
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
@@ -91,6 +95,15 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
 }
 
 static inline void ima_kexec_cmdline(const void *buf, int size) {}
+
+static inline int ima_post_key_create_or_update(struct key *keyring,
+						struct key *key,
+						const struct cred *cred,
+						unsigned long flags,
+						bool create)
+{
+	return 0;
+}
 #endif /* CONFIG_IMA */
 
 #ifndef CONFIG_IMA_KEXEC
diff --git a/include/linux/security.h b/include/linux/security.h
index 5f7441abbf42..c8348da3db2e 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1677,7 +1677,9 @@ void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
 			    const struct cred *cred, unsigned perm);
 int security_key_getsecurity(struct key *key, char **_buffer);
-
+int security_key_create_or_update(struct key *keyring, struct key *key,
+				  const struct cred *cred,
+				  unsigned long flags, bool create);
 #else
 
 static inline int security_key_alloc(struct key *key,
@@ -1704,6 +1706,15 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer)
 	return 0;
 }
 
+static inline int security_key_create_or_update(struct key *keyring,
+						struct key *key,
+						const struct cred *cred,
+						unsigned long flags,
+						bool create)
+{
+	return 0;
+}
+
 #endif
 #endif /* CONFIG_KEYS */
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 764f4c57913e..b913feaf196e 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -781,7 +781,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
 }
 
 /**
- * key_create_or_update - Update or create and instantiate a key.
+ * __key_create_or_update - Update or create and instantiate a key.
  * @keyring_ref: A pointer to the destination keyring with possession flag.
  * @type: The type of key.
  * @description: The searchable description for the key.
@@ -789,6 +789,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
  * @plen: The length of @payload.
  * @perm: The permissions mask for a new key.
  * @flags: The quota flags for a new key.
+ * @create: Set to true if the key was newly created.
+ *          Set to false if the key was updated.
  *
  * Search the destination keyring for a key of the same description and if one
  * is found, update it, otherwise create and instantiate a new one and create a
@@ -805,13 +807,14 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
  * On success, the possession flag from the keyring ref will be tacked on to
  * the key ref before it is returned.
  */
-key_ref_t key_create_or_update(key_ref_t keyring_ref,
-			       const char *type,
-			       const char *description,
-			       const void *payload,
-			       size_t plen,
-			       key_perm_t perm,
-			       unsigned long flags)
+static key_ref_t __key_create_or_update(key_ref_t keyring_ref,
+					const char *type,
+					const char *description,
+					const void *payload,
+					size_t plen,
+					key_perm_t perm,
+					unsigned long flags,
+					bool *create)
 {
 	struct keyring_index_key index_key = {
 		.description	= description,
@@ -936,6 +939,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		goto error_link_end;
 	}
 
+	*create = true;
 	key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
 
 error_link_end:
@@ -948,7 +952,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 error:
 	return key_ref;
 
- found_matching_key:
+found_matching_key:
 	/* we found a matching key, so we're going to try to update it
 	 * - we can drop the locks first as we have the key pinned
 	 */
@@ -964,9 +968,65 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		}
 	}
 
+	*create = false;
 	key_ref = __key_update(key_ref, &prep);
 	goto error_free_prep;
 }
+
+/**
+ * key_create_or_update - Update or create and instantiate a key.
+ * @keyring_ref: A pointer to the destination keyring with possession flag.
+ * @type: The type of key.
+ * @description: The searchable description for the key.
+ * @payload: The data to use to instantiate or update the key.
+ * @plen: The length of @payload.
+ * @perm: The permissions mask for a new key.
+ * @flags: The quota flags for a new key.
+ *
+ * Calls the internal function __key_create_or_update.
+ * If successful calls the security LSM hook.
+ */
+key_ref_t key_create_or_update(key_ref_t keyring_ref,
+			       const char *type,
+			       const char *description,
+			       const void *payload,
+			       size_t plen,
+			       key_perm_t perm,
+			       unsigned long flags)
+{
+	key_ref_t key_ref;
+	struct key *keyring, *key = NULL;
+	int ret = 0;
+	bool create = false;
+
+	key_ref = __key_create_or_update(keyring_ref, type, description,
+					 payload, plen, perm, flags,
+					 &create);
+	if (IS_ERR(key_ref))
+		goto out;
+
+	keyring = key_ref_to_ptr(keyring_ref);
+	key = key_ref_to_ptr(key_ref);
+
+	/* let the security module know about
+	 * the created or updated key.
+	 */
+	ret = security_key_create_or_update(keyring, key,
+					    current_cred(),
+					    flags, create);
+	if (ret < 0)
+		goto security_error;
+	else
+		goto out;
+
+security_error:
+	key_unlink(keyring, key);
+	key_put(key);
+	key_ref = ERR_PTR(ret);
+
+out:
+	return key_ref;
+}
 EXPORT_SYMBOL(key_create_or_update);
 
 /**
diff --git a/security/security.c b/security/security.c
index 250ee2d76406..707a9e7fa94d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2303,6 +2303,16 @@ int security_key_getsecurity(struct key *key, char **_buffer)
 	return call_int_hook(key_getsecurity, 0, key, _buffer);
 }
 
+int security_key_create_or_update(struct key *keyring,
+				  struct key *key,
+				  const struct cred *cred,
+				  unsigned long flags,
+				  bool create)
+{
+	return ima_post_key_create_or_update(keyring, key, cred,
+					     flags, create);
+}
+
 #endif	/* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 2/6] KEYS: ima: Refactored process_buffer_measurement function so that it can measure any buffer (and not just KEXEC_CMDLINE one)
  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
  0 siblings, 0 replies; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 13:21 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Tue, 2019-10-22 at 17:18 -0700, Lakshmi Ramasubramanian wrote:

> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 584019728660..8e965d18fb21 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -610,14 +610,14 @@ int ima_load_data(enum kernel_load_data_id id)
>   * @buf: pointer to the buffer that needs to be added to the log.
>   * @size: size of buffer(in bytes).
>   * @eventname: event name to be used for the buffer entry.
> - * @cred: a pointer to a credentials structure for user validation.
> - * @secid: the secid of the task to be validated.
> + * @pcr: pcr to extend the measurement
> + * @template_desc: template description
>   *
>   * Based on policy, the buffer is measured into the ima log.
>   */
> -static void process_buffer_measurement(const void *buf, int size,
> -				       const char *eventname,
> -				       const struct cred *cred, u32 secid)
> +void process_buffer_measurement(const void *buf, int size,
> +				const char *eventname, int pcr,
> +				struct ima_template_desc *template_desc)
>  {
>  	int ret = 0;
>  	struct ima_template_entry *entry = NULL;
> @@ -626,19 +626,11 @@ static void process_buffer_measurement(const void *buf, int size,
>  					    .filename = eventname,
>  					    .buf = buf,
>  					    .buf_len = size};
> -	struct ima_template_desc *template_desc = NULL;
>  	struct {
>  		struct ima_digest_data hdr;
>  		char digest[IMA_MAX_DIGEST_SIZE];
>  	} hash = {};
>  	int violation = 0;
> -	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
> -	int action = 0;
> -
> -	action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, &pcr,
> -				&template_desc);
> -	if (!(action & IMA_MEASURE))
> -		return;
>  
>  	iint.ima_hash = &hash.hdr;
>  	iint.ima_hash->algo = ima_hash_algo;


This patch is based on Nayna's version of this change, without any
acknowledgment.  Moving this code out of process_buffer_measurement is
going to result in code duplication.  Nayna has posted a newer version
of this patch without the code duplication.  As soon as she posts the
patch with an updated patch description, I plan on picking up that
version.

Mimi


> @@ -670,12 +662,19 @@ static void process_buffer_measurement(const void *buf, int size,
>   */
>  void ima_kexec_cmdline(const void *buf, int size)
>  {
> +	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
> +	struct ima_template_desc *template_desc = ima_template_desc_current();
> +	int action;
>  	u32 secid;
>  
>  	if (buf && size != 0) {
>  		security_task_getsecid(current, &secid);
> -		process_buffer_measurement(buf, size, "kexec-cmdline",
> -					   current_cred(), secid);
> +		action = ima_get_action(NULL, current_cred(), secid, 0,
> +					KEXEC_CMDLINE, &pcr, &template_desc);
> +		if (!(action & IMA_MEASURE))
> +			return;
> +		process_buffer_measurement(buf, size, "kexec-cmdline", pcr,
> +					   template_desc);
>  	}
>  }
>  


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys
  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
  0 siblings, 1 reply; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 13:22 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Tue, 2019-10-22 at 17:18 -0700, Lakshmi Ramasubramanian wrote:
> Add a new ima hook to measure keys added to builtin_trusted_keys
> keyring.

There is no IMA hook in this patch.

> 
> Updated ima_match_rules function to handle the new ima hook.
> This is used to determine if ima policy requires measurement
> of keys added to builtin_trusted_keys keyring.
> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> ---
>  Documentation/ABI/testing/ima_policy | 1 +
>  security/integrity/ima/ima.h         | 1 +
>  security/integrity/ima/ima_api.c     | 1 +
>  security/integrity/ima/ima_policy.c  | 5 ++++-
>  4 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> index fc376a323908..25566c74e679 100644
> --- a/Documentation/ABI/testing/ima_policy
> +++ b/Documentation/ABI/testing/ima_policy
> @@ -29,6 +29,7 @@ Description:
>  				[FIRMWARE_CHECK]
>  				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
>  				[KEXEC_CMDLINE]
> +				[BUILTIN_TRUSTED_KEYS]
>  			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
>  			       [[^]MAY_EXEC]
>  			fsmagic:= hex value
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index b6847ee1f47a..0d2908036882 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -189,6 +189,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
>  	hook(KEXEC_INITRAMFS_CHECK)	\
>  	hook(POLICY_CHECK)		\
>  	hook(KEXEC_CMDLINE)		\
> +	hook(BUILTIN_TRUSTED_KEYS)	\
>  	hook(MAX_CHECK)
>  #define __ima_hook_enumify(ENUM)	ENUM,
>  
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index f614e22bf39f..cc04706b7e7a 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -175,6 +175,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
>   *	subj,obj, and type: are LSM specific.
>   *	func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
>   *	| KEXEC_CMDLINE
> + *	| BUILTIN_TRUSTED_KEYS
>   *	mask: contains the permission mask
>   *	fsmagic: hex value
>   *
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 6df7f641ff66..944636076152 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -370,7 +370,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
>  {
>  	int i;
>  
> -	if (func == KEXEC_CMDLINE) {
> +	if ((func == KEXEC_CMDLINE) || (func == BUILTIN_TRUSTED_KEYS)) {
>  		if ((rule->flags & IMA_FUNC) && (rule->func == func))
>  			return true;
>  		return false;
> @@ -959,6 +959,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				entry->func = POLICY_CHECK;
>  			else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
>  				entry->func = KEXEC_CMDLINE;
> +			else if (strcmp(args[0].from,
> +					"BUILTIN_TRUSTED_KEYS") == 0)
> +				entry->func = BUILTIN_TRUSTED_KEYS;
>  			else
>  				result = -EINVAL;
>  			if (!result)

Any new options need to be displayed as well.

Mimi


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] KEYS: measure queued keys
  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
  0 siblings, 1 reply; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 13:23 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Tue, 2019-10-22 at 17:18 -0700, Lakshmi Ramasubramanian wrote:
> Call process_buffer_measurement to measure keys that
> are added and updated in the system.

This patch description doesn't describe what the patch actually does
(eg. it not only calls process_buffer_measurement, but defines the IMA
hook itself.)

The ordering of this patch set is awkward.  It should first introduce
a generic method for measuring keys based on the keyring.  Then add
the additional support needed for the specific builtin_trusted_keys
keyring usecase.

> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> ---
>  security/integrity/ima/ima_main.c  | 23 +++++++++++++++++++++
>  security/integrity/ima/ima_queue.c | 32 ++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+)
> 
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 8e965d18fb21..7c2afb954f19 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -678,6 +678,29 @@ void ima_kexec_cmdline(const void *buf, int size)
>  	}
>  }
>  
> +/*
> + * ima_post_key_create_or_update
> + * @keyring points to the keyring to which the key belongs
> + * @key points to the key being created or updated
> + * @cred cred structure
> + * @flags flags passed to key_create_or_update function
> + * @create flag to indicate whether the key was created or updated
> + *
> + * IMA hook called when a new key is created or updated.
> + *
> + * On success return 0.
> + * Return appropriate error code on error
> + */
> +int ima_post_key_create_or_update(struct key *keyring, struct key *key,
> +				  const struct cred *cred,
> +				  unsigned long flags, bool create)
> +{
> +	if (key->type != &key_type_asymmetric)
> +		return 0;
> +
> +	return ima_measure_key(keyring, key);
> +}
> +

Here is the new IMA hook, not "[PATCH v1 3/6] KEYS: ima hook to
measure builtin_trusted_keys".  The new hook should call
process_buffer_measurement() directly.  A subsequent patch, based on
the keyring, would determine if it needs to be queued.

Mimi


>  static int __init init_ima(void)
>  {
>  	int error;
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index a262e289615b..0da11a292f99 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -322,7 +322,12 @@ static struct ima_trusted_key_entry *ima_alloc_trusted_queue_entry(
>  int ima_measure_key(struct key *keyring, struct key *key)
>  {
>  	int rc = 0;
> +	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
> +	struct ima_template_desc *template_desc = ima_template_desc_current();
> +	int action;
>  	struct ima_trusted_key_entry *entry = NULL;
> +	const struct public_key *pk;
> +	u32 secid;
>  	enum ima_hooks func;
>  	bool queued = false;
>  
> @@ -344,16 +349,43 @@ int ima_measure_key(struct key *keyring, struct key *key)
>  
>  	mutex_unlock(&ima_trusted_keys_mutex);
>  
> +	if ((rc == 0) && !queued) {
> +		security_task_getsecid(current, &secid);
> +		action = ima_get_action(NULL, current_cred(), secid, 0,
> +					func, &pcr, &template_desc);
> +		if (action & IMA_MEASURE) {
> +			pk = key->payload.data[asym_crypto];
> +			process_buffer_measurement(pk->key, pk->keylen,
> +						   key->description,
> +						   pcr, template_desc);
> +		}
> +	}
> +
>  	return rc;
>  }
>  
>  void ima_measure_queued_trusted_keys(void)
>  {
>  	struct ima_trusted_key_entry *entry, *tmp;
> +	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
> +	struct ima_template_desc *template_desc = ima_template_desc_current();
> +	int action;
> +	u32 secid;
>  
>  	mutex_lock(&ima_trusted_keys_mutex);
>  
>  	list_for_each_entry_safe(entry, tmp, &ima_trusted_keys, list) {
> +		security_task_getsecid(current, &secid);
> +		action = ima_get_action(NULL, current_cred(), secid, 0,
> +					entry->func, &pcr,
> +					&template_desc);
> +		if (action & IMA_MEASURE) {
> +			process_buffer_measurement(entry->public_key,
> +						   entry->public_key_len,
> +						   entry->key_description,
> +						   pcr,
> +						   template_desc);
> +		}
>  		list_del(&entry->list);
>  		ima_free_trusted_key_entry(entry);
>  	}


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys
  2019-10-23 13:22   ` Mimi Zohar
@ 2019-10-23 14:49     ` Lakshmi Ramasubramanian
  2019-10-23 17:03       ` Mimi Zohar
  0 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23 14:49 UTC (permalink / raw)
  To: Mimi Zohar, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On 10/23/19 6:22 AM, Mimi Zohar wrote:

Thanks for reviewing the changes Mimi.
I'll address your comments and post an updated patch set shortly.

>> Add a new ima hook to measure keys added to builtin_trusted_keys
>> keyring.
> 
> There is no IMA hook in this patch.
> 

>> +			else if (strcmp(args[0].from,
>> +					"BUILTIN_TRUSTED_KEYS") == 0)
>> +				entry->func = BUILTIN_TRUSTED_KEYS;
>>   			else
>>   				result = -EINVAL;
>>   			if (!result)
> 
> Any new options need to be displayed as well.

Not that I can think of. Please correct me if I am wrong.

Thanks,
  -lakshmi


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 3/6] KEYS: ima hook to measure builtin_trusted_keys
  2019-10-23 14:49     ` Lakshmi Ramasubramanian
@ 2019-10-23 17:03       ` Mimi Zohar
  0 siblings, 0 replies; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 17:03 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Wed, 2019-10-23 at 07:49 -0700, Lakshmi Ramasubramanian wrote:
> On 10/23/19 6:22 AM, Mimi Zohar wrote:
> 
> Thanks for reviewing the changes Mimi.
> I'll address your comments and post an updated patch set shortly.
> 
> >> Add a new ima hook to measure keys added to builtin_trusted_keys
> >> keyring.
> > 
> > There is no IMA hook in this patch.
> > 
> 
> >> +			else if (strcmp(args[0].from,
> >> +					"BUILTIN_TRUSTED_KEYS") == 0)
> >> +				entry->func = BUILTIN_TRUSTED_KEYS;
> >>   			else
> >>   				result = -EINVAL;
> >>   			if (!result)
> > 
> > Any new options need to be displayed as well.
> 
> Not that I can think of. Please correct me if I am wrong.

True, since you're hard coding the policy.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] KEYS: measure queued keys
  2019-10-23 13:23   ` Mimi Zohar
@ 2019-10-23 17:34     ` Lakshmi Ramasubramanian
  2019-10-23 17:52       ` Mimi Zohar
  0 siblings, 1 reply; 16+ messages in thread
From: Lakshmi Ramasubramanian @ 2019-10-23 17:34 UTC (permalink / raw)
  To: Mimi Zohar, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On 10/23/19 6:23 AM, Mimi Zohar wrote:

> The ordering of this patch set is awkward.  It should first introduce
> a generic method for measuring keys based on the keyring.  Then add
> the additional support needed for the specific builtin_trusted_keys
> keyring usecase.

Would the following ordering of the patch set be acceptable:

  => PATCH 0/5: Cover letter

  => PATCH 1/5: Define the enum "hook(BUILTIN_TRUSTED_KEYS)" in ima.h

  => PATCH 2/5: Define ima hook
                This will initially do nothing if ima is not yet
                initialized.
                Call process_buffer_measurement() if ima is initialized.

  => PATCH 3/5: key_create_or_update change and the call to ima hook

  => PATCH 4/5: Queue\De-Queue of key measurement requests.
                Enable queuing of key in the ima hook if ima is not
                initialized.

  => PATCH 5/5: ima policy to enable measurement of keys which will
                enable end-to-end working of this feature.

thanks,
  -lakshmi

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] KEYS: measure queued keys
  2019-10-23 17:34     ` Lakshmi Ramasubramanian
@ 2019-10-23 17:52       ` Mimi Zohar
  2019-10-23 18:49         ` Mimi Zohar
  0 siblings, 1 reply; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 17:52 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Wed, 2019-10-23 at 10:34 -0700, Lakshmi Ramasubramanian wrote:
> On 10/23/19 6:23 AM, Mimi Zohar wrote:
> 
> > The ordering of this patch set is awkward.  It should first introduce
> > a generic method for measuring keys based on the keyring.  Then add
> > the additional support needed for the specific builtin_trusted_keys
> > keyring usecase.
> 
> Would the following ordering of the patch set be acceptable:
> 
>   => PATCH 0/5: Cover letter
> 
>   => PATCH 1/5: Define the enum "hook(BUILTIN_TRUSTED_KEYS)" in ima.h
> 
>   => PATCH 2/5: Define ima hook
>                 This will initially do nothing if ima is not yet
>                 initialized.
>                 Call process_buffer_measurement() if ima is initialized.
> 
>   => PATCH 3/5: key_create_or_update change and the call to ima hook
> 
>   => PATCH 4/5: Queue\De-Queue of key measurement requests.
>                 Enable queuing of key in the ima hook if ima is not
>                 initialized.
> 
>   => PATCH 5/5: ima policy to enable measurement of keys which will
>                 enable end-to-end working of this feature.

The first patches need to introduce the generic concept of measuring
keys based on policy.  Only afterwards would you add any builtin
trusted keyring specific code.

Mimi


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 6/6] KEYS: measure keys when they are created or updated
  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
  0 siblings, 0 replies; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 18:09 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Tue, 2019-10-22 at 17:18 -0700, Lakshmi Ramasubramanian wrote:
> diff --git a/security/security.c b/security/security.c
> index 250ee2d76406..707a9e7fa94d 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -2303,6 +2303,16 @@ int security_key_getsecurity(struct key *key, char **_buffer)
>  	return call_int_hook(key_getsecurity, 0, key, _buffer);
>  }
>  
> +int security_key_create_or_update(struct key *keyring,
> +				  struct key *key,
> +				  const struct cred *cred,
> +				  unsigned long flags,
> +				  bool create)
> +{
> +	return ima_post_key_create_or_update(keyring, key, cred,
> +					     flags, create);
> +}
> +
>  #endif	/* CONFIG_KEYS */

Either the new hook is an LSM and IMA hook, or it is just an IMA hook.
 We don't define a security_ function, if it is just an IMA hook.

Mimi


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] KEYS: measure queued keys
  2019-10-23 17:52       ` Mimi Zohar
@ 2019-10-23 18:49         ` Mimi Zohar
  0 siblings, 0 replies; 16+ messages in thread
From: Mimi Zohar @ 2019-10-23 18:49 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, dhowells, casey, sashal, jamorris,
	linux-security-module, linux-integrity, linux-kernel, keyrings

On Wed, 2019-10-23 at 13:52 -0400, Mimi Zohar wrote:
> On Wed, 2019-10-23 at 10:34 -0700, Lakshmi Ramasubramanian wrote:
> > On 10/23/19 6:23 AM, Mimi Zohar wrote:
> > 
> > > The ordering of this patch set is awkward.  It should first introduce
> > > a generic method for measuring keys based on the keyring.  Then add
> > > the additional support needed for the specific builtin_trusted_keys
> > > keyring usecase.
> > 
> > Would the following ordering of the patch set be acceptable:
> > 
> >   => PATCH 0/5: Cover letter
> > 
> >   => PATCH 1/5: Define the enum "hook(BUILTIN_TRUSTED_KEYS)" in ima.h
> > 
> >   => PATCH 2/5: Define ima hook
> >                 This will initially do nothing if ima is not yet
> >                 initialized.
> >                 Call process_buffer_measurement() if ima is initialized.
> > 
> >   => PATCH 3/5: key_create_or_update change and the call to ima hook
> > 
> >   => PATCH 4/5: Queue\De-Queue of key measurement requests.
> >                 Enable queuing of key in the ima hook if ima is not
> >                 initialized.
> > 
> >   => PATCH 5/5: ima policy to enable measurement of keys which will
> >                 enable end-to-end working of this feature.
> 
> The first patches need to introduce the generic concept of measuring
> keys based on policy.  Only afterwards would you add any builtin
> trusted keyring specific code.

1. Extend the IMA policy language to support identifying keyrings
2. Define a new IMA hook which calls process_buffer_measurement()
3. Call the new IMA hook (eg. from post_key_create_or_update)
4. Define an early workqueue for saving keys loaded prior to IMA is
initialized.  (Remember we don't hard code policy in the kernel.)

I'll be pushing out linux-integrity shortly.  For the time being,
please base your patches on -rc3.

thanks,

Mimi


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-10-23 18:49 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH v1 4/6] KEYS: ima functions to queue and dequeue keys to measure Lakshmi Ramasubramanian
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

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).