Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+28 -7
+1
Documentation/ABI/testing/ima_policy
··· 27 27 28 28 base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] 29 29 [FIRMWARE_CHECK] 30 + [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] 30 31 mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] 31 32 [[^]MAY_EXEC] 32 33 fsmagic:= hex value
+2
security/integrity/ima/ima.h
··· 147 147 POST_SETATTR, 148 148 MODULE_CHECK, 149 149 FIRMWARE_CHECK, 150 + KEXEC_KERNEL_CHECK, 151 + KEXEC_INITRAMFS_CHECK, 150 152 MAX_CHECK 151 153 }; 152 154
+9 -6
security/integrity/ima/ima_main.c
··· 339 339 return 0; 340 340 } 341 341 342 + static int read_idmap[READING_MAX_ID] = { 343 + [READING_FIRMWARE] = FIRMWARE_CHECK, 344 + [READING_MODULE] = MODULE_CHECK, 345 + [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, 346 + [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, 347 + }; 348 + 342 349 /** 343 350 * ima_post_read_file - in memory collect/appraise/audit measurement 344 351 * @file: pointer to the file to be measured/appraised/audit ··· 362 355 int ima_post_read_file(struct file *file, void *buf, loff_t size, 363 356 enum kernel_read_file_id read_id) 364 357 { 365 - enum ima_hooks func = FILE_CHECK; 358 + enum ima_hooks func; 366 359 367 360 if (!file && read_id == READING_FIRMWARE) { 368 361 if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && ··· 380 373 return 0; 381 374 } 382 375 383 - if (read_id == READING_FIRMWARE) 384 - func = FIRMWARE_CHECK; 385 - else if (read_id == READING_MODULE) 386 - func = MODULE_CHECK; 387 - 376 + func = read_idmap[read_id] ?: FILE_CHECK; 388 377 return process_measurement(file, buf, size, MAY_READ, func, 0); 389 378 } 390 379
+16 -1
security/integrity/ima/ima_policy.c
··· 612 612 entry->func = MMAP_CHECK; 613 613 else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 614 614 entry->func = BPRM_CHECK; 615 + else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") == 616 + 0) 617 + entry->func = KEXEC_KERNEL_CHECK; 618 + else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK") 619 + == 0) 620 + entry->func = KEXEC_INITRAMFS_CHECK; 615 621 else 616 622 result = -EINVAL; 617 623 if (!result) ··· 861 855 862 856 enum { 863 857 func_file = 0, func_mmap, func_bprm, 864 - func_module, func_firmware, func_post 858 + func_module, func_firmware, func_post, 859 + func_kexec_kernel, func_kexec_initramfs 865 860 }; 866 861 867 862 static char *func_tokens[] = { ··· 871 864 "BPRM_CHECK", 872 865 "MODULE_CHECK", 873 866 "FIRMWARE_CHECK", 867 + "KEXEC_KERNEL_CHECK", 868 + "KEXEC_INITRAMFS_CHECK", 874 869 "POST_SETATTR" 875 870 }; 876 871 ··· 937 928 break; 938 929 case POST_SETATTR: 939 930 seq_printf(m, pt(Opt_func), ft(func_post)); 931 + break; 932 + case KEXEC_KERNEL_CHECK: 933 + seq_printf(m, pt(Opt_func), ft(func_kexec_kernel)); 934 + break; 935 + case KEXEC_INITRAMFS_CHECK: 936 + seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs)); 940 937 break; 941 938 default: 942 939 snprintf(tbuf, sizeof(tbuf), "%d", func);