ima_process_measurements() reads and calculates the file's hash, only
if the file is in policy.  When a file is read by the kernel, the file
contents need to be loaded into memory regardless of the policy.

This patch defines a new IMA hook named ima_read_and_process_file() to
load and, at the same time, hash a file.  After reading and hashing the
file, ima_read_and_process_file() calls ima_process_measurement() with
the file hash.  If the file is in policy, an iint is created with the
hash value.

This patch defines two new policy hooks named KEXEC_CHECK and
INITRAMFS_CHECK.  Based on policy, the kexec image and initramfs files
are measured/appraised.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy      |  2 +-
 include/linux/ima.h                       | 12 +++++++
 kernel/kexec_file.c                       | 28 +++++++++-------
 security/integrity/iint.c                 |  1 +
 security/integrity/ima/ima.h              |  8 +++--
 security/integrity/ima/ima_api.c          | 36 ++++++++++++++++++++-
 security/integrity/ima/ima_appraise.c     | 11 +++++++
 security/integrity/ima/ima_crypto.c       | 54 ++++++++++++++++++++-----------
 security/integrity/ima/ima_main.c         | 44 +++++++++++++++++++++----
 security/integrity/ima/ima_policy.c       | 34 +++++++++++++++----
 security/integrity/ima/ima_template_lib.c |  2 +-
 security/integrity/integrity.h            |  7 ++--
 12 files changed, 191 insertions(+), 48 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 0a378a8..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]
+                               [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 120ccc5..5d83ecf 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,6 +22,9 @@ 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_and_process_file(struct file *file,
+                                    enum ima_read_hooks read_func,
+                                    void *buf, size_t size);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -52,6 +57,13 @@ static inline int ima_fw_from_file(struct file *file, char 
*buf, size_t size)
        return 0;
 }
 
+static inline int ima_read_and_process_file(struct file *file,
+                                           enum ima_read_hooks read_func,
+                                           void *buf, size_t size)
+{
+       return -EOPNOTSUPP;
+}
+
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index b70ada0..18c4a84 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -18,6 +18,7 @@
 #include <linux/kexec.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
+#include <linux/ima.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <linux/syscalls.h>
@@ -33,7 +34,8 @@ size_t __weak kexec_purgatory_size = 0;
 
 static int kexec_calculate_store_digests(struct kimage *image);
 
-static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
+static int copy_file_from_fd(int fd, enum ima_read_hooks read_func,
+                            void **buf, unsigned long *buf_len)
 {
        struct fd f = fdget(fd);
        int ret;
@@ -65,14 +67,17 @@ static int copy_file_from_fd(int fd, void **buf, unsigned 
long *buf_len)
                goto out;
        }
 
+       ret = ima_read_and_process_file(f.file, read_func, *buf, stat.size);
+       if (ret != -EOPNOTSUPP)
+               goto out_free;
+
        pos = 0;
        while (pos < stat.size) {
                bytes = kernel_read(f.file, pos, (char *)(*buf) + pos,
                                    stat.size - pos);
                if (bytes < 0) {
-                       vfree(*buf);
                        ret = bytes;
-                       goto out;
+                       goto out_free;
                }
 
                if (bytes == 0)
@@ -80,13 +85,13 @@ static int copy_file_from_fd(int fd, void **buf, unsigned 
long *buf_len)
                pos += bytes;
        }
 
-       if (pos != stat.size) {
+       if (pos != stat.size)
                ret = -EBADF;
+       else
+               *buf_len = pos;
+out_free:
+       if (ret < 0)
                vfree(*buf);
-               goto out;
-       }
-
-       *buf_len = pos;
 out:
        fdput(f);
        return ret;
@@ -181,8 +186,8 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
        int ret = 0;
        void *ldata;
 
-       ret = copy_file_from_fd(kernel_fd, &image->kernel_buf,
-                               &image->kernel_buf_len);
+       ret = copy_file_from_fd(kernel_fd, KEXEC_CHECK,
+                               &image->kernel_buf, &image->kernel_buf_len);
        if (ret)
                return ret;
 
