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>
Dieser Commit ist enthalten in:
Matthew Garrett
2019-08-19 17:18:01 -07:00
committet von James Morris
Ursprung b0c8fdc7fd
Commit 29d3c1c8df
5 geänderte Dateien mit 71 neuen und 2 gelöschten Zeilen

Datei anzeigen

@@ -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

Datei anzeigen

@@ -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,

Datei anzeigen

@@ -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 */