]> Git Repo - linux.git/commitdiff
Merge tag 'integrity-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar...
authorLinus Torvalds <[email protected]>
Wed, 22 Feb 2023 20:36:25 +0000 (12:36 -0800)
committerLinus Torvalds <[email protected]>
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

1  2 
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

diff --combined include/linux/ima.h
index 172b113a98642d11f96dafa1cd623e9a3d8c2f81,d79fee67235eeb11f25274eeccb2322eb771da97..86b57757c7b1004abc4d122e0fd555d739678fad
@@@ -18,10 -18,11 +18,11 @@@ struct linux_binprm
  extern enum hash_algo ima_get_current_hash_algo(void);
  extern int ima_bprm_check(struct linux_binprm *bprm);
  extern int ima_file_check(struct file *file, int mask);
 -extern void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
 +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,
@@@ -30,7 -31,7 +31,7 @@@ extern int ima_read_file(struct file *f
                         bool contents);
  extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
                              enum kernel_read_file_id id);
 -extern void ima_post_path_mknod(struct user_namespace *mnt_userns,
 +extern void ima_post_path_mknod(struct mnt_idmap *idmap,
                                struct dentry *dentry);
  extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
  extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size);
@@@ -66,7 -67,7 +67,7 @@@ static inline int ima_file_check(struc
        return 0;
  }
  
 -static inline void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
 +static inline void ima_post_create_tmpfile(struct mnt_idmap *idmap,
                                           struct inode *inode)
  {
  }
@@@ -76,7 -77,8 +77,8 @@@ static inline void ima_file_free(struc
        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;
  }