@@ -204,7 +209,8 @@ 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,
+               ret = copy_file_from_fd(initrd_fd, INITRAMFS_CHECK,
+                                       &image->initrd_buf,
                                        &image->initrd_buf_len);
                if (ret)
                        goto out;
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 54b51a4..8a45576 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -158,6 +158,7 @@ static void init_once(void *foo)
        iint->ima_mmap_status = INTEGRITY_UNKNOWN;
        iint->ima_bprm_status = INTEGRITY_UNKNOWN;
        iint->ima_module_status = INTEGRITY_UNKNOWN;
+       iint->ima_read_status = INTEGRITY_UNKNOWN;
        iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 9ebfec1..8dc9077 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>
@@ -106,7 +107,8 @@ int ima_fs_init(void);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
                           const char *op, struct inode *inode,
                           const unsigned char *filename);
-int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash,
+                      void *buf, unsigned long buf_len);
 int ima_calc_field_array_hash(struct ima_field_data *field_data,
                              struct ima_template_desc *desc, int num_fields,
                              struct ima_digest_data *hash);
@@ -142,6 +144,8 @@ int ima_get_action(struct inode *inode, int mask, int 
function);
 int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
                            struct file *file, enum hash_algo algo);
+int ima_collected_measurement(struct integrity_iint_cache *iint,
+                           struct file *file, struct ima_digest_data *hash);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
                           const unsigned char *filename,
                           struct evm_ima_xattr_data *xattr_value,
@@ -156,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, 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_api.c b/security/integrity/ima/ima_api.c
index e7c7a5d..9559e6d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -210,7 +210,7 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
 
                hash.hdr.algo = algo;
 
