summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 12:43:14 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 12:43:14 -0500
commitf218a29c25ad8abdb961435d6b8139f462061364 (patch)
treec5ef7e5b8730be6f5a5c1c16517c3b2dc2fa6b70 /security
parent8e143b90e4d45cca3dc53760d3cfab988bc74571 (diff)
parentc7f7e58fcbf33589f11bfde0506e076a00627e59 (diff)
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull integrity updates from James Morris: "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 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)" * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: integrity: Remove references to module keyring ima: Use inode_is_open_for_write ima: Support platform keyring for kernel appraisal efi: Allow the "db" UEFI variable to be suppressed efi: Import certificates from UEFI Secure Boot efi: Add an EFI signature blob parser efi: Add EFI signature data types integrity: Load certs to the platform keyring integrity: Define a trusted platform keyring selftests/ima: kexec_load syscall test ima: don't measure/appraise files on efivarfs x86/ima: retry detecting secure boot mode docs: Extend trusted keys documentation for TPM 2.0 x86/ima: define arch_get_ima_policy() for x86 ima: add support for arch specific policies ima: refactor ima_init_policy() ima: prevent kexec_load syscall based on runtime secureboot flag x86/ima: define arch_ima_get_secureboot integrity: support new struct public_key_signature encoding field
Diffstat (limited to 'security')
-rw-r--r--security/integrity/Kconfig11
-rw-r--r--security/integrity/Makefile5
-rw-r--r--security/integrity/digsig.c111
-rw-r--r--security/integrity/ima/Kconfig10
-rw-r--r--security/integrity/ima/ima_appraise.c14
-rw-r--r--security/integrity/ima/ima_main.c21
-rw-r--r--security/integrity/ima/ima_policy.c171
-rw-r--r--security/integrity/integrity.h22
-rw-r--r--security/integrity/platform_certs/efi_parser.c108
-rw-r--r--security/integrity/platform_certs/load_uefi.c194
-rw-r--r--security/integrity/platform_certs/platform_keyring.c58
11 files changed, 633 insertions, 92 deletions
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 877af1f2d904..2ea4ec9991d5 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
51 .evm keyrings be signed by a key on the system trusted 51 .evm keyrings be signed by a key on the system trusted
52 keyring. 52 keyring.
53 53
54config INTEGRITY_PLATFORM_KEYRING
55 bool "Provide keyring for platform/firmware trusted keys"
56 depends on INTEGRITY_ASYMMETRIC_KEYS
57 depends on SYSTEM_BLACKLIST_KEYRING
58 depends on EFI
59 help
60 Provide a separate, distinct keyring for platform trusted keys, which
61 the kernel automatically populates during initialization from values
62 provided by the platform for verifying the kexec'ed kerned image
63 and, possibly, the initramfs signature.
64
54config INTEGRITY_AUDIT 65config INTEGRITY_AUDIT
55 bool "Enables integrity auditing support " 66 bool "Enables integrity auditing support "
56 depends on AUDIT 67 depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,11 @@ integrity-y := iint.o
9integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o 9integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
10integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o 10integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
11integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o 11integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
12integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += platform_certs/platform_keyring.o \
13 platform_certs/efi_parser.o \
14 platform_certs/load_uefi.o
15obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
16$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
12 17
13subdir-$(CONFIG_IMA) += ima 18subdir-$(CONFIG_IMA) += ima
14obj-$(CONFIG_IMA) += ima/ 19obj-$(CONFIG_IMA) += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..f45d6edecf99 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -34,7 +34,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
34 ".evm", 34 ".evm",
35 ".ima", 35 ".ima",
36#endif 36#endif
37 "_module", 37 ".platform",
38}; 38};
39 39
40#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY 40#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +73,38 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
73 return -EOPNOTSUPP; 73 return -EOPNOTSUPP;
74} 74}
75 75
76int __init integrity_init_keyring(const unsigned int id) 76static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
77 struct key_restriction *restriction)
77{ 78{
78 const struct cred *cred = current_cred(); 79 const struct cred *cred = current_cred();
79 struct key_restriction *restriction;
80 int err = 0; 80 int err = 0;
81 81
82 keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
83 KGIDT_INIT(0), cred, perm,
84 KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
85 if (IS_ERR(keyring[id])) {
86 err = PTR_ERR(keyring[id]);
87 pr_info("Can't allocate %s keyring (%d)\n",
88 keyring_name[id], err);
89 keyring[id] = NULL;
90 }
91
92 return err;
93}
94
95int __init integrity_init_keyring(const unsigned int id)
96{
97 struct key_restriction *restriction;
98 key_perm_t perm;
99
100 perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
101 | KEY_USR_READ | KEY_USR_SEARCH;
102
103 if (id == INTEGRITY_KEYRING_PLATFORM) {
104 restriction = NULL;
105 goto out;
106 }
107
82 if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING)) 108 if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING))
83 return 0; 109 return 0;
84 110
@@ -87,32 +113,43 @@ int __init integrity_init_keyring(const unsigned int id)
87 return -ENOMEM; 113 return -ENOMEM;
88 114
89 restriction->check = restrict_link_to_ima; 115 restriction->check = restrict_link_to_ima;
116 perm |= KEY_USR_WRITE;
90 117
91 keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), 118out:
92 KGIDT_INIT(0), cred, 119 return __integrity_init_keyring(id, perm, restriction);
93 ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 120}
94 KEY_USR_VIEW | KEY_USR_READ | 121
95 KEY_USR_WRITE | KEY_USR_SEARCH), 122int __init integrity_add_key(const unsigned int id, const void *data,
96 KEY_ALLOC_NOT_IN_QUOTA, 123 off_t size, key_perm_t perm)
97 restriction, NULL); 124{
98 if (IS_ERR(keyring[id])) { 125 key_ref_t key;
99 err = PTR_ERR(keyring[id]); 126 int rc = 0;
100 pr_info("Can't allocate %s keyring (%d)\n", 127
101 keyring_name[id], err); 128 if (!keyring[id])
102 keyring[id] = NULL; 129 return -EINVAL;
130
131 key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
132 NULL, data, size, perm,
133 KEY_ALLOC_NOT_IN_QUOTA);
134 if (IS_ERR(key)) {
135 rc = PTR_ERR(key);
136 pr_err("Problem loading X.509 certificate %d\n", rc);
137 } else {
138 pr_notice("Loaded X.509 cert '%s'\n",
139 key_ref_to_ptr(key)->description);
140 key_ref_put(key);
103 } 141 }
104 return err; 142
143 return rc;
144
105} 145}
106 146
107int __init integrity_load_x509(const unsigned int id, const char *path) 147int __init integrity_load_x509(const unsigned int id, const char *path)
108{ 148{
109 key_ref_t key;
110 void *data; 149 void *data;
111 loff_t size; 150 loff_t size;
112 int rc; 151 int rc;
113 152 key_perm_t perm;
114 if (!keyring[id])
115 return -EINVAL;
116 153
117 rc = kernel_read_file_from_path(path, &data, &size, 0, 154 rc = kernel_read_file_from_path(path, &data, &size, 0,
118 READING_X509_CERTIFICATE); 155 READING_X509_CERTIFICATE);
@@ -121,23 +158,21 @@ int __init integrity_load_x509(const unsigned int id, const char *path)
121 return rc; 158 return rc;
122 } 159 }
123 160
124 key = key_create_or_update(make_key_ref(keyring[id], 1), 161 perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
125 "asymmetric", 162
126 NULL, 163 pr_info("Loading X.509 certificate: %s\n", path);
127 data, 164 rc = integrity_add_key(id, (const void *)data, size, perm);
128 size, 165
129 ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
130 KEY_USR_VIEW | KEY_USR_READ),
131 KEY_ALLOC_NOT_IN_QUOTA);
132 if (IS_ERR(key)) {
133 rc = PTR_ERR(key);
134 pr_err("Problem loading X.509 certificate (%d): %s\n",
135 rc, path);
136 } else {
137 pr_notice("Loaded X.509 cert '%s': %s\n",
138 key_ref_to_ptr(key)->description, path);
139 key_ref_put(key);
140 }
141 vfree(data); 166 vfree(data);
142 return 0; 167 return rc;
168}
169
170int __init integrity_load_cert(const unsigned int id, const char *source,
171 const void *data, size_t len, key_perm_t perm)
172{
173 if (!data)
174 return -EINVAL;
175
176 pr_info("Loading X.509 certificate: %s\n", source);
177 return integrity_add_key(id, data, len, perm);
143} 178}
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 13b446328dda..a18f8c6d13b5 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -157,6 +157,14 @@ config IMA_APPRAISE
157 <http://linux-ima.sourceforge.net> 157 <http://linux-ima.sourceforge.net>
158 If unsure, say N. 158 If unsure, say N.
159 159
160config IMA_ARCH_POLICY
161 bool "Enable loading an IMA architecture specific policy"
162 depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
163 default n
164 help
165 This option enables loading an IMA architecture specific policy
166 based on run time secure boot flags.
167
160config IMA_APPRAISE_BUILD_POLICY 168config IMA_APPRAISE_BUILD_POLICY
161 bool "IMA build time configured policy rules" 169 bool "IMA build time configured policy rules"
162 depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS 170 depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
@@ -217,7 +225,7 @@ config IMA_APPRAISE_REQUIRE_POLICY_SIGS
217 225
218config IMA_APPRAISE_BOOTPARAM 226config IMA_APPRAISE_BOOTPARAM
219 bool "ima_appraise boot parameter" 227 bool "ima_appraise boot parameter"
220 depends on IMA_APPRAISE 228 depends on IMA_APPRAISE && !IMA_ARCH_POLICY
221 default y 229 default y
222 help 230 help
223 This option enables the different "ima_appraise=" modes 231 This option enables the different "ima_appraise=" modes
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 2e11e750a067..a2baa85ea2f5 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -289,12 +289,22 @@ int ima_appraise_measurement(enum ima_hooks func,
289 case EVM_IMA_XATTR_DIGSIG: 289 case EVM_IMA_XATTR_DIGSIG:
290 set_bit(IMA_DIGSIG, &iint->atomic_flags); 290 set_bit(IMA_DIGSIG, &iint->atomic_flags);
291 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 291 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
292 (const char *)xattr_value, rc, 292 (const char *)xattr_value,
293 xattr_len,
293 iint->ima_hash->digest, 294 iint->ima_hash->digest,
294 iint->ima_hash->length); 295 iint->ima_hash->length);
295 if (rc == -EOPNOTSUPP) { 296 if (rc == -EOPNOTSUPP) {
296 status = INTEGRITY_UNKNOWN; 297 status = INTEGRITY_UNKNOWN;
297 } else if (rc) { 298 break;
299 }
300 if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
301 func == KEXEC_KERNEL_CHECK)
302 rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
303 (const char *)xattr_value,
304 xattr_len,
305 iint->ima_hash->digest,
306 iint->ima_hash->length);
307 if (rc) {
298 cause = "invalid-signature"; 308 cause = "invalid-signature";
299 status = INTEGRITY_FAIL; 309 status = INTEGRITY_FAIL;
300 } else { 310 } else {
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 616a88f95b92..4ffac4f5c647 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -105,7 +105,7 @@ static void ima_rdwr_violation_check(struct file *file,
105 } else { 105 } else {
106 if (must_measure) 106 if (must_measure)
107 set_bit(IMA_MUST_MEASURE, &iint->atomic_flags); 107 set_bit(IMA_MUST_MEASURE, &iint->atomic_flags);
108 if ((atomic_read(&inode->i_writecount) > 0) && must_measure) 108 if (inode_is_open_for_write(inode) && must_measure)
109 send_writers = true; 109 send_writers = true;
110 } 110 }
111 111
@@ -507,20 +507,26 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
507 */ 507 */
508int ima_load_data(enum kernel_load_data_id id) 508int ima_load_data(enum kernel_load_data_id id)
509{ 509{
510 bool sig_enforce; 510 bool ima_enforce, sig_enforce;
511 511
512 if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE) 512 ima_enforce =
513 return 0; 513 (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
514 514
515 switch (id) { 515 switch (id) {
516 case LOADING_KEXEC_IMAGE: 516 case LOADING_KEXEC_IMAGE:
517 if (ima_appraise & IMA_APPRAISE_KEXEC) { 517 if (IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
518 && arch_ima_get_secureboot()) {
519 pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
520 return -EACCES;
521 }
522
523 if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) {
518 pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); 524 pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
519 return -EACCES; /* INTEGRITY_UNKNOWN */ 525 return -EACCES; /* INTEGRITY_UNKNOWN */
520 } 526 }
521 break; 527 break;
522 case LOADING_FIRMWARE: 528 case LOADING_FIRMWARE:
523 if (ima_appraise & IMA_APPRAISE_FIRMWARE) { 529 if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
524 pr_err("Prevent firmware sysfs fallback loading.\n"); 530 pr_err("Prevent firmware sysfs fallback loading.\n");
525 return -EACCES; /* INTEGRITY_UNKNOWN */ 531 return -EACCES; /* INTEGRITY_UNKNOWN */
526 } 532 }
@@ -528,7 +534,8 @@ int ima_load_data(enum kernel_load_data_id id)
528 case LOADING_MODULE: 534 case LOADING_MODULE:
529 sig_enforce = is_module_sig_enforced(); 535 sig_enforce = is_module_sig_enforced();
530 536
531 if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) { 537 if (ima_enforce && (!sig_enforce
538 && (ima_appraise & IMA_APPRAISE_MODULES))) {
532 pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); 539 pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
533 return -EACCES; /* INTEGRITY_UNKNOWN */ 540 return -EACCES; /* INTEGRITY_UNKNOWN */
534 } 541 }
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index fcf5b2729063..8bc8a1c8cb3f 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -20,6 +20,7 @@
20#include <linux/rculist.h> 20#include <linux/rculist.h>
21#include <linux/genhd.h> 21#include <linux/genhd.h>
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/ima.h>
23 24
24#include "ima.h" 25#include "ima.h"
25 26
@@ -58,6 +59,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
58 59
59enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB }; 60enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
60 61
62enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
63
61struct ima_rule_entry { 64struct ima_rule_entry {
62 struct list_head list; 65 struct list_head list;
63 int action; 66 int action;
@@ -104,7 +107,8 @@ static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
104 .flags = IMA_FSMAGIC}, 107 .flags = IMA_FSMAGIC},
105 {.action = DONT_MEASURE, .fsmagic = CGROUP2_SUPER_MAGIC, 108 {.action = DONT_MEASURE, .fsmagic = CGROUP2_SUPER_MAGIC,
106 .flags = IMA_FSMAGIC}, 109 .flags = IMA_FSMAGIC},
107 {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC} 110 {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
111 {.action = DONT_MEASURE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC}
108}; 112};
109 113
110static struct ima_rule_entry original_measurement_rules[] __ro_after_init = { 114static struct ima_rule_entry original_measurement_rules[] __ro_after_init = {
@@ -147,6 +151,7 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
147 {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, 151 {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
148 {.action = DONT_APPRAISE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC}, 152 {.action = DONT_APPRAISE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC},
149 {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, 153 {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
154 {.action = DONT_APPRAISE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC},
150 {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 155 {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
151 {.action = DONT_APPRAISE, .fsmagic = CGROUP2_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 156 {.action = DONT_APPRAISE, .fsmagic = CGROUP2_SUPER_MAGIC, .flags = IMA_FSMAGIC},
152#ifdef CONFIG_IMA_WRITE_POLICY 157#ifdef CONFIG_IMA_WRITE_POLICY
@@ -193,6 +198,9 @@ static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
193 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 198 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
194}; 199};
195 200
201/* An array of architecture specific rules */
202struct ima_rule_entry *arch_policy_entry __ro_after_init;
203
196static LIST_HEAD(ima_default_rules); 204static LIST_HEAD(ima_default_rules);
197static LIST_HEAD(ima_policy_rules); 205static LIST_HEAD(ima_policy_rules);
198static LIST_HEAD(ima_temp_rules); 206static LIST_HEAD(ima_temp_rules);
@@ -473,6 +481,75 @@ static int ima_appraise_flag(enum ima_hooks func)
473 return 0; 481 return 0;
474} 482}
475 483
484static void add_rules(struct ima_rule_entry *entries, int count,
485 enum policy_rule_list policy_rule)
486{
487 int i = 0;
488
489 for (i = 0; i < count; i++) {
490 struct ima_rule_entry *entry;
491
492 if (policy_rule & IMA_DEFAULT_POLICY)
493 list_add_tail(&entries[i].list, &ima_default_rules);
494
495 if (policy_rule & IMA_CUSTOM_POLICY) {
496 entry = kmemdup(&entries[i], sizeof(*entry),
497 GFP_KERNEL);
498 if (!entry)
499 continue;
500
501 list_add_tail(&entry->list, &ima_policy_rules);
502 }
503 if (entries[i].action == APPRAISE)
504 temp_ima_appraise |= ima_appraise_flag(entries[i].func);
505 if (entries[i].func == POLICY_CHECK)
506 temp_ima_appraise |= IMA_APPRAISE_POLICY;
507 }
508}
509
510static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
511
512static int __init ima_init_arch_policy(void)
513{
514 const char * const *arch_rules;
515 const char * const *rules;
516 int arch_entries = 0;
517 int i = 0;
518
519 arch_rules = arch_get_ima_policy();
520 if (!arch_rules)
521 return arch_entries;
522
523 /* Get number of rules */
524 for (rules = arch_rules; *rules != NULL; rules++)
525 arch_entries++;
526
527 arch_policy_entry = kcalloc(arch_entries + 1,
528 sizeof(*arch_policy_entry), GFP_KERNEL);
529 if (!arch_policy_entry)
530 return 0;
531
532 /* Convert each policy string rules to struct ima_rule_entry format */
533 for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
534 char rule[255];
535 int result;
536
537 result = strlcpy(rule, *rules, sizeof(rule));
538
539 INIT_LIST_HEAD(&arch_policy_entry[i].list);
540 result = ima_parse_rule(rule, &arch_policy_entry[i]);
541 if (result) {
542 pr_warn("Skipping unknown architecture policy rule: %s\n",
543 rule);
544 memset(&arch_policy_entry[i], 0,
545 sizeof(*arch_policy_entry));
546 continue;
547 }
548 i++;
549 }
550 return i;
551}
552
476/** 553/**
477 * ima_init_policy - initialize the default measure rules. 554 * ima_init_policy - initialize the default measure rules.
478 * 555 *
@@ -481,68 +558,68 @@ static int ima_appraise_flag(enum ima_hooks func)
481 */ 558 */
482void __init ima_init_policy(void) 559void __init ima_init_policy(void)
483{ 560{
484 int i, measure_entries, appraise_entries, secure_boot_entries; 561 int build_appraise_entries, arch_entries;
485 562
486 /* if !ima_policy set entries = 0 so we load NO default rules */ 563 /* if !ima_policy, we load NO default rules */
487 measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0; 564 if (ima_policy)
488 appraise_entries = ima_use_appraise_tcb ? 565 add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
489 ARRAY_SIZE(default_appraise_rules) : 0; 566 IMA_DEFAULT_POLICY);
490 secure_boot_entries = ima_use_secure_boot ?
491 ARRAY_SIZE(secure_boot_rules) : 0;
492
493 for (i = 0; i < measure_entries; i++)
494 list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
495 567
496 switch (ima_policy) { 568 switch (ima_policy) {
497 case ORIGINAL_TCB: 569 case ORIGINAL_TCB:
498 for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++) 570 add_rules(original_measurement_rules,
499 list_add_tail(&original_measurement_rules[i].list, 571 ARRAY_SIZE(original_measurement_rules),
500 &ima_default_rules); 572 IMA_DEFAULT_POLICY);
501 break; 573 break;
502 case DEFAULT_TCB: 574 case DEFAULT_TCB:
503 for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++) 575 add_rules(default_measurement_rules,
504 list_add_tail(&default_measurement_rules[i].list, 576 ARRAY_SIZE(default_measurement_rules),
505 &ima_default_rules); 577 IMA_DEFAULT_POLICY);
506 default: 578 default:
507 break; 579 break;
508 } 580 }
509 581
510 /* 582 /*
583 * Based on runtime secure boot flags, insert arch specific measurement
584 * and appraise rules requiring file signatures for both the initial
585 * and custom policies, prior to other appraise rules.
586 * (Highest priority)
587 */
588 arch_entries = ima_init_arch_policy();
589 if (!arch_entries)
590 pr_info("No architecture policies found\n");
591 else
592 add_rules(arch_policy_entry, arch_entries,
593 IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
594
595 /*
511 * Insert the builtin "secure_boot" policy rules requiring file 596 * Insert the builtin "secure_boot" policy rules requiring file
512 * signatures, prior to any other appraise rules. 597 * signatures, prior to other appraise rules.
513 */ 598 */
514 for (i = 0; i < secure_boot_entries; i++) { 599 if (ima_use_secure_boot)
515 list_add_tail(&secure_boot_rules[i].list, &ima_default_rules); 600 add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
516 temp_ima_appraise |= 601 IMA_DEFAULT_POLICY);
517 ima_appraise_flag(secure_boot_rules[i].func);
518 }
519 602
520 /* 603 /*
521 * Insert the build time appraise rules requiring file signatures 604 * Insert the build time appraise rules requiring file signatures
522 * for both the initial and custom policies, prior to other appraise 605 * for both the initial and custom policies, prior to other appraise
523 * rules. 606 * rules. As the secure boot rules includes all of the build time
607 * rules, include either one or the other set of rules, but not both.
524 */ 608 */
525 for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) { 609 build_appraise_entries = ARRAY_SIZE(build_appraise_rules);
526 struct ima_rule_entry *entry; 610 if (build_appraise_entries) {
527 611 if (ima_use_secure_boot)
528 if (!secure_boot_entries) 612 add_rules(build_appraise_rules, build_appraise_entries,
529 list_add_tail(&build_appraise_rules[i].list, 613 IMA_CUSTOM_POLICY);
530 &ima_default_rules); 614 else
531 615 add_rules(build_appraise_rules, build_appraise_entries,
532 entry = kmemdup(&build_appraise_rules[i], sizeof(*entry), 616 IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
533 GFP_KERNEL);
534 if (entry)
535 list_add_tail(&entry->list, &ima_policy_rules);
536 build_ima_appraise |=
537 ima_appraise_flag(build_appraise_rules[i].func);
538 } 617 }
539 618
540 for (i = 0; i < appraise_entries; i++) { 619 if (ima_use_appraise_tcb)
541 list_add_tail(&default_appraise_rules[i].list, 620 add_rules(default_appraise_rules,
542 &ima_default_rules); 621 ARRAY_SIZE(default_appraise_rules),
543 if (default_appraise_rules[i].func == POLICY_CHECK) 622 IMA_DEFAULT_POLICY);
544 temp_ima_appraise |= IMA_APPRAISE_POLICY;
545 }
546 623
547 ima_rules = &ima_default_rules; 624 ima_rules = &ima_default_rules;
548 ima_update_policy_flag(); 625 ima_update_policy_flag();
@@ -576,6 +653,14 @@ void ima_update_policy(void)
576 if (ima_rules != policy) { 653 if (ima_rules != policy) {
577 ima_policy_flag = 0; 654 ima_policy_flag = 0;
578 ima_rules = policy; 655 ima_rules = policy;
656
657 /*
658 * IMA architecture specific policy rules are specified
659 * as strings and converted to an array of ima_entry_rules
660 * on boot. After loading a custom policy, free the
661 * architecture specific rules stored as an array.
662 */
663 kfree(arch_policy_entry);
579 } 664 }
580 ima_update_policy_flag(); 665 ima_update_policy_flag();
581} 666}
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index e60473b13a8d..7de59f44cba3 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -141,7 +141,7 @@ int integrity_kernel_read(struct file *file, loff_t offset,
141 141
142#define INTEGRITY_KEYRING_EVM 0 142#define INTEGRITY_KEYRING_EVM 0
143#define INTEGRITY_KEYRING_IMA 1 143#define INTEGRITY_KEYRING_IMA 1
144#define INTEGRITY_KEYRING_MODULE 2 144#define INTEGRITY_KEYRING_PLATFORM 2
145#define INTEGRITY_KEYRING_MAX 3 145#define INTEGRITY_KEYRING_MAX 3
146 146
147extern struct dentry *integrity_dir; 147extern struct dentry *integrity_dir;
@@ -153,6 +153,8 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
153 153
154int __init integrity_init_keyring(const unsigned int id); 154int __init integrity_init_keyring(const unsigned int id);
155int __init integrity_load_x509(const unsigned int id, const char *path); 155int __init integrity_load_x509(const unsigned int id, const char *path);
156int __init integrity_load_cert(const unsigned int id, const char *source,
157 const void *data, size_t len, key_perm_t perm);
156#else 158#else
157 159
158static inline int integrity_digsig_verify(const unsigned int id, 160static inline int integrity_digsig_verify(const unsigned int id,
@@ -166,6 +168,14 @@ static inline int integrity_init_keyring(const unsigned int id)
166{ 168{
167 return 0; 169 return 0;
168} 170}
171
172static inline int __init integrity_load_cert(const unsigned int id,
173 const char *source,
174 const void *data, size_t len,
175 key_perm_t perm)
176{
177 return 0;
178}
169#endif /* CONFIG_INTEGRITY_SIGNATURE */ 179#endif /* CONFIG_INTEGRITY_SIGNATURE */
170 180
171#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS 181#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
@@ -222,3 +232,13 @@ integrity_audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type)
222} 232}
223 233
224#endif 234#endif
235
236#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
237void __init add_to_platform_keyring(const char *source, const void *data,
238 size_t len);
239#else
240static inline void __init add_to_platform_keyring(const char *source,
241 const void *data, size_t len)
242{
243}
244#endif
diff --git a/security/integrity/platform_certs/efi_parser.c b/security/integrity/platform_certs/efi_parser.c
new file mode 100644
index 000000000000..18f01f36fe6a
--- /dev/null
+++ b/security/integrity/platform_certs/efi_parser.c
@@ -0,0 +1,108 @@
1// SPDX-License-Identifier: GPL-2.0+
2/* EFI signature/key/certificate list parser
3 *
4 * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 */
7
8#define pr_fmt(fmt) "EFI: "fmt
9#include <linux/module.h>
10#include <linux/printk.h>
11#include <linux/err.h>
12#include <linux/efi.h>
13
14/**
15 * parse_efi_signature_list - Parse an EFI signature list for certificates
16 * @source: The source of the key
17 * @data: The data blob to parse
18 * @size: The size of the data blob
19 * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
20 *
21 * Parse an EFI signature list looking for elements of interest. A list is
22 * made up of a series of sublists, where all the elements in a sublist are of
23 * the same type, but sublists can be of different types.
24 *
25 * For each sublist encountered, the @get_handler_for_guid function is called
26 * with the type specifier GUID and returns either a pointer to a function to
27 * handle elements of that type or NULL if the type is not of interest.
28 *
29 * If the sublist is of interest, each element is passed to the handler
30 * function in turn.
31 *
32 * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
33 * returned if the list was parsed correctly. No error can be returned from
34 * the @get_handler_for_guid function or the element handler function it
35 * returns.
36 */
37int __init parse_efi_signature_list(
38 const char *source,
39 const void *data, size_t size,
40 efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
41{
42 efi_element_handler_t handler;
43 unsigned int offs = 0;
44
45 pr_devel("-->%s(,%zu)\n", __func__, size);
46
47 while (size > 0) {
48 const efi_signature_data_t *elem;
49 efi_signature_list_t list;
50 size_t lsize, esize, hsize, elsize;
51
52 if (size < sizeof(list))
53 return -EBADMSG;
54
55 memcpy(&list, data, sizeof(list));
56 pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
57 offs,
58 list.signature_type.b, list.signature_list_size,
59 list.signature_header_size, list.signature_size);
60
61 lsize = list.signature_list_size;
62 hsize = list.signature_header_size;
63 esize = list.signature_size;
64 elsize = lsize - sizeof(list) - hsize;
65
66 if (lsize > size) {
67 pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
68 __func__, offs);
69 return -EBADMSG;
70 }
71
72 if (lsize < sizeof(list) ||
73 lsize - sizeof(list) < hsize ||
74 esize < sizeof(*elem) ||
75 elsize < esize ||
76 elsize % esize != 0) {
77 pr_devel("- bad size combo @%x\n", offs);
78 return -EBADMSG;
79 }
80
81 handler = get_handler_for_guid(&list.signature_type);
82 if (!handler) {
83 data += lsize;
84 size -= lsize;
85 offs += lsize;
86 continue;
87 }
88
89 data += sizeof(list) + hsize;
90 size -= sizeof(list) + hsize;
91 offs += sizeof(list) + hsize;
92
93 for (; elsize > 0; elsize -= esize) {
94 elem = data;
95
96 pr_devel("ELEM[%04x]\n", offs);
97 handler(source,
98 &elem->signature_data,
99 esize - sizeof(*elem));
100
101 data += esize;
102 size -= esize;
103 offs += esize;
104 }
105 }
106
107 return 0;
108}
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index 000000000000..81b19c52832b
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,194 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/kernel.h>
4#include <linux/sched.h>
5#include <linux/cred.h>
6#include <linux/err.h>
7#include <linux/efi.h>
8#include <linux/slab.h>
9#include <keys/asymmetric-type.h>
10#include <keys/system_keyring.h>
11#include "../integrity.h"
12
13static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
14static efi_guid_t efi_cert_x509_sha256_guid __initdata =
15 EFI_CERT_X509_SHA256_GUID;
16static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
17
18/*
19 * Look to see if a UEFI variable called MokIgnoreDB exists and return true if
20 * it does.
21 *
22 * This UEFI variable is set by the shim if a user tells the shim to not use
23 * the certs/hashes in the UEFI db variable for verification purposes. If it
24 * is set, we should ignore the db variable also and the true return indicates
25 * this.
26 */
27static __init bool uefi_check_ignore_db(void)
28{
29 efi_status_t status;
30 unsigned int db = 0;
31 unsigned long size = sizeof(db);
32 efi_guid_t guid = EFI_SHIM_LOCK_GUID;
33
34 status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db);
35 return status == EFI_SUCCESS;
36}
37
38/*
39 * Get a certificate list blob from the named EFI variable.
40 */
41static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
42 unsigned long *size)
43{
44 efi_status_t status;
45 unsigned long lsize = 4;
46 unsigned long tmpdb[4];
47 void *db;
48
49 status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
50 if (status != EFI_BUFFER_TOO_SMALL) {
51 pr_err("Couldn't get size: 0x%lx\n", status);
52 return NULL;
53 }
54
55 db = kmalloc(lsize, GFP_KERNEL);
56 if (!db)
57 return NULL;
58
59 status = efi.get_variable(name, guid, NULL, &lsize, db);
60 if (status != EFI_SUCCESS) {
61 kfree(db);
62 pr_err("Error reading db var: 0x%lx\n", status);
63 return NULL;
64 }
65
66 *size = lsize;
67 return db;
68}
69
70/*
71 * Blacklist a hash.
72 */
73static __init void uefi_blacklist_hash(const char *source, const void *data,
74 size_t len, const char *type,
75 size_t type_len)
76{
77 char *hash, *p;
78
79 hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
80 if (!hash)
81 return;
82 p = memcpy(hash, type, type_len);
83 p += type_len;
84 bin2hex(p, data, len);
85 p += len * 2;
86 *p = 0;
87
88 mark_hash_blacklisted(hash);
89 kfree(hash);
90}
91
92/*
93 * Blacklist an X509 TBS hash.
94 */
95static __init void uefi_blacklist_x509_tbs(const char *source,
96 const void *data, size_t len)
97{
98 uefi_blacklist_hash(source, data, len, "tbs:", 4);
99}
100
101/*
102 * Blacklist the hash of an executable.
103 */
104static __init void uefi_blacklist_binary(const char *source,
105 const void *data, size_t len)
106{
107 uefi_blacklist_hash(source, data, len, "bin:", 4);
108}
109
110/*
111 * Return the appropriate handler for particular signature list types found in
112 * the UEFI db and MokListRT tables.
113 */
114static __init efi_element_handler_t get_handler_for_db(const efi_guid_t *
115 sig_type)
116{
117 if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
118 return add_to_platform_keyring;
119 return 0;
120}
121
122/*
123 * Return the appropriate handler for particular signature list types found in
124 * the UEFI dbx and MokListXRT tables.
125 */
126static __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *
127 sig_type)
128{
129 if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
130 return uefi_blacklist_x509_tbs;
131 if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
132 return uefi_blacklist_binary;
133 return 0;
134}
135
136/*
137 * Load the certs contained in the UEFI databases into the platform trusted
138 * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
139 * keyring.
140 */
141static int __init load_uefi_certs(void)
142{
143 efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
144 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
145 void *db = NULL, *dbx = NULL, *mok = NULL;
146 unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
147 int rc = 0;
148
149 if (!efi.get_variable)
150 return false;
151
152 /* Get db, MokListRT, and dbx. They might not exist, so it isn't
153 * an error if we can't get them.
154 */
155 if (!uefi_check_ignore_db()) {
156 db = get_cert_list(L"db", &secure_var, &dbsize);
157 if (!db) {
158 pr_err("MODSIGN: Couldn't get UEFI db list\n");
159 } else {
160 rc = parse_efi_signature_list("UEFI:db",
161 db, dbsize, get_handler_for_db);
162 if (rc)
163 pr_err("Couldn't parse db signatures: %d\n",
164 rc);
165 kfree(db);
166 }
167 }
168
169 mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
170 if (!mok) {
171 pr_info("Couldn't get UEFI MokListRT\n");
172 } else {
173 rc = parse_efi_signature_list("UEFI:MokListRT",
174 mok, moksize, get_handler_for_db);
175 if (rc)
176 pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
177 kfree(mok);
178 }
179
180 dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
181 if (!dbx) {
182 pr_info("Couldn't get UEFI dbx list\n");
183 } else {
184 rc = parse_efi_signature_list("UEFI:dbx",
185 dbx, dbxsize,
186 get_handler_for_dbx);
187 if (rc)
188 pr_err("Couldn't parse dbx signatures: %d\n", rc);
189 kfree(dbx);
190 }
191
192 return rc;
193}
194late_initcall(load_uefi_certs);
diff --git a/security/integrity/platform_certs/platform_keyring.c b/security/integrity/platform_certs/platform_keyring.c
new file mode 100644
index 000000000000..bcafd7387729
--- /dev/null
+++ b/security/integrity/platform_certs/platform_keyring.c
@@ -0,0 +1,58 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Platform keyring for firmware/platform keys
4 *
5 * Copyright IBM Corporation, 2018
6 * Author(s): Nayna Jain <nayna@linux.ibm.com>
7 */
8
9#include <linux/export.h>
10#include <linux/kernel.h>
11#include <linux/sched.h>
12#include <linux/cred.h>
13#include <linux/err.h>
14#include <linux/slab.h>
15#include "../integrity.h"
16
17/**
18 * add_to_platform_keyring - Add to platform keyring without validation.
19 * @source: Source of key
20 * @data: The blob holding the key
21 * @len: The length of the data blob
22 *
23 * Add a key to the platform keyring without checking its trust chain. This
24 * is available only during kernel initialisation.
25 */
26void __init add_to_platform_keyring(const char *source, const void *data,
27 size_t len)
28{
29 key_perm_t perm;
30 int rc;
31
32 perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
33
34 rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source, data, len,
35 perm);
36 if (rc)
37 pr_info("Error adding keys to platform keyring %s\n", source);
38}
39
40/*
41 * Create the trusted keyrings.
42 */
43static __init int platform_keyring_init(void)
44{
45 int rc;
46
47 rc = integrity_init_keyring(INTEGRITY_KEYRING_PLATFORM);
48 if (rc)
49 return rc;
50
51 pr_notice("Platform Keyring initialized\n");
52 return 0;
53}
54
55/*
56 * Must be initialised before we try and load the keys into the keyring.
57 */
58device_initcall(platform_keyring_init);