Add support for measuring/appraising the initramfs being kexec'ed. This patch extends the existing ima_hooks enumeration by defining a new enumeration named ima_read_hooks. Callers that read a file into a buffer and want to verify the integrity of the file should be included in the ima_read_hooks enumeration.
This patch defines ima_read_hooks and INITRAMFS_CHECK. Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com> --- Documentation/ABI/testing/ima_policy | 2 +- include/linux/ima.h | 8 ++++++-- kernel/kexec_file.c | 10 +++++++--- security/integrity/ima/ima.h | 3 ++- security/integrity/ima/ima_appraise.c | 3 +++ security/integrity/ima/ima_main.c | 5 +++-- security/integrity/ima/ima_policy.c | 10 ++++++++-- 7 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 5ae0be1..e80f767 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -26,7 +26,7 @@ Description: option: [[appraise_type=]] [permit_directio] base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] - [FIRMWARE_CHECK] [KEXEC_CHECK] + [FIRMWARE_CHECK] [KEXEC_CHECK] [INITRAMFS_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value diff --git a/include/linux/ima.h b/include/linux/ima.h index 244452b..3f8d130 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -13,6 +13,8 @@ #include <linux/fs.h> struct linux_binprm; +enum ima_read_hooks { KEXEC_CHECK = 1, INITRAMFS_CHECK, IMA_MAX_READ_CHECK}; + #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask, int opened); @@ -20,7 +22,8 @@ extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_module_check(struct file *file); extern int ima_fw_from_file(struct file *file, char *buf, size_t size); -extern int ima_read_file_from_fd(int fd, void **buf, size_t *size); +extern int ima_read_file_from_fd(int fd, enum ima_read_hooks func, + void **buf, size_t *size); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -53,7 +56,8 @@ static inline int ima_fw_from_file(struct file *file, char *buf, size_t size) return 0; } -static inline int ima_read_file_from_fd(int fd, void **buf, size_t *size) +static inline int ima_read_file_from_fd(int fd, enum ima_read_hooks func, + void **buf, size_t *size) { return -EOPNOTSUPP; } diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index fd703b8..0fb67cb 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -182,7 +182,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, int ret = 0; void *ldata; - ret = ima_read_file_from_fd(kernel_fd, &image->kernel_buf, + ret = ima_read_file_from_fd(kernel_fd, KEXEC_CHECK, &image->kernel_buf, &image->kernel_buf_len); if (ret == -EOPNOTSUPP) ret = copy_file_from_fd(kernel_fd, &image->kernel_buf, @@ -207,8 +207,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, #endif /* It is possible that there no initramfs is being loaded */ if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { - ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, - &image->initrd_buf_len); + ret = ima_read_file_from_fd(initrd_fd, INITRAMFS_CHECK, + &image->initrd_buf, + &image->initrd_buf_len); + if (ret == -EOPNOTSUPP) + ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, + &image->initrd_buf_len); if (ret) goto out; } diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 3389bb3..3337d14 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -20,6 +20,7 @@ #include <linux/types.h> #include <linux/crypto.h> #include <linux/security.h> +#include <linux/ima.h> #include <linux/hash.h> #include <linux/tpm.h> #include <linux/audit.h> @@ -159,7 +160,7 @@ void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(struct path *path, char **pathbuf); /* IMA policy related functions */ -enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, KEXEC_CHECK, POST_SETATTR }; +enum ima_hooks { FILE_CHECK = IMA_MAX_READ_CHECK, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR}; int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, int flags); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 07bc4e4..e58df45 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -79,6 +79,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, case FIRMWARE_CHECK: return iint->ima_firmware_status; case KEXEC_CHECK: + case INITRAMFS_CHECK: return iint->ima_read_status; case FILE_CHECK: default: @@ -103,6 +104,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, iint->ima_firmware_status = status; break; case KEXEC_CHECK: + case INITRAMFS_CHECK: iint->ima_read_status = status; break; case FILE_CHECK: @@ -128,6 +130,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED); break; case KEXEC_CHECK: + case INITRAMFS_CHECK: iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED); break; case FILE_CHECK: diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index d7e04bb..40c80a2 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -375,7 +375,8 @@ int ima_fw_from_file(struct file *file, char *buf, size_t size) return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, NULL, 0); } -int ima_read_file_from_fd(int fd, void **buf, size_t *buf_len) +int ima_read_file_from_fd(int fd, enum ima_read_hooks func, + void **buf, size_t *buf_len) { struct fd f = fdget(fd); int ret; @@ -383,7 +384,7 @@ int ima_read_file_from_fd(int fd, void **buf, size_t *buf_len) if (!f.file) return -EBADF; - ret = ima_read_and_process_file(f.file, KEXEC_CHECK, buf, buf_len); + ret = ima_read_and_process_file(f.file, func, buf, buf_len); fdput(f); return ret; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4e5aec9..a1f2eb3 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -50,7 +50,10 @@ struct ima_rule_entry { struct list_head list; int action; unsigned int flags; - enum ima_hooks func; + union { + enum ima_hooks func; + enum ima_read_hooks read_func; + }; int mask; unsigned long fsmagic; u8 fsuuid[16]; @@ -305,6 +308,7 @@ static int get_subaction(struct ima_rule_entry *rule, int func) case FIRMWARE_CHECK: return IMA_FIRMWARE_APPRAISE; case KEXEC_CHECK: + case INITRAMFS_CHECK: return IMA_READ_APPRAISE; case FILE_CHECK: default: @@ -582,7 +586,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) else if (strcmp(args[0].from, "BPRM_CHECK") == 0) entry->func = BPRM_CHECK; else if (strcmp(args[0].from, "KEXEC_CHECK") == 0) - entry->func = KEXEC_CHECK; + entry->read_func = KEXEC_CHECK; + else if (strcmp(args[0].from, "INITRAMFS_CHECK") == 0) + entry->read_func = INITRAMFS_CHECK; else result = -EINVAL; if (!result) -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html