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

Reply via email to