ima: support for kexec image and initramfs
Add IMA policy support for measuring/appraising the kexec image and initramfs. Two new IMA policy identifiers KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK are defined. Example policy rules: measure func=KEXEC_KERNEL_CHECK appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig measure func=KEXEC_INITRAMFS_CHECK appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig Moving the enumeration to the vfs layer simplified the patches, allowing the IMA changes, for the most part, to be separated from the other changes. Unfortunately, passing either a kernel_read_file_id or a ima_hooks enumeration within IMA is messy. Option 1: duplicate kernel_read_file enumeration in ima_hooks enum kernel_read_file_id { ... READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS, READING_MAX_ID enum ima_hooks { ... KEXEC_KERNEL_CHECK KEXEC_INITRAMFS_CHECK Option 2: define ima_hooks as extension of kernel_read_file eg: enum ima_hooks { FILE_CHECK = READING_MAX_ID, MMAP_CHECK, In order to pass both kernel_read_file_id and ima_hooks values, we would need to specify a struct containing a union. struct caller_id { union { enum ima_hooks func_id; enum kernel_read_file_id read_id; }; }; Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id, perhaps changing the enumeration name. For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in the ima_hooks. Changelog v4: - replaced switch statement with a kernel_read_file_id to an ima_hooks id mapping array - Dmitry - renamed ima_hook tokens KEXEC_CHECK and INITRAMFS_CHECK to KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK respectively - Dave Young 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> Cc: Dave Young <dyoung@redhat.com>
This commit is contained in:
parent
b804defe42
commit
d9ddf077bb
@ -27,6 +27,7 @@ Description:
|
|||||||
|
|
||||||
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
||||||
[FIRMWARE_CHECK]
|
[FIRMWARE_CHECK]
|
||||||
|
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
|
||||||
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
|
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
|
||||||
[[^]MAY_EXEC]
|
[[^]MAY_EXEC]
|
||||||
fsmagic:= hex value
|
fsmagic:= hex value
|
||||||
|
@ -147,6 +147,8 @@ enum ima_hooks {
|
|||||||
POST_SETATTR,
|
POST_SETATTR,
|
||||||
MODULE_CHECK,
|
MODULE_CHECK,
|
||||||
FIRMWARE_CHECK,
|
FIRMWARE_CHECK,
|
||||||
|
KEXEC_KERNEL_CHECK,
|
||||||
|
KEXEC_INITRAMFS_CHECK,
|
||||||
MAX_CHECK
|
MAX_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -339,6 +339,13 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_idmap[READING_MAX_ID] = {
|
||||||
|
[READING_FIRMWARE] = FIRMWARE_CHECK,
|
||||||
|
[READING_MODULE] = MODULE_CHECK,
|
||||||
|
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
|
||||||
|
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ima_post_read_file - in memory collect/appraise/audit measurement
|
* ima_post_read_file - in memory collect/appraise/audit measurement
|
||||||
* @file: pointer to the file to be measured/appraised/audit
|
* @file: pointer to the file to be measured/appraised/audit
|
||||||
@ -355,7 +362,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
|
|||||||
int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
||||||
enum kernel_read_file_id read_id)
|
enum kernel_read_file_id read_id)
|
||||||
{
|
{
|
||||||
enum ima_hooks func = FILE_CHECK;
|
enum ima_hooks func;
|
||||||
|
|
||||||
if (!file && read_id == READING_FIRMWARE) {
|
if (!file && read_id == READING_FIRMWARE) {
|
||||||
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
|
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
|
||||||
@ -373,11 +380,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_id == READING_FIRMWARE)
|
func = read_idmap[read_id] ?: FILE_CHECK;
|
||||||
func = FIRMWARE_CHECK;
|
|
||||||
else if (read_id == READING_MODULE)
|
|
||||||
func = MODULE_CHECK;
|
|
||||||
|
|
||||||
return process_measurement(file, buf, size, MAY_READ, func, 0);
|
return process_measurement(file, buf, size, MAY_READ, func, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,6 +612,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
|||||||
entry->func = MMAP_CHECK;
|
entry->func = MMAP_CHECK;
|
||||||
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
|
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
|
||||||
entry->func = BPRM_CHECK;
|
entry->func = BPRM_CHECK;
|
||||||
|
else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") ==
|
||||||
|
0)
|
||||||
|
entry->func = KEXEC_KERNEL_CHECK;
|
||||||
|
else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
|
||||||
|
== 0)
|
||||||
|
entry->func = KEXEC_INITRAMFS_CHECK;
|
||||||
else
|
else
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
if (!result)
|
if (!result)
|
||||||
@ -855,7 +861,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
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *func_tokens[] = {
|
static char *func_tokens[] = {
|
||||||
@ -864,6 +871,8 @@ static char *func_tokens[] = {
|
|||||||
"BPRM_CHECK",
|
"BPRM_CHECK",
|
||||||
"MODULE_CHECK",
|
"MODULE_CHECK",
|
||||||
"FIRMWARE_CHECK",
|
"FIRMWARE_CHECK",
|
||||||
|
"KEXEC_KERNEL_CHECK",
|
||||||
|
"KEXEC_INITRAMFS_CHECK",
|
||||||
"POST_SETATTR"
|
"POST_SETATTR"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -929,6 +938,12 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
|
|||||||
case POST_SETATTR:
|
case POST_SETATTR:
|
||||||
seq_printf(m, pt(Opt_func), ft(func_post));
|
seq_printf(m, pt(Opt_func), ft(func_post));
|
||||||
break;
|
break;
|
||||||
|
case KEXEC_KERNEL_CHECK:
|
||||||
|
seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
|
||||||
|
break;
|
||||||
|
case KEXEC_INITRAMFS_CHECK:
|
||||||
|
seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
|
||||||
|
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user