* [PATCH v6 1/3] IMA: Define workqueue for early boot key measurements
2020-01-03 5:56 [PATCH v6 0/3] IMA: Deferred measurement of keys Lakshmi Ramasubramanian
@ 2020-01-03 5:56 ` Lakshmi Ramasubramanian
2020-01-03 14:15 ` Mimi Zohar
2020-01-03 5:56 ` [PATCH v6 2/3] IMA: Call workqueue functions to measure queued keys Lakshmi Ramasubramanian
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-01-03 5:56 UTC (permalink / raw)
To: zohar, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
Measuring keys requires a custom IMA policy to be loaded.
Keys created or updated before a custom IMA policy is loaded should
be queued and the keys should be processed after a custom policy
is loaded.
This patch defines workqueue for queuing keys when a custom IMA policy
has not yet been loaded.
A flag namely ima_process_keys is used to check if the key should be
queued or should be processed immediately.
Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Reported-by: kernel test robot <rong.a.chen@intel.com>
Reported-by: kbuild test robot <lkp@intel.com>
---
security/integrity/ima/ima.h | 15 +++
security/integrity/ima/ima_asymmetric_keys.c | 115 +++++++++++++++++++
2 files changed, 130 insertions(+)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index f06238e41a7c..97f8a4078483 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -205,6 +205,21 @@ extern const char *const func_tokens[];
struct modsig;
+#ifdef CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+/*
+ * To track keys that need to be measured.
+ */
+struct ima_key_entry {
+ struct list_head list;
+ void *payload;
+ size_t payload_len;
+ char *keyring_name;
+};
+void ima_process_queued_keys(void);
+#else
+static inline void ima_process_queued_keys(void) {}
+#endif /* CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE */
+
/* 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_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index fea2e7dd3b09..1d56f003f1a7 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -14,6 +14,121 @@
#include <keys/asymmetric-type.h>
#include "ima.h"
+/*
+ * Flag to indicate whether a key can be processed
+ * right away or should be queued for processing later.
+ */
+static bool ima_process_keys;
+
+/*
+ * To synchronize access to the list of keys that need to be measured
+ */
+static DEFINE_SPINLOCK(ima_keys_lock);
+static LIST_HEAD(ima_keys);
+
+static void ima_free_key_entry(struct ima_key_entry *entry)
+{
+ if (entry) {
+ kfree(entry->payload);
+ kfree(entry->keyring_name);
+ kfree(entry);
+ }
+}
+
+static struct ima_key_entry *ima_alloc_key_entry(
+ struct key *keyring,
+ const void *payload, size_t payload_len)
+{
+ int rc = 0;
+ struct ima_key_entry *entry;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (entry) {
+ entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
+ entry->keyring_name = kstrdup(keyring->description,
+ GFP_KERNEL);
+ entry->payload_len = payload_len;
+ }
+
+ if ((entry == NULL) || (entry->payload == NULL) ||
+ (entry->keyring_name == NULL)) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&entry->list);
+
+out:
+ if (rc) {
+ ima_free_key_entry(entry);
+ entry = NULL;
+ }
+
+ return entry;
+}
+
+static bool ima_queue_key(struct key *keyring, const void *payload,
+ size_t payload_len)
+{
+ bool queued = false;
+ struct ima_key_entry *entry;
+
+ entry = ima_alloc_key_entry(keyring, payload, payload_len);
+ if (!entry)
+ return false;
+
+ spin_lock(&ima_keys_lock);
+ if (!ima_process_keys) {
+ list_add_tail(&entry->list, &ima_keys);
+ queued = true;
+ }
+ spin_unlock(&ima_keys_lock);
+
+ if (!queued)
+ ima_free_key_entry(entry);
+
+ return queued;
+}
+
+/*
+ * ima_process_queued_keys() - process keys queued for measurement
+ *
+ * This function sets ima_process_keys to true and processes queued keys.
+ * From here on keys will be processed right away (not queued).
+ */
+void ima_process_queued_keys(void)
+{
+ struct ima_key_entry *entry, *tmp;
+ bool process = false;
+
+ if (ima_process_keys)
+ return;
+
+ /*
+ * Since ima_process_keys is set to true, any new key will be
+ * processed immediately and not be queued to ima_keys list.
+ * First one setting the ima_process_keys flag to true will
+ * process the queued keys.
+ */
+ spin_lock(&ima_keys_lock);
+ if (!ima_process_keys) {
+ ima_process_keys = true;
+ process = true;
+ }
+ spin_unlock(&ima_keys_lock);
+
+ if (!process)
+ return;
+
+ list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
+ process_buffer_measurement(entry->payload, entry->payload_len,
+ entry->keyring_name, KEY_CHECK, 0,
+ entry->keyring_name);
+ list_del(&entry->list);
+ ima_free_key_entry(entry);
+ }
+}
+
/**
* ima_post_key_create_or_update - measure asymmetric keys
* @keyring: keyring to which the key is linked to
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/3] IMA: Define workqueue for early boot key measurements
2020-01-03 5:56 ` [PATCH v6 1/3] IMA: Define workqueue for early boot key measurements Lakshmi Ramasubramanian
@ 2020-01-03 14:15 ` Mimi Zohar
0 siblings, 0 replies; 7+ messages in thread
From: Mimi Zohar @ 2020-01-03 14:15 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
Hi Lakshmi,
On Thu, 2020-01-02 at 21:56 -0800, Lakshmi Ramasubramanian wrote:
> Measuring keys requires a custom IMA policy to be loaded.
> Keys created or updated before a custom IMA policy is loaded should
> be queued and the keys should be processed after a custom policy
> is loaded.
>
> This patch defines workqueue for queuing keys when a custom IMA policy
> has not yet been loaded.
>
> A flag namely ima_process_keys is used to check if the key should be
> queued or should be processed immediately.
>
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> Reported-by: kernel test robot <rong.a.chen@intel.com>
> Reported-by: kbuild test robot <lkp@intel.com>
The changes based on "kernel test robot" reports are properly folded
into this patch, but unless the tag - "Acked-by", "Reported-by" - is
qualified, it refers to the entire patch. Let's limit it as:
Reported-by: kernel test robot <rong.a.chen@intel.com> # sleeping
function called from invalid context
Reported-by: kbuild test robot <lkp@intel.com> # sparse symbol
ima_queued_key() should be static
Mimi
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v6 2/3] IMA: Call workqueue functions to measure queued keys
2020-01-03 5:56 [PATCH v6 0/3] IMA: Deferred measurement of keys Lakshmi Ramasubramanian
2020-01-03 5:56 ` [PATCH v6 1/3] IMA: Define workqueue for early boot key measurements Lakshmi Ramasubramanian
@ 2020-01-03 5:56 ` Lakshmi Ramasubramanian
2020-01-03 5:56 ` [PATCH v6 3/3] IMA: Defined timer to free " Lakshmi Ramasubramanian
2020-01-03 15:08 ` [PATCH v6 0/3] IMA: Deferred measurement of keys Mimi Zohar
3 siblings, 0 replies; 7+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-01-03 5:56 UTC (permalink / raw)
To: zohar, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
Measuring keys requires a custom IMA policy to be loaded.
Keys should be queued for measurement if a custom IMA policy
is not yet loaded. Keys queued for measurement, if any, should be
processed when a custom IMA policy is loaded.
This patch updates the IMA hook function ima_post_key_create_or_update()
to queue the key if a custom IMA policy has not yet been loaded.
And, ima_update_policy() function, which is called when
a custom IMA policy is loaded, is updated to process queued keys.
Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
security/integrity/ima/ima_asymmetric_keys.c | 8 ++++++++
security/integrity/ima/ima_policy.c | 3 +++
2 files changed, 11 insertions(+)
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index 1d56f003f1a7..eb71cbf224c1 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -145,6 +145,8 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
const void *payload, size_t payload_len,
unsigned long flags, bool create)
{
+ bool queued = false;
+
/* Only asymmetric keys are handled by this hook. */
if (key->type != &key_type_asymmetric)
return;
@@ -152,6 +154,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
if (!payload || (payload_len == 0))
return;
+ if (!ima_process_keys)
+ queued = ima_queue_key(keyring, payload, payload_len);
+
+ if (queued)
+ return;
+
/*
* keyring->description points to the name of the keyring
* (such as ".builtin_trusted_keys", ".ima", etc.) to
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index a4dde9d575b2..04b9c6c555de 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -807,6 +807,9 @@ void ima_update_policy(void)
kfree(arch_policy_entry);
}
ima_update_policy_flag();
+
+ /* Custom IMA policy has been loaded */
+ ima_process_queued_keys();
}
/* Keep the enumeration in sync with the policy_tokens! */
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v6 3/3] IMA: Defined timer to free queued keys
2020-01-03 5:56 [PATCH v6 0/3] IMA: Deferred measurement of keys Lakshmi Ramasubramanian
2020-01-03 5:56 ` [PATCH v6 1/3] IMA: Define workqueue for early boot key measurements Lakshmi Ramasubramanian
2020-01-03 5:56 ` [PATCH v6 2/3] IMA: Call workqueue functions to measure queued keys Lakshmi Ramasubramanian
@ 2020-01-03 5:56 ` Lakshmi Ramasubramanian
2020-01-03 15:08 ` [PATCH v6 0/3] IMA: Deferred measurement of keys Mimi Zohar
3 siblings, 0 replies; 7+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-01-03 5:56 UTC (permalink / raw)
To: zohar, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
keys queued for measurement should be freed if a custom IMA policy
was not loaded. Otherwise, the keys will remain queued forever
consuming kernel memory.
This patch defines a timer to handle the above scenario. The timer
is setup to expire 5 minutes after IMA initialization is completed.
If a custom IMA policy is loaded before the timer expires, the timer
is removed and any queued keys are processed for measurement.
But if a custom policy was not loaded, on timer expiration
queued keys are just freed.
Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Reported-by: kernel test robot <rong.a.chen@intel.com>
---
security/integrity/ima/ima.h | 2 +
security/integrity/ima/ima_asymmetric_keys.c | 42 ++++++++++++++++++--
security/integrity/ima/ima_init.c | 8 +++-
3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 97f8a4078483..c483215a9ee5 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -216,8 +216,10 @@ struct ima_key_entry {
char *keyring_name;
};
void ima_process_queued_keys(void);
+void ima_init_key_queue(void);
#else
static inline void ima_process_queued_keys(void) {}
+static inline void ima_init_key_queue(void) {}
#endif /* CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE */
/* LIM API function definitions */
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index eb71cbf224c1..d1fa1706e03f 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -11,6 +11,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/timer.h>
#include <keys/asymmetric-type.h>
#include "ima.h"
@@ -26,6 +27,36 @@ static bool ima_process_keys;
static DEFINE_SPINLOCK(ima_keys_lock);
static LIST_HEAD(ima_keys);
+/*
+ * If custom IMA policy is not loaded then keys queued up
+ * for measurement should be freed. This timer is used
+ * for handling this scenario.
+ */
+static long ima_key_queue_timeout = 300000; /* 5 Minutes */
+static struct timer_list ima_key_queue_timer;
+static bool timer_expired;
+
+/*
+ * This timer callback function frees keys that may still be
+ * queued up in case custom IMA policy was not loaded.
+ */
+static void ima_timer_handler(struct timer_list *timer)
+{
+ timer_expired = true;
+ ima_process_queued_keys();
+}
+
+/*
+ * This function sets up a timer to free queued keys in case
+ * custom IMA policy was never loaded.
+ */
+void ima_init_key_queue(void)
+{
+ timer_setup(&ima_key_queue_timer, ima_timer_handler, 0);
+ mod_timer(&ima_key_queue_timer,
+ jiffies + msecs_to_jiffies(ima_key_queue_timeout));
+}
+
static void ima_free_key_entry(struct ima_key_entry *entry)
{
if (entry) {
@@ -120,10 +151,15 @@ void ima_process_queued_keys(void)
if (!process)
return;
+ del_timer(&ima_key_queue_timer);
+
list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
- process_buffer_measurement(entry->payload, entry->payload_len,
- entry->keyring_name, KEY_CHECK, 0,
- entry->keyring_name);
+ if (!timer_expired)
+ process_buffer_measurement(entry->payload,
+ entry->payload_len,
+ entry->keyring_name,
+ KEY_CHECK, 0,
+ entry->keyring_name);
list_del(&entry->list);
ima_free_key_entry(entry);
}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 5d55ade5f3b9..195cb4079b2b 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -131,5 +131,11 @@ int __init ima_init(void)
ima_init_policy();
- return ima_fs_init();
+ rc = ima_fs_init();
+ if (rc != 0)
+ return rc;
+
+ ima_init_key_queue();
+
+ return rc;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6 0/3] IMA: Deferred measurement of keys
2020-01-03 5:56 [PATCH v6 0/3] IMA: Deferred measurement of keys Lakshmi Ramasubramanian
` (2 preceding siblings ...)
2020-01-03 5:56 ` [PATCH v6 3/3] IMA: Defined timer to free " Lakshmi Ramasubramanian
@ 2020-01-03 15:08 ` Mimi Zohar
2020-01-03 15:47 ` Mimi Zohar
3 siblings, 1 reply; 7+ messages in thread
From: Mimi Zohar @ 2020-01-03 15:08 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
Hi Lakshmi,
Instead of loosing the cover letter, Jonathan Corbet suggested
including it as the merge comment. I'd like to do that with this
cover letter.
On Thu, 2020-01-02 at 21:56 -0800, Lakshmi Ramasubramanian wrote:
> This patchset extends the previous version[1] by adding support for
> deferred processing of keys.
>
> With the patchset referenced above, the IMA subsystem supports
> measuring asymmetric keys when the key is created or updated.
The first sentence and the clause of the next sentence are
unnecessary. I would begin the cover letter with "The IMA subsystem
supports" and add the reference afterwards.
> But keys created or updated before a custom IMA policy is loaded
> are currently not measured. This includes keys added to, for instance,
> .builtin_trusted_keys which happens early in the boot process.
Let's not limit the example to just the .builtin_trusted_keys keyring.
Please update it as:
This includes keys added, for instance, to either the .ima or
.builtin_trusted_keys keyrings, which happens early in the boot
process.
>
> This change adds support for queuing keys created or updated before
> a custom IMA policy is loaded. The queued keys are processed when
> a custom policy is loaded. Keys created or updated after a custom policy
> is loaded are measured immediately (not queued).
>
> If the kernel is built with both CONFIG_IMA and
> CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE enabled then the IMA policy
> must be applied as a custom policy for the keys to be measured.
> If a custom IMA policy is not provided within 5 minutes after
> IMA is initialized, any queued keys will be freed.
As the merge message, this is too much information. I would extend
the previous paragraph and drop this one, like:
"... (not queued). In the case when a custom policy is not loaded
within 5 minutes of IMA initialization, the queued keys are freed."
> This is by design.
It's unclear what "is by design" refers to. Perhaps expand this
sentence like: "Measuring the early boot keys, by design, requires
loading a custom policy.
>
> [1] https://lore.kernel.org/linux-integrity/20191211164707.4698-1-nramas@linux.microsoft.com/
thanks,
Mimi
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 0/3] IMA: Deferred measurement of keys
2020-01-03 15:08 ` [PATCH v6 0/3] IMA: Deferred measurement of keys Mimi Zohar
@ 2020-01-03 15:47 ` Mimi Zohar
0 siblings, 0 replies; 7+ messages in thread
From: Mimi Zohar @ 2020-01-03 15:47 UTC (permalink / raw)
To: Lakshmi Ramasubramanian, James.Bottomley, linux-integrity
Cc: eric.snowberg, dhowells, mathew.j.martineau, matthewgarrett,
sashal, jamorris, linux-kernel, keyrings
On Fri, 2020-01-03 at 10:08 -0500, Mimi Zohar wrote:
> > This change adds support for queuing keys created or updated before
> > a custom IMA policy is loaded. The queued keys are processed when
> > a custom policy is loaded. Keys created or updated after a custom policy
> > is loaded are measured immediately (not queued).
> >
> > If the kernel is built with both CONFIG_IMA and
> > CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE enabled then the IMA policy
> > must be applied as a custom policy for the keys to be measured.
> > If a custom IMA policy is not provided within 5 minutes after
> > IMA is initialized, any queued keys will be freed.
>
> As the merge message, this is too much information. I would extend
> the previous paragraph and drop this one, like:
> "... (not queued). In the case when a custom policy is not loaded
> within 5 minutes of IMA initialization, the queued keys are freed."
>
> > This is by design.
>
> It's unclear what "is by design" refers to. Perhaps expand this
> sentence like: "Measuring the early boot keys, by design, requires
> loading a custom policy.
Instead of including this comment as the last sentence of the cover
letter, it would make a good opening sentence for the second
paragraph.
Mimi
^ permalink raw reply [flat|nested] 7+ messages in thread