Merge tag 'integrity-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Feb 2023 20:36:25 +0000 (12:36 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Feb 2023 20:36:25 +0000 (12:36 -0800)
Pull integrity update from Mimi Zohar:
 "One doc and one code cleanup, and two bug fixes"

* tag 'integrity-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
  ima: Introduce MMAP_CHECK_REQPROT hook
  ima: Align ima_file_mmap() parameters with mmap_file LSM hook
  evm: call dump_security_xattr() in all cases to remove code duplication
  ima: fix ima_delete_rules() kernel-doc warning
  ima: return IMA digest value only when IMA_COLLECTED flag is set
  ima: fix error handling logic when file measurement failed

Documentation/ABI/testing/ima_policy
include/linux/ima.h
security/integrity/evm/evm_crypto.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/security.c

index db17fc8a0c9f6e3416631a9804efce98bc17c2c4..49db0ff288e550155edb1520648d3e31d189b4f0 100644 (file)
@@ -35,7 +35,7 @@ Description:
                                [FIRMWARE_CHECK]
                                [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
                                [KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
-                               [SETXATTR_CHECK]
+                               [SETXATTR_CHECK][MMAP_CHECK_REQPROT]
                        mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
                               [[^]MAY_EXEC]
                        fsmagic:= hex value
index 172b113a98642d11f96dafa1cd623e9a3d8c2f81..86b57757c7b1004abc4d122e0fd555d739678fad 100644 (file)
@@ -21,7 +21,8 @@ extern int ima_file_check(struct file *file, int mask);
 extern void ima_post_create_tmpfile(struct mnt_idmap *idmap,
                                    struct inode *inode);
 extern void ima_file_free(struct file *file);
-extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern int ima_file_mmap(struct file *file, unsigned long reqprot,
+                        unsigned long prot, unsigned long flags);
 extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot);
 extern int ima_load_data(enum kernel_load_data_id id, bool contents);
 extern int ima_post_load_data(char *buf, loff_t size,
@@ -76,7 +77,8 @@ static inline void ima_file_free(struct file *file)
        return;
 }
 
-static inline int ima_file_mmap(struct file *file, unsigned long prot)
+static inline int ima_file_mmap(struct file *file, unsigned long reqprot,
+                               unsigned long prot, unsigned long flags)
 {
        return 0;
 }
index 52b811da6989cbd69c18f636345fbca1517a17e5..033804f5a5f20daeceb048797e0094a3849d8d45 100644 (file)
@@ -183,8 +183,8 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
  * Dump large security xattr values as a continuous ascii hexademical string.
  * (pr_debug is limited to 64 bytes.)
  */
-static void dump_security_xattr(const char *prefix, const void *src,
-                               size_t count)
+static void dump_security_xattr_l(const char *prefix, const void *src,
+                                 size_t count)
 {
 #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
        char *asciihex, *p;
@@ -200,6 +200,16 @@ static void dump_security_xattr(const char *prefix, const void *src,
 #endif
 }
 
+static void dump_security_xattr(const char *name, const char *value,
+                               size_t value_len)
+{
+       if (value_len < 64)
+               pr_debug("%s: (%zu) [%*phN]\n", name, value_len,
+                        (int)value_len, value);
+       else
+               dump_security_xattr_l(name, value, value_len);
+}
+
 /*
  * Calculate the HMAC value across the set of protected security xattrs.
  *
@@ -254,15 +264,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                        if (is_ima)
                                ima_present = true;
 
-                       if (req_xattr_value_len < 64)
-                               pr_debug("%s: (%zu) [%*phN]\n", req_xattr_name,
-                                        req_xattr_value_len,
-                                        (int)req_xattr_value_len,
-                                        req_xattr_value);
-                       else
-                               dump_security_xattr(req_xattr_name,
-                                                   req_xattr_value,
-                                                   req_xattr_value_len);
+                       dump_security_xattr(req_xattr_name,
+                                           req_xattr_value,
+                                           req_xattr_value_len);
                        continue;
                }
                size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name,
@@ -286,12 +290,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                if (is_ima)
                        ima_present = true;
 
-               if (xattr_size < 64)
-                       pr_debug("%s: (%zu) [%*phN]", xattr->name, xattr_size,
-                                (int)xattr_size, xattr_value);
-               else
-                       dump_security_xattr(xattr->name, xattr_value,
-                                           xattr_size);
+               dump_security_xattr(xattr->name, xattr_value, xattr_size);
        }
        hmac_add_misc(desc, inode, type, data->digest);
 
index d8530e7225151f4d960d47f5ab48298adf5fe70f..c29db699c996e5801177f234e12da0e45e4b9658 100644 (file)
@@ -190,6 +190,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
        hook(NONE, none)                                \
        hook(FILE_CHECK, file)                          \
        hook(MMAP_CHECK, mmap)                          \
+       hook(MMAP_CHECK_REQPROT, mmap_reqprot)          \
        hook(BPRM_CHECK, bprm)                          \
        hook(CREDS_CHECK, creds)                        \
        hook(POST_SETATTR, post_setattr)                \
index 9345fd66f5b8e9602a89c9581e63ffb0be20d155..d3662f4acadc1d355624a972af2d300f0ccc0231 100644 (file)
@@ -179,7 +179,8 @@ err_out:
  *             subj=, obj=, type=, func=, mask=, fsmagic=
  *     subj,obj, and type: are LSM specific.
  *     func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
- *     | KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA
+ *     | KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA | SETXATTR_CHECK
+ *     | MMAP_CHECK_REQPROT
  *     mask: contains the permission mask
  *     fsmagic: hex value
  *
@@ -292,7 +293,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
                result = ima_calc_file_hash(file, &hash.hdr);
        }
 
-       if (result == -ENOMEM)
+       if (result && result != -EBADF && result != -EINVAL)
                goto out;
 
        length = sizeof(hash.hdr) + hash.hdr.length;
index 555342d337f967f4a5011c06f09573f60338b10e..491c1aca0b1ce52453bc068ba4566aa1c957a9e3 100644 (file)
@@ -111,6 +111,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
 {
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                return iint->ima_mmap_status;
        case BPRM_CHECK:
                return iint->ima_bprm_status;
@@ -131,6 +132,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
 {
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                iint->ima_mmap_status = status;
                break;
        case BPRM_CHECK:
@@ -155,6 +157,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
 {
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
                break;
        case BPRM_CHECK:
index 358578267feaa448aaa2598ec3f9c8b1cb93a7fb..d66a0a36415e8cb495162e39521abdd559c05141 100644 (file)
@@ -89,7 +89,8 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file,
        struct inode *inode;
        int rc = 0;
 
-       if ((func == MMAP_CHECK) && mapping_writably_mapped(file->f_mapping)) {
+       if ((func == MMAP_CHECK || func == MMAP_CHECK_REQPROT) &&
+           mapping_writably_mapped(file->f_mapping)) {
                rc = -ETXTBSY;
                inode = file_inode(file);
 
@@ -227,7 +228,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
        action = ima_get_action(file_mnt_idmap(file), inode, cred, secid,
                                mask, func, &pcr, &template_desc, NULL,
                                &allowed_algos);
-       violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
+       violation_check = ((func == FILE_CHECK || func == MMAP_CHECK ||
+                           func == MMAP_CHECK_REQPROT) &&
                           (ima_policy_flag & IMA_MEASURE));
        if (!action && !violation_check)
                return 0;
@@ -337,7 +339,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
        hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
 
        rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig);
-       if (rc == -ENOMEM)
+       if (rc != 0 && rc != -EBADF && rc != -EINVAL)
                goto out_locked;
 
        if (!pathbuf)   /* ima_rdwr_violation possibly pre-fetched */
@@ -397,7 +399,9 @@ out:
 /**
  * ima_file_mmap - based on policy, collect/store measurement.
  * @file: pointer to the file to be measured (May be NULL)
- * @prot: contains the protection that will be applied by the kernel.
+ * @reqprot: protection requested by the application
+ * @prot: protection that will be applied by the kernel
+ * @flags: operational flags
  *
  * Measure files being mmapped executable based on the ima_must_measure()
  * policy decision.
@@ -405,15 +409,27 @@ out:
  * On success return 0.  On integrity appraisal error, assuming the file
  * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
  */
-int ima_file_mmap(struct file *file, unsigned long prot)
+int ima_file_mmap(struct file *file, unsigned long reqprot,
+                 unsigned long prot, unsigned long flags)
 {
        u32 secid;
+       int ret;
 
-       if (file && (prot & PROT_EXEC)) {
-               security_current_getsecid_subj(&secid);
+       if (!file)
+               return 0;
+
+       security_current_getsecid_subj(&secid);
+
+       if (reqprot & PROT_EXEC) {
+               ret = process_measurement(file, current_cred(), secid, NULL,
+                                         0, MAY_EXEC, MMAP_CHECK_REQPROT);
+               if (ret)
+                       return ret;
+       }
+
+       if (prot & PROT_EXEC)
                return process_measurement(file, current_cred(), secid, NULL,
                                           0, MAY_EXEC, MMAP_CHECK);
-       }
 
        return 0;
 }
@@ -454,6 +470,10 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
        action = ima_get_action(file_mnt_idmap(vma->vm_file), inode,
                                current_cred(), secid, MAY_EXEC, MMAP_CHECK,
                                &pcr, &template, NULL, NULL);
+       action |= ima_get_action(file_mnt_idmap(vma->vm_file), inode,
+                                current_cred(), secid, MAY_EXEC,
+                                MMAP_CHECK_REQPROT, &pcr, &template, NULL,
+                                NULL);
 
        /* Is the mmap'ed file in policy? */
        if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
@@ -563,7 +583,7 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
         * ima_file_hash can be called when ima_collect_measurement has still
         * not been called, we might not always have a hash.
         */
-       if (!iint->ima_hash) {
+       if (!iint->ima_hash || !(iint->flags & IMA_COLLECTED)) {
                mutex_unlock(&iint->mutex);
                return -EOPNOTSUPP;
        }
index fc128a6b4abe31247550d4979d793b2090d88a83..3ca8b7348c2e45ffc3cc607f8d4237ab50d8fc9c 100644 (file)
@@ -697,6 +697,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
 
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                return IMA_MMAP_APPRAISE;
        case BPRM_CHECK:
                return IMA_BPRM_APPRAISE;
@@ -1266,6 +1267,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
        case NONE:
        case FILE_CHECK:
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
        case BPRM_CHECK:
        case CREDS_CHECK:
        case POST_SETATTR:
@@ -1504,6 +1506,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
                                || (strcmp(args[0].from, "MMAP_CHECK") == 0))
                                entry->func = MMAP_CHECK;
+                       else if ((strcmp(args[0].from, "MMAP_CHECK_REQPROT") == 0))
+                               entry->func = MMAP_CHECK_REQPROT;
                        else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
                                entry->func = BPRM_CHECK;
                        else if (strcmp(args[0].from, "CREDS_CHECK") == 0)
@@ -1955,7 +1959,8 @@ ssize_t ima_parse_add_rule(char *rule)
 }
 
 /**
- * ima_delete_rules() called to cleanup invalid in-flight policy.
+ * ima_delete_rules() - called to cleanup invalid in-flight policy.
+ *
  * We don't need locking as we operate on the temp list, which is
  * different from the active one.  There is also only one user of
  * ima_delete_rules() at a time.
index 4e1150c44ab78f5413808b66631ee3984b16fb4e..cf6cc576736f3dbb1d3ad21cf3def26801ec52d4 100644 (file)
@@ -1661,12 +1661,13 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
 int security_mmap_file(struct file *file, unsigned long prot,
                        unsigned long flags)
 {
+       unsigned long prot_adj = mmap_prot(file, prot);
        int ret;
-       ret = call_int_hook(mmap_file, 0, file, prot,
-                                       mmap_prot(file, prot), flags);
+
+       ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags);
        if (ret)
                return ret;
-       return ima_file_mmap(file, prot);
+       return ima_file_mmap(file, prot, prot_adj, flags);
 }
 
 int security_mmap_addr(unsigned long addr)