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

Commit 16c267aa authored by Mimi Zohar's avatar Mimi Zohar Committed by James Morris
Browse files

ima: based on policy require signed kexec kernel images



The original kexec_load syscall can not verify file signatures, nor can
the kexec image be measured.  Based on policy, deny the kexec_load
syscall.

Signed-off-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Kees Cook <keescook@chromium.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarJames Morris <james.morris@microsoft.com>
parent a210fd32
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#define _LINUX_IMA_H

#include <linux/fs.h>
#include <linux/security.h>
#include <linux/kexec.h>
struct linux_binprm;

@@ -19,6 +20,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask, int opened);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_load_data(enum kernel_load_data_id id);
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
			      enum kernel_read_file_id id);
@@ -49,6 +51,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
	return 0;
}

static inline int ima_load_data(enum kernel_load_data_id id)
{
	return 0;
}

static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
{
	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -232,6 +232,7 @@ int ima_policy_show(struct seq_file *m, void *v);
#define IMA_APPRAISE_MODULES	0x08
#define IMA_APPRAISE_FIRMWARE	0x10
#define IMA_APPRAISE_POLICY	0x20
#define IMA_APPRAISE_KEXEC	0x40

#ifdef CONFIG_IMA_APPRAISE
int ima_appraise_measurement(enum ima_hooks func,
+27 −0
Original line number Diff line number Diff line
@@ -496,6 +496,33 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
				   MAY_READ, func, 0);
}

/**
 * ima_load_data - appraise decision based on policy
 * @id: kernel load data caller identifier
 *
 * Callers of this LSM hook can not measure, appraise, or audit the
 * data provided by userspace.  Enforce policy rules requring a file
 * signature (eg. kexec'ed kernel image).
 *
 * For permission return 0, otherwise return -EACCES.
 */
int ima_load_data(enum kernel_load_data_id id)
{
	if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
		return 0;

	switch (id) {
	case LOADING_KEXEC_IMAGE:
		if (ima_appraise & IMA_APPRAISE_KEXEC) {
			pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
			return -EACCES;	/* INTEGRITY_UNKNOWN */
		}
	default:
		break;
	}
	return 0;
}

static int __init init_ima(void)
{
	int error;
+2 −0
Original line number Diff line number Diff line
@@ -448,6 +448,8 @@ static int ima_appraise_flag(enum ima_hooks func)
		return IMA_APPRAISE_FIRMWARE;
	else if (func == POLICY_CHECK)
		return IMA_APPRAISE_POLICY;
	else if (func == KEXEC_KERNEL_CHECK)
		return IMA_APPRAISE_KEXEC;
	return 0;
}

+6 −1
Original line number Diff line number Diff line
@@ -1058,7 +1058,12 @@ EXPORT_SYMBOL_GPL(security_kernel_post_read_file);

int security_kernel_load_data(enum kernel_load_data_id id)
{
	return call_int_hook(kernel_load_data, 0, id);
	int ret;

	ret = call_int_hook(kernel_load_data, 0, id);
	if (ret)
		return ret;
	return ima_load_data(id);
}

int security_task_fix_setuid(struct cred *new, const struct cred *old,