History

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.

Matthew Garrett committed 7 years ago

Commit 29d3c1c1 parent b0c8fdc5 files · +71 −2Browse files

Unified · Split

5 files
  1. include/linux/ima.h +9 −0
  2. kernel/kexec_file.c +9 −1
  3. security/integrity/ima/ima.h +2 −0
  4. security/integrity/ima/ima_main.c +1 −1
  5. security/integrity/ima/ima_policy.c +50 −0
include/linux/ima.h+9−0
@@ -129,4 +129,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry, · 128 unmodified lines
129129 return 0;
130130 }
131131 #endif /* CONFIG_IMA_APPRAISE */
132+
133+#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
134+extern bool ima_appraise_signature(enum kernel_read_file_id func);
135+#else
136+static 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 */
132141 #endif /* _LINUX_IMA_H */
kernel/kexec_file.c+9−1
@@ -208,7 +208,15 @@ kimage_validate_signature(struct kimage *image) · 207 unmodified lines
208208 return ret;
209209 }
210210
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;
212220
213221 /* All other errors are fatal, including nomem, unparseable
214222 * signatures and signature check failures - even if signatures
security/integrity/ima/ima.h+2−0
@@ -111,6 +111,8 @@ struct ima_kexec_hdr { · 110 unmodified lines
111111 u64 count;
112112 };
113113
114+extern const int read_idmap[];
115+
114116 #ifdef CONFIG_HAVE_IMA_KEXEC
115117 void ima_load_kexec_buffer(void);
116118 #else
security/integrity/ima/ima_main.c+1−1
@@ -469,7 +469,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) · 468 unmodified lines
469469 return 0;
470470 }
471471
472−static const int read_idmap[READING_MAX_ID] = {
472+const int read_idmap[READING_MAX_ID] = {
473473 [READING_FIRMWARE] = FIRMWARE_CHECK,
474474 [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK,
475475 [READING_MODULE] = MODULE_CHECK,
security/integrity/ima/ima_policy.c+50−0
@@ -1339,3 +1339,53 @@ int ima_policy_show(struct seq_file *m, void *v) · 1338 unmodified lines
13391339 return 0;
13401340 }
13411341 #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+ */
1350+bool 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 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t