@@@ -111,7 -113,7 +113,7 @@@ static inline int ima_post_read_file(st
        return 0;
  }
  
 -static inline void ima_post_path_mknod(struct user_namespace *mnt_userns,
 +static inline void ima_post_path_mknod(struct mnt_idmap *idmap,
                                       struct dentry *dentry)
  {
        return;
@@@ -183,18 -185,18 +185,18 @@@ static inline void ima_post_key_create_
  
  #ifdef CONFIG_IMA_APPRAISE
  extern bool is_ima_appraise_enabled(void);
 -extern void ima_inode_post_setattr(struct user_namespace *mnt_userns,
 +extern void ima_inode_post_setattr(struct mnt_idmap *idmap,
                                   struct dentry *dentry);
  extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
                       const void *xattr_value, size_t xattr_value_len);
 -extern int ima_inode_set_acl(struct user_namespace *mnt_userns,
 +extern int ima_inode_set_acl(struct mnt_idmap *idmap,
                             struct dentry *dentry, const char *acl_name,
                             struct posix_acl *kacl);
 -static inline int ima_inode_remove_acl(struct user_namespace *mnt_userns,
 +static inline int ima_inode_remove_acl(struct mnt_idmap *idmap,
                                       struct dentry *dentry,
                                       const char *acl_name)
  {
 -      return ima_inode_set_acl(mnt_userns, dentry, acl_name, NULL);
 +      return ima_inode_set_acl(idmap, dentry, acl_name, NULL);
  }
  extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name);
  #else
@@@ -203,7 -205,7 +205,7 @@@ static inline bool is_ima_appraise_enab
        return 0;
  }
  
 -static inline void ima_inode_post_setattr(struct user_namespace *mnt_userns,
 +static inline void ima_inode_post_setattr(struct mnt_idmap *idmap,
                                          struct dentry *dentry)
  {
        return;
@@@ -217,7 -219,7 +219,7 @@@ static inline int ima_inode_setxattr(st
        return 0;
  }
  
 -static inline int ima_inode_set_acl(struct user_namespace *mnt_userns,
 +static inline int ima_inode_set_acl(struct mnt_idmap *idmap,
                                    struct dentry *dentry, const char *acl_name,
                                    struct posix_acl *kacl)
  {
@@@ -231,7 -233,7 +233,7 @@@ static inline int ima_inode_removexattr
        return 0;
  }
  
 -static inline int ima_inode_remove_acl(struct user_namespace *mnt_userns,
 +static inline int ima_inode_remove_acl(struct mnt_idmap *idmap,
                                       struct dentry *dentry,
                                       const char *acl_name)
  {
index 52b811da6989cbd69c18f636345fbca1517a17e5,0fe6c9cd8eab41350ed4c113a73e9a0866da3a04..033804f5a5f20daeceb048797e0094a3849d8d45
@@@ -183,8 -183,8 +183,8 @@@ static void hmac_add_misc(struct shash_
   * 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;
  #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,18 -264,12 +264,12 @@@ static int evm_calc_hmac_or_hash(struc
                        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(&init_user_ns, dentry, xattr->name,
 +              size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name,
                                          &xattr_value, xattr_size, GFP_NOFS);
                if (size == -ENOMEM) {
                        error = -ENOMEM;
                if (size < 0)
                        continue;
  
 -              user_space_size = vfs_getxattr(&init_user_ns, dentry,
 +              user_space_size = vfs_getxattr(&nop_mnt_idmap, dentry,
                                               xattr->name, NULL, 0);
                if (user_space_size != size)
                        pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n",
                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);
  
@@@ -331,7 -330,7 +330,7 @@@ static int evm_is_immutable(struct dent
                return 1;
  
        /* Do this the hard way */
 -      rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM,
 +      rc = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, XATTR_NAME_EVM,
                                (char **)&xattr_data, 0, GFP_NOFS);
        if (rc <= 0) {
                if (rc == -ENODATA)
@@@ -376,12 -375,12 +375,12 @@@ int evm_update_evmxattr(struct dentry *
                           xattr_value_len, &data);
        if (rc == 0) {
                data.hdr.xattr.sha1.type = EVM_XATTR_HMAC;
 -              rc = __vfs_setxattr_noperm(&init_user_ns, dentry,
 +              rc = __vfs_setxattr_noperm(&nop_mnt_idmap, dentry,
                                           XATTR_NAME_EVM,
                                           &data.hdr.xattr.data[1],
                                           SHA1_DIGEST_SIZE + 1, 0);
        } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
 -              rc = __vfs_removexattr(&init_user_ns, dentry, XATTR_NAME_EVM);
 +              rc = __vfs_removexattr(&nop_mnt_idmap, dentry, XATTR_NAME_EVM);
        }
        return rc;
  }
index d8530e7225151f4d960d47f5ab48298adf5fe70f,7186769d5e138b625ce026c99100859183888dcb..c29db699c996e5801177f234e12da0e45e4b9658
@@@ -190,6 -190,7 +190,7 @@@ static inline unsigned int ima_hash_key
        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)                \
@@@ -254,7 -255,7 +255,7 @@@ static inline void ima_process_queued_k
  #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
  
  /* LIM API function definitions */
 -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_get_action(struct mnt_idmap *idmap, struct inode *inode,
                   const struct cred *cred, u32 secid, int mask,
                   enum ima_hooks func, int *pcr,
                   struct ima_template_desc **template_desc,
@@@ -268,7 -269,7 +269,7 @@@ void ima_store_measurement(struct integ
                           struct evm_ima_xattr_data *xattr_value,
                           int xattr_len, const struct modsig *modsig, int pcr,
                           struct ima_template_desc *template_desc);
 -int process_buffer_measurement(struct user_namespace *mnt_userns,
 +int process_buffer_measurement(struct mnt_idmap *idmap,
                               struct inode *inode, const void *buf, int size,
                               const char *eventname, enum ima_hooks func,
                               int pcr, const char *func_data,
@@@ -285,7 -286,7 +286,7 @@@ void ima_free_template_entry(struct ima
  const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
  
  /* IMA policy related functions */
 -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_match_policy(struct mnt_idmap *idmap, struct inode *inode,
                     const struct cred *cred, u32 secid, enum ima_hooks func,
                     int mask, int flags, int *pcr,
                     struct ima_template_desc **template_desc,
@@@ -318,7 -319,7 +319,7 @@@ int ima_appraise_measurement(enum ima_h
                             struct file *file, const unsigned char *filename,
                             struct evm_ima_xattr_data *xattr_value,
                             int xattr_len, const struct modsig *modsig);
 -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
                      int mask, enum ima_hooks func);
  void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
  enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
@@@ -346,7 -347,7 +347,7 @@@ static inline int ima_appraise_measurem
        return INTEGRITY_UNKNOWN;
  }
  
 -static inline int ima_must_appraise(struct user_namespace *mnt_userns,
 +static inline int ima_must_appraise(struct mnt_idmap *idmap,
                                    struct inode *inode, int mask,
                                    enum ima_hooks func)
  {
index 9345fd66f5b8e9602a89c9581e63ffb0be20d155,635803b0d522d05b0447fc47cac775becea711b1..d3662f4acadc1d355624a972af2d300f0ccc0231
@@@ -163,7 -163,7 +163,7 @@@ err_out
  
  /**
   * ima_get_action - appraise & measure decision based on policy.
 - * @mnt_userns:       user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @inode: pointer to the inode associated with the object being validated
   * @cred: pointer to credentials structure to validate
   * @secid: secid of the task being validated
   *            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
   *
   * Returns IMA_MEASURE, IMA_APPRAISE mask.
   *
   */
 -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_get_action(struct mnt_idmap *idmap, struct inode *inode,
                   const struct cred *cred, u32 secid, int mask,
                   enum ima_hooks func, int *pcr,
                   struct ima_template_desc **template_desc,
  
        flags &= ima_policy_flag;
  
 -      return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
 +      return ima_match_policy(idmap, inode, cred, secid, func, mask,
                                flags, pcr, template_desc, func_data,
                                allowed_algos);
  }
@@@ -292,7 -293,7 +293,7 @@@ int ima_collect_measurement(struct inte
                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,97c7d247315c2a3ce477ff9da4413b99ef758689..491c1aca0b1ce52453bc068ba4566aa1c957a9e3
@@@ -70,7 -70,7 +70,7 @@@ bool is_ima_appraise_enabled(void
   *
   * Return 1 to appraise or hash
   */
 -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
                      int mask, enum ima_hooks func)
  {
        u32 secid;
@@@ -79,7 -79,7 +79,7 @@@
                return 0;
  
        security_current_getsecid_subj(&secid);
 -      return ima_match_policy(mnt_userns, inode, current_cred(), secid,
 +      return ima_match_policy(idmap, inode, current_cred(), secid,
                                func, mask, IMA_APPRAISE | IMA_HASH, NULL,
                                NULL, NULL, NULL);
  }
@@@ -98,7 -98,7 +98,7 @@@ static int ima_fix_xattr(struct dentry 
                iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG;
                iint->ima_hash->xattr.ng.algo = algo;
        }
 -      rc = __vfs_setxattr_noperm(&init_user_ns, dentry, XATTR_NAME_IMA,
 +      rc = __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_IMA,
                                   &iint->ima_hash->xattr.data[offset],
                                   (sizeof(iint->ima_hash->xattr) - offset) +
                                   iint->ima_hash->length, 0);
@@@ -111,6 -111,7 +111,7 @@@ enum integrity_status ima_get_cache_sta
  {
        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 +132,7 @@@ static void ima_set_cache_status(struc
  {
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                iint->ima_mmap_status = status;
                break;
        case BPRM_CHECK:
@@@ -155,6 -157,7 +157,7 @@@ static void ima_cache_flags(struct inte
  {
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
                break;
        case BPRM_CHECK:
@@@ -225,7 -228,7 +228,7 @@@ int ima_read_xattr(struct dentry *dentr
  {
        int ret;
  
 -      ret = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_IMA,
 +      ret = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, XATTR_NAME_IMA,
                                 (char **)xattr_value, xattr_len, GFP_NOFS);
        if (ret == -EOPNOTSUPP)
                ret = 0;
@@@ -456,7 -459,7 +459,7 @@@ int ima_check_blacklist(struct integrit
  
                rc = is_binary_blacklisted(digest, digestsize);
                if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
 -                      process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
 +                      process_buffer_measurement(&nop_mnt_idmap, NULL, digest, digestsize,
                                                   "blacklisted-hash", NONE,
                                                   pcr, NULL, false, NULL, 0);
        }
@@@ -622,7 -625,7 +625,7 @@@ void ima_update_xattr(struct integrity_
  
  /**
   * ima_inode_post_setattr - reflect file metadata changes
 - * @mnt_userns:       user namespace of the mount the inode was found from
 + * @idmap:  idmap of the mount the inode was found from
   * @dentry: pointer to the affected dentry
   *
   * Changes to a dentry's metadata might result in needing to appraise.
   * This function is called from notify_change(), which expects the caller
   * to lock the inode's i_mutex.
   */
 -void ima_inode_post_setattr(struct user_namespace *mnt_userns,
 +void ima_inode_post_setattr(struct mnt_idmap *idmap,
                            struct dentry *dentry)
  {
        struct inode *inode = d_backing_inode(dentry);
            || !(inode->i_opflags & IOP_XATTR))
                return;
  
 -      action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR);
 +      action = ima_must_appraise(idmap, inode, MAY_ACCESS, POST_SETATTR);
        iint = integrity_iint_find(inode);
        if (iint) {
                set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
@@@ -774,7 -777,7 +777,7 @@@ int ima_inode_setxattr(struct dentry *d
        return result;
  }
  
 -int ima_inode_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
 +int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
                      const char *acl_name, struct posix_acl *kacl)
  {
        if (evm_revalidate_status(acl_name))
index 358578267feaa448aaa2598ec3f9c8b1cb93a7fb,31ab86f7e4d3001be442a9e796ad25bc54fd889e..d66a0a36415e8cb495162e39521abdd559c05141
@@@ -89,7 -89,8 +89,8 @@@ static int mmap_violation_check(enum im
        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);
  
@@@ -224,10 -225,11 +225,11 @@@ static int process_measurement(struct f
         * bitmask based on the appraise/audit/measurement policy.
         * Included is the appraise submask.
         */
 -      action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
 +      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;
        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 +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.
   * 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;
  }
@@@ -451,9 -467,13 +467,13 @@@ int ima_file_mprotect(struct vm_area_st
  
        security_current_getsecid_subj(&secid);
        inode = file_inode(vma->vm_file);
 -      action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
 +      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_user_ns(vma->vm_file), inode,
++      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 +583,7 @@@ static int __ima_inode_hash(struct inod
         * 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;
        }
@@@ -638,14 -658,14 +658,14 @@@ EXPORT_SYMBOL_GPL(ima_inode_hash)
  
  /**
   * ima_post_create_tmpfile - mark newly created tmpfile as new
 - * @mnt_userns: user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @inode: inode of the newly created tmpfile
   *
   * No measuring, appraising or auditing of newly created tmpfiles is needed.
   * Skip calling process_measurement(), but indicate which newly, created
   * tmpfiles are in policy.
   */
 -void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
 +void ima_post_create_tmpfile(struct mnt_idmap *idmap,
                             struct inode *inode)
  {
        struct integrity_iint_cache *iint;
        if (!ima_policy_flag || !S_ISREG(inode->i_mode))
                return;
  
 -      must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
 +      must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS,
                                          FILE_CHECK);
        if (!must_appraise)
                return;
  
  /**
   * ima_post_path_mknod - mark as a new inode
 - * @mnt_userns: user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @dentry: newly created dentry
   *
   * Mark files created via the mknodat syscall as new, so that the
   * file data can be written later.
   */
 -void ima_post_path_mknod(struct user_namespace *mnt_userns,
 +void ima_post_path_mknod(struct mnt_idmap *idmap,
                         struct dentry *dentry)
  {
        struct integrity_iint_cache *iint;
        if (!ima_policy_flag || !S_ISREG(inode->i_mode))
                return;
  
 -      must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
 +      must_appraise = ima_must_appraise(idmap, inode, MAY_ACCESS,
                                          FILE_CHECK);
        if (!must_appraise)
                return;
@@@ -869,7 -889,7 +889,7 @@@ int ima_post_load_data(char *buf, loff_
  
  /**
   * process_buffer_measurement - Measure the buffer or the buffer data hash
 - * @mnt_userns:       user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @inode: inode associated with the object being measured (NULL for KEY_CHECK)
   * @buf: pointer to the buffer that needs to be added to the log.
   * @size: size of buffer(in bytes).
   * has been written to the passed location but not added to a measurement entry,
   * a negative value otherwise.
   */
 -int process_buffer_measurement(struct user_namespace *mnt_userns,
 +int process_buffer_measurement(struct mnt_idmap *idmap,
                               struct inode *inode, const void *buf, int size,
                               const char *eventname, enum ima_hooks func,
                               int pcr, const char *func_data,
         */
        if (func) {
                security_current_getsecid_subj(&secid);
 -              action = ima_get_action(mnt_userns, inode, current_cred(),
 +              action = ima_get_action(idmap, inode, current_cred(),
                                        secid, 0, func, &pcr, &template,
                                        func_data, NULL);
                if (!(action & IMA_MEASURE) && !digest)
@@@ -1011,7 -1031,7 +1031,7 @@@ void ima_kexec_cmdline(int kernel_fd, c
        if (!f.file)
                return;
  
 -      process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
 +      process_buffer_measurement(file_mnt_idmap(f.file), file_inode(f.file),
                                   buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
                                   NULL, false, NULL, 0);
        fdput(f);
@@@ -1044,7 -1064,7 +1064,7 @@@ int ima_measure_critical_data(const cha
        if (!event_name || !event_label || !buf || !buf_len)
                return -ENOPARAM;
  
 -      return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len,
 +      return process_buffer_measurement(&nop_mnt_idmap, NULL, buf, buf_len,
                                          event_name, CRITICAL_DATA, 0,
                                          event_label, hash, digest,
                                          digest_len);
index fc128a6b4abe31247550d4979d793b2090d88a83,40c0769238e637294196e5dbc132fe4a09041bf7..3ca8b7348c2e45ffc3cc607f8d4237ab50d8fc9c
@@@ -552,7 -552,7 +552,7 @@@ static bool ima_match_rule_data(struct 
  /**
   * ima_match_rules - determine whether an inode matches the policy rule.
   * @rule: a pointer to a rule
 - * @mnt_userns:       user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @inode: a pointer to an inode
   * @cred: a pointer to a credentials structure for user validation
   * @secid: the secid of the task to be validated
   * Returns true on rule match, false on failure.
   */
  static bool ima_match_rules(struct ima_rule_entry *rule,
 -                          struct user_namespace *mnt_userns,
 +                          struct mnt_idmap *idmap,
                            struct inode *inode, const struct cred *cred,
                            u32 secid, enum ima_hooks func, int mask,
                            const char *func_data)
                        return false;
        }
        if ((rule->flags & IMA_FOWNER) &&
 -          !rule->fowner_op(i_uid_into_vfsuid(mnt_userns, inode),
 +          !rule->fowner_op(i_uid_into_vfsuid(idmap, inode),
                             rule->fowner))
                return false;
        if ((rule->flags & IMA_FGROUP) &&
 -          !rule->fgroup_op(i_gid_into_vfsgid(mnt_userns, inode),
 +          !rule->fgroup_op(i_gid_into_vfsgid(idmap, inode),
                             rule->fgroup))
                return false;
        for (i = 0; i < MAX_LSM_RULES; i++) {
@@@ -697,6 -697,7 +697,7 @@@ static int get_subaction(struct ima_rul
  
        switch (func) {
        case MMAP_CHECK:
+       case MMAP_CHECK_REQPROT:
                return IMA_MMAP_APPRAISE;
        case BPRM_CHECK:
                return IMA_BPRM_APPRAISE;
  
  /**
   * ima_match_policy - decision based on LSM and other conditions
 - * @mnt_userns:       user namespace of the mount the inode was found from
 + * @idmap: idmap of the mount the inode was found from
   * @inode: pointer to an inode for which the policy decision is being made
   * @cred: pointer to a credentials structure for which the policy decision is
   *        being made
   * list when walking it.  Reads are many orders of magnitude more numerous
   * than writes so ima_match_policy() is classical RCU candidate.
   */
 -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
 +int ima_match_policy(struct mnt_idmap *idmap, struct inode *inode,
                     const struct cred *cred, u32 secid, enum ima_hooks func,
                     int mask, int flags, int *pcr,
                     struct ima_template_desc **template_desc,
                if (!(entry->action & actmask))
                        continue;
  
 -              if (!ima_match_rules(entry, mnt_userns, inode, cred, secid,
 +              if (!ima_match_rules(entry, idmap, inode, cred, secid,
                                     func, mask, func_data))
                        continue;
  
@@@ -1266,6 -1267,7 +1267,7 @@@ static bool ima_validate_rule(struct im
        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 +1506,8 @@@ static int ima_parse_rule(char *rule, s
                        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 +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.
diff --combined security/security.c
index 4e1150c44ab78f5413808b66631ee3984b16fb4e,174afa4fad813280399a6974a375877a711c371f..cf6cc576736f3dbb1d3ad21cf3def26801ec52d4
@@@ -1354,7 -1354,7 +1354,7 @@@ int security_inode_permission(struct in
        return call_int_hook(inode_permission, 0, inode, mask);
  }
  
 -int security_inode_setattr(struct user_namespace *mnt_userns,
 +int security_inode_setattr(struct mnt_idmap *idmap,
                           struct dentry *dentry, struct iattr *attr)
  {
        int ret;
        ret = call_int_hook(inode_setattr, 0, dentry, attr);
        if (ret)
                return ret;
 -      return evm_inode_setattr(mnt_userns, dentry, attr);
 +      return evm_inode_setattr(idmap, dentry, attr);
  }
  EXPORT_SYMBOL_GPL(security_inode_setattr);
  
@@@ -1375,7 -1375,7 +1375,7 @@@ int security_inode_getattr(const struc
        return call_int_hook(inode_getattr, 0, path);
  }
  
 -int security_inode_setxattr(struct user_namespace *mnt_userns,
 +int security_inode_setxattr(struct mnt_idmap *idmap,
                            struct dentry *dentry, const char *name,
                            const void *value, size_t size, int flags)
  {
         * SELinux and Smack integrate the cap call,
         * so assume that all LSMs supplying this call do so.
         */
 -      ret = call_int_hook(inode_setxattr, 1, mnt_userns, dentry, name, value,
 +      ret = call_int_hook(inode_setxattr, 1, idmap, dentry, name, value,
                            size, flags);
  
        if (ret == 1)
        ret = ima_inode_setxattr(dentry, name, value, size);
        if (ret)
                return ret;
 -      return evm_inode_setxattr(mnt_userns, dentry, name, value, size);
 +      return evm_inode_setxattr(idmap, dentry, name, value, size);
  }
  
 -int security_inode_set_acl(struct user_namespace *mnt_userns,
 +int security_inode_set_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name,
                           struct posix_acl *kacl)
  {
  
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
 -      ret = call_int_hook(inode_set_acl, 0, mnt_userns, dentry, acl_name,
 +      ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name,
                            kacl);
        if (ret)
                return ret;
 -      ret = ima_inode_set_acl(mnt_userns, dentry, acl_name, kacl);
 +      ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl);
        if (ret)
                return ret;
 -      return evm_inode_set_acl(mnt_userns, dentry, acl_name, kacl);
 +      return evm_inode_set_acl(idmap, dentry, acl_name, kacl);
  }
  
 -int security_inode_get_acl(struct user_namespace *mnt_userns,
 +int security_inode_get_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name)
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
 -      return call_int_hook(inode_get_acl, 0, mnt_userns, dentry, acl_name);
 +      return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name);
  }
  
 -int security_inode_remove_acl(struct user_namespace *mnt_userns,
 +int security_inode_remove_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name)
  {
        int ret;
  
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
 -      ret = call_int_hook(inode_remove_acl, 0, mnt_userns, dentry, acl_name);
 +      ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name);
        if (ret)
                return ret;
 -      ret = ima_inode_remove_acl(mnt_userns, dentry, acl_name);
 +      ret = ima_inode_remove_acl(idmap, dentry, acl_name);
        if (ret)
                return ret;
 -      return evm_inode_remove_acl(mnt_userns, dentry, acl_name);
 +      return evm_inode_remove_acl(idmap, dentry, acl_name);
  }
  
  void security_inode_post_setxattr(struct dentry *dentry, const char *name,
@@@ -1465,7 -1465,7 +1465,7 @@@ int security_inode_listxattr(struct den
        return call_int_hook(inode_listxattr, 0, dentry);
  }
  
 -int security_inode_removexattr(struct user_namespace *mnt_userns,
 +int security_inode_removexattr(struct mnt_idmap *idmap,
                               struct dentry *dentry, const char *name)
  {
        int ret;
         * SELinux and Smack integrate the cap call,
         * so assume that all LSMs supplying this call do so.
         */
 -      ret = call_int_hook(inode_removexattr, 1, mnt_userns, dentry, name);
 +      ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name);
        if (ret == 1)
 -              ret = cap_inode_removexattr(mnt_userns, dentry, name);
 +              ret = cap_inode_removexattr(idmap, dentry, name);
        if (ret)
                return ret;
        ret = ima_inode_removexattr(dentry, name);
        if (ret)
                return ret;
 -      return evm_inode_removexattr(mnt_userns, dentry, name);
 +      return evm_inode_removexattr(idmap, dentry, name);
  }
  
  int security_inode_need_killpriv(struct dentry *dentry)
        return call_int_hook(inode_need_killpriv, 0, dentry);
  }
  
 -int security_inode_killpriv(struct user_namespace *mnt_userns,
 +int security_inode_killpriv(struct mnt_idmap *idmap,
                            struct dentry *dentry)
  {
 -      return call_int_hook(inode_killpriv, 0, mnt_userns, dentry);
 +      return call_int_hook(inode_killpriv, 0, idmap, dentry);
  }
  
 -int security_inode_getsecurity(struct user_namespace *mnt_userns,
 +int security_inode_getsecurity(struct mnt_idmap *idmap,
                               struct inode *inode, const char *name,
                               void **buffer, bool alloc)
  {
         * Only one module will provide an attribute with a given name.
         */
        hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
 -              rc = hp->hook.inode_getsecurity(mnt_userns, inode, name, buffer, alloc);
 +              rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, alloc);
                if (rc != LSM_RET_DEFAULT(inode_getsecurity))
                        return rc;
        }
@@@ -1661,12 -1661,13 +1661,13 @@@ static inline unsigned long mmap_prot(s
  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)
This page took 0.114456 seconds and 4 git commands to generate.