[RFC PATCH 18/20] IMA: Use the system blacklist keyring [ver #2]

From: David Howells
Date: Tue Jan 19 2016 - 06:33:54 EST


Use the system blacklist keyring instead of having an IMA-specific keyring.
This requires that the system blacklist be made writable. To control what
goes into it, additions to the system blacklist is restricted to
certificates that can be validated by CA certificates in the system
keyring.

Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
---

certs/blacklist.c | 26 +++++++++++++++++++++++---
include/keys/system_keyring.h | 14 +++++---------
security/integrity/digsig_asymmetric.c | 13 +++----------
security/integrity/ima/ima_mok.c | 15 ++-------------
4 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/certs/blacklist.c b/certs/blacklist.c
index 7f769479c17b..5648504768b2 100644
--- a/certs/blacklist.c
+++ b/certs/blacklist.c
@@ -18,6 +18,7 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <keys/system_keyring.h>
+#include <keys/asymmetric-type.h>
#include "blacklist.h"

static struct key *blacklist_keyring;
@@ -80,7 +81,8 @@ int mark_hash_blacklisted(const char *hash)
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW),
KEY_ALLOC_NOT_IN_QUOTA |
- KEY_ALLOC_BUILT_IN);
+ KEY_ALLOC_BUILT_IN |
+ KEY_ALLOC_BYPASS_RESTRICTION);
if (IS_ERR(key)) {
pr_err("Problem blacklisting hash (%ld)\n",
PTR_ERR(key));
@@ -129,6 +131,24 @@ int is_bin_hash_blacklisted(const u8 *hash, size_t hash_len)
}
EXPORT_SYMBOL_GPL(is_bin_hash_blacklisted);

+/**
+ * is_key_blacklisted - Determine if a key is blacklisted
+ * @name: The name or ID of the key to check.
+ */
+int is_key_blacklisted(const char *name)
+{
+ key_ref_t kref;
+
+ kref = keyring_search(make_key_ref(blacklist_keyring, true),
+ &key_type_asymmetric, name);
+ if (!IS_ERR(kref)) {
+ key_ref_put(kref);
+ return -EKEYREJECTED;
+ }
+
+ return 0;
+}
+
/*
* Intialise the blacklist
*/
@@ -145,10 +165,10 @@ static int __init blacklist_init(void)
current_cred(),
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ |
- KEY_USR_SEARCH,
+ KEY_USR_SEARCH | KEY_USR_WRITE,
KEY_ALLOC_NOT_IN_QUOTA |
KEY_FLAG_KEEP,
- NULL, NULL);
+ restrict_link_by_system_trusted, NULL);
if (IS_ERR(blacklist_keyring))
panic("Can't allocate system blacklist keyring\n");

diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 615244b1e276..15107dcc2ec4 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -25,6 +25,7 @@ extern int restrict_link_by_system_trusted(struct key *keyring,
extern int mark_hash_blacklisted(const char *hash);
extern int is_hash_blacklisted(const char *hash);
extern int is_bin_hash_blacklisted(const u8 *hash, size_t hash_len);
+extern int is_key_blacklisted(const char *name);
#else
static inline int is_hash_blacklisted(const char *hash)
{
@@ -34,29 +35,24 @@ static inline int is_bin_hash_blacklisted(const u8 *hash, size_t hash_len)
{
return 0;
}
+static inline int is_key_blacklisted(const char *name)
+{
+ return 0;
+}
#endif

#ifdef CONFIG_IMA_MOK_KEYRING
extern struct key *ima_mok_keyring;
-extern struct key *ima_blacklist_keyring;

static inline struct key *get_ima_mok_keyring(void)
{
return ima_mok_keyring;
}
-static inline struct key *get_ima_blacklist_keyring(void)
-{
- return ima_blacklist_keyring;
-}
#else
static inline struct key *get_ima_mok_keyring(void)
{
return NULL;
}
-static inline struct key *get_ima_blacklist_keyring(void)
-{
- return NULL;
-}
#endif /* CONFIG_IMA_MOK_KEYRING */


diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index be1af41b5c2a..bd854dff36e0 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -34,16 +34,9 @@ static struct key *ds_request_asymmetric_key(struct key *keyring,

pr_debug("key search: \"%s\"\n", name);

- key = get_ima_blacklist_keyring();
- if (key) {
- key_ref_t kref;
-
- kref = keyring_search(make_key_ref(key, 1),
- &key_type_asymmetric, name);
- if (!IS_ERR(kref)) {
- pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
- return ERR_PTR(-EKEYREJECTED);
- }
+ if (is_key_blacklisted(name) == -EKEYREJECTED) {
+ pr_err("Key '%s' is blacklisted\n", name);
+ return ERR_PTR(-EKEYREJECTED);
}

if (keyring) {
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c
index be0da013622c..6b34770a6c9f 100644
--- a/security/integrity/ima/ima_mok.c
+++ b/security/integrity/ima/ima_mok.c
@@ -21,7 +21,6 @@


struct key *ima_mok_keyring;
-struct key *ima_blacklist_keyring;

/*
* Allocate the IMA MOK and blacklist keyrings
@@ -38,18 +37,8 @@ __init int ima_mok_init(void)
KEY_ALLOC_NOT_IN_QUOTA,
restrict_link_by_system_trusted, NULL);

- ima_blacklist_keyring = keyring_alloc(".ima_blacklist",
- KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ |
- KEY_USR_WRITE | KEY_USR_SEARCH,
- KEY_ALLOC_NOT_IN_QUOTA,
- restrict_link_by_system_trusted, NULL);
-
- if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring))
- panic("Can't allocate IMA MOK or blacklist keyrings.");
-
- set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags);
+ if (IS_ERR(ima_mok_keyring))
+ panic("Can't allocate IMA MOK keyring.");
return 0;
}
device_initcall(ima_mok_init);