summaryrefslogtreecommitdiffstats
path: root/security/integrity/digsig.c
diff options
context:
space:
mode:
authorJames Morris <james.morris@microsoft.com>2018-12-17 11:26:46 -0800
committerJames Morris <james.morris@microsoft.com>2018-12-17 11:26:46 -0800
commit5580b4a1a8ca85c53bd5b94c5d302e47dca3e5cb (patch)
tree69597129504be73e8826be9984e05d073a5c47b5 /security/integrity/digsig.c
parent8bd8ea195f6d135a8d85201116314eb5237ad7e7 (diff)
parenteed9de3b4f47114f440980203ca27c5fab70f529 (diff)
downloadlinux-5580b4a1a8ca85c53bd5b94c5d302e47dca3e5cb.tar.gz
linux-5580b4a1a8ca85c53bd5b94c5d302e47dca3e5cb.tar.bz2
linux-5580b4a1a8ca85c53bd5b94c5d302e47dca3e5cb.zip
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next-integrity
From Mimi: In Linux 4.19, a new LSM hook named security_kernel_load_data was upstreamed, allowing LSMs and IMA to prevent the kexec_load syscall.  Different signature verification methods exist for verifying the kexec'ed kernel image.  This pull request adds additional support in IMA to prevent loading unsigned kernel images via the kexec_load syscall, independently of the IMA policy rules, based on the runtime "secure boot" flag.  An initial IMA kselftest is included. In addition, this pull request defines a new, separate keyring named ".platform" for storing the preboot/firmware keys needed for verifying the kexec'ed kernel image's signature and includes the associated IMA kexec usage of the ".platform" keyring. (David Howell's and Josh Boyer's patches for reading the preboot/firmware keys, which were previously posted for a different use case scenario, are included here.)
Diffstat (limited to 'security/integrity/digsig.c')
-rw-r--r--security/integrity/digsig.c110
1 files changed, 73 insertions, 37 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..71c3200521d6 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
".ima",
#endif
"_module",
+ ".platform",
};
#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,38 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return -EOPNOTSUPP;
}
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+ struct key_restriction *restriction)
{
const struct cred *cred = current_cred();
- struct key_restriction *restriction;
int err = 0;
+ keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+ KGIDT_INIT(0), cred, perm,
+ KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
+ if (IS_ERR(keyring[id])) {
+ err = PTR_ERR(keyring[id]);
+ pr_info("Can't allocate %s keyring (%d)\n",
+ keyring_name[id], err);
+ keyring[id] = NULL;
+ }
+
+ return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
+ struct key_restriction *restriction;
+ key_perm_t perm;
+
+ perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+ | KEY_USR_READ | KEY_USR_SEARCH;
+
+ if (id == INTEGRITY_KEYRING_PLATFORM) {
+ restriction = NULL;
+ goto out;
+ }
+
if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING))
return 0;
@@ -87,32 +114,43 @@ int __init integrity_init_keyring(const unsigned int id)
return -ENOMEM;
restriction->check = restrict_link_to_ima;
+ perm |= KEY_USR_WRITE;
- keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
- KGIDT_INIT(0), cred,
- ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ |
- KEY_USR_WRITE | KEY_USR_SEARCH),
- KEY_ALLOC_NOT_IN_QUOTA,
- restriction, NULL);
- if (IS_ERR(keyring[id])) {
- err = PTR_ERR(keyring[id]);
- pr_info("Can't allocate %s keyring (%d)\n",
- keyring_name[id], err);
- keyring[id] = NULL;
+out:
+ return __integrity_init_keyring(id, perm, restriction);
+}
+
+int __init integrity_add_key(const unsigned int id, const void *data,
+ off_t size, key_perm_t perm)
+{
+ key_ref_t key;
+ int rc = 0;
+
+ if (!keyring[id])
+ return -EINVAL;
+
+ key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
+ NULL, data, size, perm,
+ KEY_ALLOC_NOT_IN_QUOTA);
+ if (IS_ERR(key)) {
+ rc = PTR_ERR(key);
+ pr_err("Problem loading X.509 certificate %d\n", rc);
+ } else {
+ pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+ key_ref_put(key);
}
- return err;
+
+ return rc;
+
}
int __init integrity_load_x509(const unsigned int id, const char *path)
{
- key_ref_t key;
void *data;
loff_t size;
int rc;
-
- if (!keyring[id])
- return -EINVAL;
+ key_perm_t perm;
rc = kernel_read_file_from_path(path, &data, &size, 0,
READING_X509_CERTIFICATE);
@@ -121,23 +159,21 @@ int __init integrity_load_x509(const unsigned int id, const char *path)
return rc;
}
- key = key_create_or_update(make_key_ref(keyring[id], 1),
- "asymmetric",
- NULL,
- data,
- size,
- ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ),
- KEY_ALLOC_NOT_IN_QUOTA);
- if (IS_ERR(key)) {
- rc = PTR_ERR(key);
- pr_err("Problem loading X.509 certificate (%d): %s\n",
- rc, path);
- } else {
- pr_notice("Loaded X.509 cert '%s': %s\n",
- key_ref_to_ptr(key)->description, path);
- key_ref_put(key);
- }
+ perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
+
+ pr_info("Loading X.509 certificate: %s\n", path);
+ rc = integrity_add_key(id, (const void *)data, size, perm);
+
vfree(data);
- return 0;
+ return rc;
+}
+
+int __init integrity_load_cert(const unsigned int id, const char *source,
+ const void *data, size_t len, key_perm_t perm)
+{
+ if (!data)
+ return -EINVAL;
+
+ pr_info("Loading X.509 certificate: %s\n", source);
+ return integrity_add_key(id, data, len, perm);
}