Skip to content

Commit 29d3c1c

Browse files
Matthew GarrettJames Morris
authored andcommitted
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 <[email protected]> Acked-by: Mimi Zohar <[email protected]> Cc: Dmitry Kasatkin <[email protected]> Cc: [email protected] Signed-off-by: James Morris <[email protected]>
1 parent b0c8fdc commit 29d3c1c

File tree

5 files changed

+71
-2
lines changed

5 files changed

+71
-2
lines changed

include/linux/ima.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,15 @@ kimage_validate_signature(struct kimage *image)
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ struct ima_kexec_hdr {
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,3 +1339,53 @@ int ima_policy_show(struct seq_file *m, void *v)
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 */

0 commit comments

Comments
 (0)