ima: measure and appraise the IMA policy itself
Add support for measuring and appraising the IMA policy itself. Changelog v4: - use braces on both if/else branches, even if single line on one of the branches - Dmitry - Use the id mapping - Dmitry Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Petko Manolov <petkan@mip-labs.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
This commit is contained in:
Родитель
7429b09281
Коммит
19f8a84713
|
@ -149,6 +149,7 @@ enum ima_hooks {
|
||||||
FIRMWARE_CHECK,
|
FIRMWARE_CHECK,
|
||||||
KEXEC_KERNEL_CHECK,
|
KEXEC_KERNEL_CHECK,
|
||||||
KEXEC_INITRAMFS_CHECK,
|
KEXEC_INITRAMFS_CHECK,
|
||||||
|
POLICY_CHECK,
|
||||||
MAX_CHECK
|
MAX_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,6 +192,7 @@ int ima_policy_show(struct seq_file *m, void *v);
|
||||||
#define IMA_APPRAISE_LOG 0x04
|
#define IMA_APPRAISE_LOG 0x04
|
||||||
#define IMA_APPRAISE_MODULES 0x08
|
#define IMA_APPRAISE_MODULES 0x08
|
||||||
#define IMA_APPRAISE_FIRMWARE 0x10
|
#define IMA_APPRAISE_FIRMWARE 0x10
|
||||||
|
#define IMA_APPRAISE_POLICY 0x20
|
||||||
|
|
||||||
#ifdef CONFIG_IMA_APPRAISE
|
#ifdef CONFIG_IMA_APPRAISE
|
||||||
int ima_appraise_measurement(enum ima_hooks func,
|
int ima_appraise_measurement(enum ima_hooks func,
|
||||||
|
|
|
@ -325,10 +325,18 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
if (data[0] == '/')
|
if (data[0] == '/') {
|
||||||
result = ima_read_policy(data);
|
result = ima_read_policy(data);
|
||||||
else
|
} else if (ima_appraise & IMA_APPRAISE_POLICY) {
|
||||||
|
pr_err("IMA: signed policy file (specified as an absolute pathname) required\n");
|
||||||
|
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
|
||||||
|
"policy_update", "signed policy required",
|
||||||
|
1, 0);
|
||||||
|
if (ima_appraise & IMA_APPRAISE_ENFORCE)
|
||||||
|
result = -EACCES;
|
||||||
|
} else {
|
||||||
result = ima_parse_add_rule(data);
|
result = ima_parse_add_rule(data);
|
||||||
|
}
|
||||||
mutex_unlock(&ima_write_mutex);
|
mutex_unlock(&ima_write_mutex);
|
||||||
out_free:
|
out_free:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
|
|
|
@ -344,6 +344,7 @@ static int read_idmap[READING_MAX_ID] = {
|
||||||
[READING_MODULE] = MODULE_CHECK,
|
[READING_MODULE] = MODULE_CHECK,
|
||||||
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
|
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
|
||||||
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
|
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
|
||||||
|
[READING_POLICY] = POLICY_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -114,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
|
||||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
|
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
|
||||||
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
||||||
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
|
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
|
||||||
|
{.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ima_rule_entry default_appraise_rules[] = {
|
static struct ima_rule_entry default_appraise_rules[] = {
|
||||||
|
@ -618,6 +619,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
|
else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
|
||||||
== 0)
|
== 0)
|
||||||
entry->func = KEXEC_INITRAMFS_CHECK;
|
entry->func = KEXEC_INITRAMFS_CHECK;
|
||||||
|
else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
|
||||||
|
entry->func = POLICY_CHECK;
|
||||||
else
|
else
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
if (!result)
|
if (!result)
|
||||||
|
@ -776,6 +779,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
temp_ima_appraise |= IMA_APPRAISE_MODULES;
|
temp_ima_appraise |= IMA_APPRAISE_MODULES;
|
||||||
else if (entry->func == FIRMWARE_CHECK)
|
else if (entry->func == FIRMWARE_CHECK)
|
||||||
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
|
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
|
||||||
|
else if (entry->func == POLICY_CHECK)
|
||||||
|
temp_ima_appraise |= IMA_APPRAISE_POLICY;
|
||||||
audit_log_format(ab, "res=%d", !result);
|
audit_log_format(ab, "res=%d", !result);
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
return result;
|
return result;
|
||||||
|
@ -862,7 +867,8 @@ static char *mask_tokens[] = {
|
||||||
enum {
|
enum {
|
||||||
func_file = 0, func_mmap, func_bprm,
|
func_file = 0, func_mmap, func_bprm,
|
||||||
func_module, func_firmware, func_post,
|
func_module, func_firmware, func_post,
|
||||||
func_kexec_kernel, func_kexec_initramfs
|
func_kexec_kernel, func_kexec_initramfs,
|
||||||
|
func_policy
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *func_tokens[] = {
|
static char *func_tokens[] = {
|
||||||
|
@ -873,6 +879,7 @@ static char *func_tokens[] = {
|
||||||
"FIRMWARE_CHECK",
|
"FIRMWARE_CHECK",
|
||||||
"KEXEC_KERNEL_CHECK",
|
"KEXEC_KERNEL_CHECK",
|
||||||
"KEXEC_INITRAMFS_CHECK",
|
"KEXEC_INITRAMFS_CHECK",
|
||||||
|
"POLICY_CHECK",
|
||||||
"POST_SETATTR"
|
"POST_SETATTR"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -944,6 +951,9 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
|
||||||
case KEXEC_INITRAMFS_CHECK:
|
case KEXEC_INITRAMFS_CHECK:
|
||||||
seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
|
seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
|
||||||
break;
|
break;
|
||||||
|
case POLICY_CHECK:
|
||||||
|
seq_printf(m, pt(Opt_func), ft(func_policy));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(tbuf, sizeof(tbuf), "%d", func);
|
snprintf(tbuf, sizeof(tbuf), "%d", func);
|
||||||
seq_printf(m, pt(Opt_func), tbuf);
|
seq_printf(m, pt(Opt_func), tbuf);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче