Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29d3c1c8 authored by Matthew Garrett's avatar Matthew Garrett Committed by James Morris
Browse files

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: default avatarMatthew Garrett <mjg59@google.com>
Acked-by: default avatarMimi Zohar <zohar@linux.ibm.com>
Cc: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: linux-integrity@vger.kernel.org
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent b0c8fdc7
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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 */
+9 −1
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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,
+50 −0
Original line number Diff line number Diff line
@@ -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 */