-               result = ima_calc_file_hash(file, &hash.hdr);
+               result = ima_calc_file_hash(file, &hash.hdr, NULL, 0);
                if (!result) {
                        int length = sizeof(hash.hdr) + hash.hdr.length;
                        void *tmpbuf = krealloc(iint->ima_hash, length,
@@ -233,6 +233,40 @@ out:
 }
 
 /*
+ * ima_collected_measurement - save the "collected" file hash
+ *
+ * The file hash has already been "collected".  Save the file hash
+ * in the iint and clear the measured/appraised flags.
+ */
+int ima_collected_measurement(struct integrity_iint_cache *iint,
+                             struct file *file, struct ima_digest_data *hash)
+{
+       const char *audit_cause = "failed";
+       const char *filename = file->f_path.dentry->d_name.name;
+       int length = sizeof(struct ima_digest_data) + hash->length;
+       int result = -ENOMEM;
+       void *tmpbuf = krealloc(iint->ima_hash, length, GFP_KERNEL);
+
+       if (!tmpbuf)
+               goto out;
+
+       iint->ima_hash = tmpbuf;
+       memcpy(iint->ima_hash, hash, length);
+       iint->version = file_inode(file)->i_version;
+       iint->flags &= ~(IMA_MEASURED | IMA_AUDITED| IMA_READ_APPRAISED);
+       iint->flags |= IMA_COLLECTED;
+       result = 0;
+
+out:
+       if (result)
+               integrity_audit_msg(AUDIT_INTEGRITY_DATA,
+                                   d_inode(file->f_path.dentry),
+                                   filename, "collected_data", audit_cause,
+                                   result, 0);
+       return result;
+}
+
+/*
  * ima_store_measurement - store file measurement
  *
  * Create an "ima" template and then store the template by calling
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 9c2b46b..e58df45 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -78,6 +78,9 @@ enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache *iint,
                return iint->ima_module_status;
        case FIRMWARE_CHECK:
                return iint->ima_firmware_status;
+       case KEXEC_CHECK:
+       case INITRAMFS_CHECK:
+               return iint->ima_read_status;
        case FILE_CHECK:
        default:
                return iint->ima_file_status;
@@ -100,6 +103,10 @@ static void ima_set_cache_status(struct 
integrity_iint_cache *iint,
        case FIRMWARE_CHECK:
                iint->ima_firmware_status = status;
                break;
+       case KEXEC_CHECK:
+       case INITRAMFS_CHECK:
+               iint->ima_read_status = status;
+               break;
        case FILE_CHECK:
        default:
                iint->ima_file_status = status;
@@ -122,6 +129,10 @@ static void ima_cache_flags(struct integrity_iint_cache 
*iint, int func)
        case FIRMWARE_CHECK:
                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:
        default:
                iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fb30ce4..cc0da02 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -352,10 +352,11 @@ static int ima_calc_file_ahash(struct file *file, struct 
ima_digest_data *hash)
 
 static int ima_calc_file_hash_tfm(struct file *file,
                                  struct ima_digest_data *hash,
+                                 void *buf, unsigned long buf_len,
                                  struct crypto_shash *tfm)
 {
-       loff_t i_size, offset = 0;
-       char *rbuf;
+       loff_t i_size = buf_len, offset = 0;
+       char *rbuf = buf;
        int rc, read = 0;
        SHASH_DESC_ON_STACK(shash, tfm);
 
@@ -368,14 +369,16 @@ static int ima_calc_file_hash_tfm(struct file *file,
        if (rc != 0)
                return rc;
 
-       i_size = i_size_read(file_inode(file));
+       if (!buf) {
+               i_size = i_size_read(file_inode(file));
 
-       if (i_size == 0)
-               goto out;
+               if (i_size == 0)
+                       goto out;
 
-       rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!rbuf)
-               return -ENOMEM;
+               rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+               if (!rbuf)
+                       return -ENOMEM;
+       }
 
        if (!(file->f_mode & FMODE_READ)) {
                file->f_mode |= FMODE_READ;
@@ -383,31 +386,42 @@ static int ima_calc_file_hash_tfm(struct file *file,
        }
 
        while (offset < i_size) {
-               int rbuf_len;
+               int rbuf_len, len = buf ? buf_len : PAGE_SIZE;
 
-               rbuf_len = integrity_kernel_read(file, offset, rbuf, PAGE_SIZE);
+               rbuf_len = integrity_kernel_read(file, offset,
+                                                !buf ? rbuf : rbuf + offset,
+                                                len);
                if (rbuf_len < 0) {
                        rc = rbuf_len;
                        break;
                }
                if (rbuf_len == 0)
                        break;
-               offset += rbuf_len;
 
-               rc = crypto_shash_update(shash, rbuf, rbuf_len);
+               rc = crypto_shash_update(shash, !buf ? rbuf : rbuf + offset,
+                                        rbuf_len);
+               offset += rbuf_len;
                if (rc)
                        break;
        }
        if (read)
                file->f_mode &= ~FMODE_READ;
-       kfree(rbuf);
+
+       if (!buf)
+               kfree(rbuf);
 out:
        if (!rc)
                rc = crypto_shash_final(shash, hash->digest);
        return rc;
 }
 
-static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash)
+/*
+ * ima_calc_file_shash calculates a file hash.  When the caller specfies
+ * a buffer, read the file data into memory, calculating the file hash,
+ * and return the buffer.
+ */
+static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash,
+                              void *buf, unsigned long buf_len)
 {
        struct crypto_shash *tfm;
        int rc;
@@ -416,7 +430,7 @@ static int ima_calc_file_shash(struct file *file, struct 
ima_digest_data *hash)
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
-       rc = ima_calc_file_hash_tfm(file, hash, tfm);
+       rc = ima_calc_file_hash_tfm(file, hash, buf, buf_len, tfm);
 
        ima_free_tfm(tfm);
 
@@ -435,21 +449,25 @@ static int ima_calc_file_shash(struct file *file, struct 
ima_digest_data *hash)
  * If the ima.ahash_minsize parameter is not specified, this function uses
  * shash for the hash calculation.  If ahash fails, it falls back to using
  * shash.
+ *
+ * When returning the file data to the caller, use shash to calculate the
+ * file hash.
  */
-int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
+int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash,
+                      void *buf, unsigned long buf_len)
 {
        loff_t i_size;
        int rc;
 
        i_size = i_size_read(file_inode(file));
 
-       if (ima_ahash_minsize && i_size >= ima_ahash_minsize) {
+       if (ima_ahash_minsize && i_size >= ima_ahash_minsize && !buf) {
                rc = ima_calc_file_ahash(file, hash);
                if (!rc)
                        return 0;
        }
 
-       return ima_calc_file_shash(file, hash);
+       return ima_calc_file_shash(file, hash, buf, buf_len);
 }
 
 /*
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index d9fc463..b8b0b8c 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -22,6 +22,7 @@
 #include <linux/mount.h>
 #include <linux/mman.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/xattr.h>
 #include <linux/ima.h>
 
@@ -154,7 +155,7 @@ void ima_file_free(struct file *file)
 }
 
 static int process_measurement(struct file *file, int mask, int function,
-                              int opened)
+                              struct ima_digest_data *hash, int opened)
 {
        struct inode *inode = file_inode(file);
        struct integrity_iint_cache *iint = NULL;
@@ -193,6 +194,11 @@ static int process_measurement(struct file *file, int 
mask, int function,
                if (!iint)
                        goto out;
        }
+       if (hash) {
+               rc = ima_collected_measurement(iint, file, hash);
+               if (rc)
+                       goto out;
+       }
 
        if (violation_check) {
                ima_rdwr_violation_check(file, iint, action & IMA_MEASURE,
@@ -273,7 +279,7 @@ out:
 int ima_file_mmap(struct file *file, unsigned long prot)
 {
        if (file && (prot & PROT_EXEC))
-               return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0);
+               return process_measurement(file, MAY_EXEC, MMAP_CHECK, NULL, 0);
        return 0;
 }
 
@@ -292,7 +298,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
  */
 int ima_bprm_check(struct linux_binprm *bprm)
 {
-       return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0);
+       return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, NULL, 0);
 }
 
 /**
@@ -309,7 +315,7 @@ int ima_file_check(struct file *file, int mask, int opened)
 {
        return process_measurement(file,
                                   mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
-                                  FILE_CHECK, opened);
+                                  FILE_CHECK, NULL, opened);
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
@@ -332,7 +338,33 @@ int ima_module_check(struct file *file)
 #endif
                return 0;       /* We rely on module signature checking */
        }
