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>
This commit is contained in:
parent
b0c8fdc7fd
commit
29d3c1c8df
|
@ -129,4 +129,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IMA_APPRAISE */
|
||||
|
||||
#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
|
||||
extern bool ima_appraise_signature(enum kernel_read_file_id func);
|
||||
#else
|
||||
static inline bool ima_appraise_signature(enum kernel_read_file_id func)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
|
||||
#endif /* _LINUX_IMA_H */
|
||||
|
|
|
@ -208,7 +208,15 @@ kimage_validate_signature(struct kimage *image)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return security_locked_down(LOCKDOWN_KEXEC);
|
||||
/* If IMA is guaranteed to appraise a signature on the kexec
|
||||
* image, permit it even if the kernel is otherwise locked
|
||||
* down.
|
||||
*/
|
||||
if (!ima_appraise_signature(READING_KEXEC_IMAGE) &&
|
||||
security_locked_down(LOCKDOWN_KEXEC))
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
|
||||
/* All other errors are fatal, including nomem, unparseable
|
||||
* signatures and signature check failures - even if signatures
|
||||
|
|
|
@ -111,6 +111,8 @@ struct ima_kexec_hdr {
|
|||
u64 count;
|
||||
};
|
||||
|
||||
extern const int read_idmap[];
|
||||
|
||||
#ifdef CONFIG_HAVE_IMA_KEXEC
|
||||
void ima_load_kexec_buffer(void);
|
||||
#else
|
||||
|
|
|
@ -469,7 +469,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const int read_idmap[READING_MAX_ID] = {
|
||||
const int read_idmap[READING_MAX_ID] = {
|
||||
[READING_FIRMWARE] = FIRMWARE_CHECK,
|
||||
[READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK,
|
||||
[READING_MODULE] = MODULE_CHECK,
|
||||
|
|
|
@ -1339,3 +1339,53 @@ int ima_policy_show(struct seq_file *m, void *v)
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IMA_READ_POLICY */
|
||||
|
||||
#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
|
||||
/*
|
||||
* ima_appraise_signature: whether IMA will appraise a given function using
|
||||
* an IMA digital signature. This is restricted to cases where the kernel
|
||||
* has a set of built-in trusted keys in order to avoid an attacker simply
|
||||
* loading additional keys.
|
||||
*/
|
||||
bool ima_appraise_signature(enum kernel_read_file_id id)
|
||||
{
|
||||
struct ima_rule_entry *entry;
|
||||
bool found = false;
|
||||
enum ima_hooks func;
|
||||
|
||||
if (id >= READING_MAX_ID)
|
||||
return false;
|
||||
|
||||
func = read_idmap[id] ?: FILE_CHECK;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(entry, ima_rules, list) {
|
||||
if (entry->action != APPRAISE)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* A generic entry will match, but otherwise require that it
|
||||
* match the func we're looking for
|
||||
*/
|
||||
if (entry->func && entry->func != func)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We require this to be a digital signature, not a raw IMA
|
||||
* hash.
|
||||
*/
|
||||
if (entry->flags & IMA_DIGSIG_REQUIRED)
|
||||
found = true;
|
||||
|
||||
/*
|
||||
* We've found a rule that matches, so break now even if it
|
||||
* didn't require a digital signature - a later rule that does
|
||||
* won't override it, so would be a false positive.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return found;
|
||||
}
|
||||
#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
|
||||
|
|
Loading…
Reference in New Issue