Linux-Integrity Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] IMA: pre-allocate keyrings string
@ 2020-01-16  3:15 Lakshmi Ramasubramanian
  2020-01-16 12:56 ` Mimi Zohar
  0 siblings, 1 reply; 2+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-01-16  3:15 UTC (permalink / raw)
  To: zohar, James.Bottomley, arnd, linux-integrity
  Cc: dhowells, sashal, linux-kernel, keyrings, linux-crypto

ima_match_keyring() is called while holding rcu read lock.
Since this function executes in atmomic context, it should
not call any function that can sleep (such as kstrdup()).

This patch pre-allocates a buffer to hold the keyrings
string read from the IMA policy and uses that to check
the given keyring in ima_match_keyring().

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Fixes: e9085e0ad38a ("IMA: Add support to limit measuring keys")
---
 security/integrity/ima/ima_policy.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 9963863d6c92..0bb4376ddba7 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -207,6 +207,7 @@ static LIST_HEAD(ima_default_rules);
 static LIST_HEAD(ima_policy_rules);
 static LIST_HEAD(ima_temp_rules);
 static struct list_head *ima_rules;
+static char *ima_keyrings;
 
 static int ima_policy __initdata;
 
@@ -369,7 +370,7 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
 static bool ima_match_keyring(struct ima_rule_entry *rule,
 			      const char *keyring, const struct cred *cred)
 {
-	char *keyrings, *next_keyring, *keyrings_ptr;
+	char *next_keyring, *keyrings_ptr;
 	bool matched = false;
 
 	if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
@@ -381,15 +382,13 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
 	if (!keyring)
 		return false;
 
-	keyrings = kstrdup(rule->keyrings, GFP_KERNEL);
-	if (!keyrings)
-		return false;
+	strcpy(ima_keyrings, rule->keyrings);
 
 	/*
 	 * "keyrings=" is specified in the policy in the format below:
 	 * keyrings=.builtin_trusted_keys|.ima|.evm
 	 */
-	keyrings_ptr = keyrings;
+	keyrings_ptr = ima_keyrings;
 	while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) {
 		if (!strcmp(next_keyring, keyring)) {
 			matched = true;
@@ -397,8 +396,6 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
 		}
 	}
 
-	kfree(keyrings);
-
 	return matched;
 }
 
@@ -1120,8 +1117,17 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 				result = -EINVAL;
 				break;
 			}
+
+			ima_keyrings = kstrdup(args[0].from, GFP_KERNEL);
+			if (!ima_keyrings) {
+				result = -ENOMEM;
+				break;
+			}
+
 			entry->keyrings = kstrdup(args[0].from, GFP_KERNEL);
 			if (!entry->keyrings) {
+				kfree(ima_keyrings);
+				ima_keyrings = NULL;
 				result = -ENOMEM;
 				break;
 			}
-- 
2.17.1


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

* Re: [PATCH] IMA: pre-allocate keyrings string
  2020-01-16  3:15 [PATCH] IMA: pre-allocate keyrings string Lakshmi Ramasubramanian
@ 2020-01-16 12:56 ` Mimi Zohar
  0 siblings, 0 replies; 2+ messages in thread
From: Mimi Zohar @ 2020-01-16 12:56 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, linux-integrity; +Cc: sashal, linux-kernel, keyrings

Hi Laskhmi,

On Wed, 2020-01-15 at 19:15 -0800, Lakshmi Ramasubramanian wrote:
> ima_match_keyring() is called while holding rcu read lock.
> Since this function executes in atmomic context, it should
> not call any function that can sleep (such as kstrdup()).

Good catch!

> This patch pre-allocates a buffer to hold the keyrings
> string read from the IMA policy and uses that to check
> the given keyring in ima_match_keyring().

(Reminder: this patch description line length is a bit short.
 According to  Documentation/process/submitting-patches.rst, the patch
description line length should be line wrapped at 75 columns.)

> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> Fixes: e9085e0ad38a ("IMA: Add support to limit measuring keys")
> ---

 
> @@ -1120,8 +1117,17 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				result = -EINVAL;
>  				break;
>  			}
> +
> +			ima_keyrings = kstrdup(args[0].from, GFP_KERNEL);
> +			if (!ima_keyrings) {
> +				result = -ENOMEM;
> +				break;
> +			}


This would work for a single "key" measurement rule, but not for
multiple rules, where the last "keyrings" string is shorter than the
previous ones.  For example, in addition to the builtin trusted
keyrings, another rule could measure a keyring owned by a user.

measure func=KEY_CHECK template=ima-buf keyrings=.ima|.builtin_trusted_keys
measure func=KEY_CHECK uid=1000 template=ima-buf keyrings=_foo

Mimi

>  			entry->keyrings = kstrdup(args[0].from, GFP_KERNEL);
>  			if (!entry->keyrings) {
> +				kfree(ima_keyrings);
> +				ima_keyrings = NULL;
>  				result = -ENOMEM;
>  				break;
>  			}


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

end of thread, back to index

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-16  3:15 [PATCH] IMA: pre-allocate keyrings string Lakshmi Ramasubramanian
2020-01-16 12:56 ` Mimi Zohar

Linux-Integrity Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-integrity/0 linux-integrity/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-integrity linux-integrity/ https://lore.kernel.org/linux-integrity \
		linux-integrity@vger.kernel.org
	public-inbox-index linux-integrity

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-integrity


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git