-       return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0);
+       return process_measurement(file, MAY_EXEC, MODULE_CHECK, NULL, 0);
+}
+
+int ima_read_and_process_file(struct file *file, enum ima_read_hooks read_func,
+                             void *buf, size_t buf_len)
+{
+       struct evm_ima_xattr_data *xattr_value = NULL;
+       struct ima_template_desc *template_desc = ima_template_desc_current();
+       int xattr_len = 0;
+       struct {
+               struct ima_digest_data hdr;
+               char digest[IMA_MAX_DIGEST_SIZE];
+       } hash;
+       int ret;
+
+       template_desc = ima_template_desc_current();
+       if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
+               xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
+
+       hash.hdr.algo = ima_get_hash_algo(xattr_value, xattr_len);
+
+       ret = ima_calc_file_hash(file, &hash.hdr, buf, buf_len);
+       if (!ret)
+               ret = process_measurement(file, MAY_READ, read_func,
+                                         &hash.hdr, 0);
+       kfree(xattr_value);
+       return ret;
 }
 
 int ima_fw_from_file(struct file *file, char *buf, size_t size)
@@ -343,7 +375,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t 
size)
                        return -EACCES; /* INTEGRITY_UNKNOWN */
                return 0;
        }
-       return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0);
+       return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, NULL, 0);
 }
 
 static int __init init_ima(void)
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index ba5d2fc..6fe0ab9 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -53,7 +53,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];
@@ -303,6 +306,9 @@ static int get_subaction(struct ima_rule_entry *rule, int 
func)
                return IMA_MODULE_APPRAISE;
        case FIRMWARE_CHECK:
                return IMA_FIRMWARE_APPRAISE;
+       case KEXEC_CHECK:
+       case INITRAMFS_CHECK:
+               return IMA_READ_APPRAISE;
        case FILE_CHECK:
        default:
                return IMA_FILE_APPRAISE;
@@ -604,6 +610,10 @@ static int ima_parse_rule(char *rule, struct 
ima_rule_entry *entry)
                                entry->func = MMAP_CHECK;
                        else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
                                entry->func = BPRM_CHECK;
+                       else if (strcmp(args[0].from, "KEXEC_CHECK") == 0)
+                               entry->read_func = KEXEC_CHECK;
+                       else if (strcmp(args[0].from, "INITRAMFS_CHECK") == 0)
+                               entry->read_func = INITRAMFS_CHECK;
                        else
                                result = -EINVAL;
                        if (!result)
@@ -847,7 +857,8 @@ static char *mask_tokens[] = {
 
 enum {
        func_file = 0, func_mmap, func_bprm,
-       func_module, func_firmware, func_post
+       func_module, func_firmware, func_post,
+       func_kexec, func_initramfs
 };
 
 static char *func_tokens[] = {
@@ -856,7 +867,9 @@ static char *func_tokens[] = {
        "BPRM_CHECK",
        "MODULE_CHECK",
        "FIRMWARE_CHECK",
-       "POST_SETATTR"
+       "POST_SETATTR",
+       "KEXEC_CHECK",
+       "INITRAMFS_CHECK",
 };
 
 void *ima_policy_start(struct seq_file *m, loff_t *pos)
@@ -937,9 +950,18 @@ int ima_policy_show(struct seq_file *m, void *v)
                        seq_printf(m, pt(Opt_func), ft(func_post));
                        break;
                default:
-                       snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
-                       seq_printf(m, pt(Opt_func), tbuf);
-                       break;
+                       switch (entry->read_func) {
+                       case KEXEC_CHECK:
+                               seq_printf(m, pt(Opt_func), ft(func_kexec));
+                               break;
+                       case INITRAMFS_CHECK:
+                               seq_printf(m, pt(Opt_func), ft(func_initramfs));
+                               break;
+                       default:
+                               snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
+                               seq_printf(m, pt(Opt_func), tbuf);
+                               break;
+                       }
                }
                seq_puts(m, " ");
        }
diff --git a/security/integrity/ima/ima_template_lib.c 
b/security/integrity/ima/ima_template_lib.c
index f9bae04..d0a155a 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -224,7 +224,7 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
        inode = file_inode(event_data->file);
        hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
            ima_hash_algo : HASH_ALGO_SHA1;
-       result = ima_calc_file_hash(event_data->file, &hash.hdr);
+       result = ima_calc_file_hash(event_data->file, &hash.hdr, NULL, 0);
        if (result) {
                integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
                                    event_data->filename, "collect_data",
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 5413f22..645d5be 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -49,12 +49,14 @@
 #define IMA_MODULE_APPRAISED   0x00008000
 #define IMA_FIRMWARE_APPRAISE  0x00010000
 #define IMA_FIRMWARE_APPRAISED 0x00020000
+#define IMA_READ_APPRAISE      0x00040000
+#define IMA_READ_APPRAISED     0x00080000
 #define IMA_APPRAISE_SUBMASK   (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
                                 IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \
-                                IMA_FIRMWARE_APPRAISE)
+                                IMA_FIRMWARE_APPRAISE | IMA_READ_APPRAISE)
 #define IMA_APPRAISED_SUBMASK  (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \
                                 IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \
-                                IMA_FIRMWARE_APPRAISED)
+                                IMA_FIRMWARE_APPRAISED | IMA_READ_APPRAISED)
 
 enum evm_ima_xattr_type {
        IMA_XATTR_DIGEST = 0x01,
@@ -111,6 +113,7 @@ struct integrity_iint_cache {
        enum integrity_status ima_bprm_status:4;
        enum integrity_status ima_module_status:4;
        enum integrity_status ima_firmware_status:4;
+       enum integrity_status ima_read_status:4;
        enum integrity_status evm_status:4;
        struct ima_digest_data *ima_hash;
 };
-- 
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