summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Garrett <matthewgarrett@google.com>2019-08-19 20:18:01 -0400
committerJames Morris <jmorris@namei.org>2019-08-20 00:54:16 -0400
commit29d3c1c8dfe752c01b7115ecd5a3142b232a38e1 (patch)
tree9a42db9e64c08db645dcf9689344d4f718b4d518
parentb0c8fdc7fdb77586c3d1937050925b960743306e (diff)
kexec: Allow kexec_file() with appropriate IMA policy when locked down
Systems in lockdown mode should block the kexec of untrusted kernels. For x86 and ARM we can ensure that a kernel is trustworthy by validating a PE signature, but this isn't possible on other architectures. On those platforms we can use IMA digital signatures instead. Add a function to determine whether IMA has or will verify signatures for a given event type, and if so permit kexec_file() even if the kernel is otherwise locked down. This is restricted to cases where CONFIG_INTEGRITY_TRUSTED_KEYRING is set in order to prevent an attacker from loading additional keys at runtime. Signed-off-by: Matthew Garrett <mjg59@google.com> Acked-by: Mimi Zohar <zohar@linux.ibm.com> Cc: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> Cc: linux-integrity@vger.kernel.org Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--include/linux/ima.h9
-rw-r--r--kernel/kexec_file.c10
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_main.c2
-rw-r--r--security/integrity/ima/ima_policy.c50
5 files changed, 71 insertions, 2 deletions
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 00036d2f57c3..8e2f324fb901 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -129,4 +129,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
129 return 0; 129 return 0;
130} 130}
131#endif /* CONFIG_IMA_APPRAISE */ 131#endif /* CONFIG_IMA_APPRAISE */
132
133#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
134extern bool ima_appraise_signature(enum kernel_read_file_id func);
135#else
136static inline bool ima_appraise_signature(enum kernel_read_file_id func)
137{
138 return false;
139}
140#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
132#endif /* _LINUX_IMA_H */ 141#endif /* _LINUX_IMA_H */
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 43109ef4d6bf..7f4a618fc8c1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -208,7 +208,15 @@ kimage_validate_signature(struct kimage *image)
208 return ret; 208 return ret;
209 } 209 }
210 210
211 return security_locked_down(LOCKDOWN_KEXEC); 211 /* If IMA is guaranteed to appraise a signature on the kexec
212 * image, permit it even if the kernel is otherwise locked
213 * down.
214 */
215 if (!ima_appraise_signature(READING_KEXEC_IMAGE) &&
216 security_locked_down(LOCKDOWN_KEXEC))
217 return -EPERM;
218
219 return 0;
212 220
213 /* All other errors are fatal, including nomem, unparseable 221 /* All other errors are fatal, including nomem, unparseable
214 * signatures and signature check failures - even if signatures 222 * signatures and signature check failures - even if signatures
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index ca10917b5f89..874bd77d3b91 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -111,6 +111,8 @@ struct ima_kexec_hdr {
111 u64 count; 111 u64 count;
112}; 112};
113 113
114extern const int read_idmap[];
115
114#ifdef CONFIG_HAVE_IMA_KEXEC 116#ifdef CONFIG_HAVE_IMA_KEXEC
115void ima_load_kexec_buffer(void); 117void ima_load_kexec_buffer(void);
116#else 118#else
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1cffda4412b7..1747bc7bcb60 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -469,7 +469,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
469 return 0; 469 return 0;
470} 470}
471 471
472static const int read_idmap[READING_MAX_ID] = { 472const int read_idmap[READING_MAX_ID] = {
473 [READING_FIRMWARE] = FIRMWARE_CHECK, 473 [READING_FIRMWARE] = FIRMWARE_CHECK,
474 [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK, 474 [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK,
475 [READING_MODULE] = MODULE_CHECK, 475 [READING_MODULE] = MODULE_CHECK,
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 7b53f2ca58e2..b8773f05f9da 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1339,3 +1339,53 @@ int ima_policy_show(struct seq_file *m, void *v)
1339 return 0; 1339 return 0;
1340} 1340}
1341#endif /* CONFIG_IMA_READ_POLICY */ 1341#endif /* CONFIG_IMA_READ_POLICY */
1342
1343#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
1344/*
1345 * ima_appraise_signature: whether IMA will appraise a given function using
1346 * an IMA digital signature. This is restricted to cases where the kernel
1347 * has a set of built-in trusted keys in order to avoid an attacker simply
1348 * loading additional keys.
1349 */
1350bool ima_appraise_signature(enum kernel_read_file_id id)
1351{
1352 struct ima_rule_entry *entry;
1353 bool found = false;
1354 enum ima_hooks func;
1355
1356 if (id >= READING_MAX_ID)
1357 return false;
1358
1359 func = read_idmap[id] ?: FILE_CHECK;
1360
1361 rcu_read_lock();
1362 list_for_each_entry_rcu(entry, ima_rules, list) {
1363 if (entry->action != APPRAISE)
1364 continue;
1365
1366 /*
1367 * A generic entry will match, but otherwise require that it
1368 * match the func we're looking for
1369 */
1370 if (entry->func && entry->func != func)
1371 continue;
1372
1373 /*
1374 * We require this to be a digital signature, not a raw IMA
1375 * hash.
1376 */
1377 if (entry->flags & IMA_DIGSIG_REQUIRED)
1378 found = true;
1379
1380 /*
1381 * We've found a rule that matches, so break now even if it
1382 * didn't require a digital signature - a later rule that does
1383 * won't override it, so would be a false positive.
1384 */
1385 break;
1386 }
1387
1388 rcu_read_unlock();
1389 return found;
1390}
1391#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */