Merge tag 'fixes-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Apr 2021 02:32:55 +0000 (19:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Apr 2021 02:32:55 +0000 (19:32 -0700)
Pull security layer fixes from James Morris:
 "Miscellaneous minor fixes"

* tag 'fixes-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  security: commoncap: clean up kernel-doc comments
  security: commoncap: fix -Wstringop-overread warning

1  2 
security/commoncap.c

diff --combined security/commoncap.c
index 1c519c87521765a0a474100a8b4309c44f44c3c5,b088bf002db582c85e7344be2e8496a055666d24..3f810d37b71bde1eed0b63d7bc4cd6ca62833196
@@@ -50,7 -50,7 +50,7 @@@ static void warn_setuid_and_fcaps_mixed
  /**
   * cap_capable - Determine whether a task has a particular effective capability
   * @cred: The credentials to use
-  * @ns:  The user namespace in which we need the capability
+  * @targ_ns:  The user namespace in which we need the capability
   * @cap: The capability to check for
   * @opts: Bitmask of options defined in include/linux/security.h
   *
@@@ -289,7 -289,7 +289,7 @@@ int cap_capset(struct cred *new
   * affects the security markings on that inode, and if it is, should
   * inode_killpriv() be invoked or the change rejected.
   *
-  * Returns 1 if security.capability has a value, meaning inode_killpriv()
+  * Return: 1 if security.capability has a value, meaning inode_killpriv()
   * is required, 0 otherwise, meaning inode_killpriv() is not required.
   */
  int cap_inode_need_killpriv(struct dentry *dentry)
  
  /**
   * cap_inode_killpriv - Erase the security markings on an inode
 - * @dentry: The inode/dentry to alter
 + *
 + * @mnt_userns:       user namespace of the mount the inode was found from
 + * @dentry:   The inode/dentry to alter
   *
   * Erase the privilege-enhancing security markings on an inode.
   *
-  * Returns 0 if successful, -ve on error.
 + * If the inode has been found through an idmapped mount the user namespace of
 + * the vfsmount must be passed through @mnt_userns. This function will then
 + * take care to map the inode according to @mnt_userns before checking
 + * permissions. On non-idmapped mounts or if permission checking is to be
 + * performed on the raw inode simply passs init_user_ns.
 + *
+  * Return: 0 if successful, -ve on error.
   */
 -int cap_inode_killpriv(struct dentry *dentry)
 +int cap_inode_killpriv(struct user_namespace *mnt_userns, struct dentry *dentry)
  {
        int error;
  
 -      error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
 +      error = __vfs_removexattr(mnt_userns, dentry, XATTR_NAME_CAPS);
        if (error == -EOPNOTSUPP)
                error = 0;
        return error;
@@@ -374,8 -366,7 +374,8 @@@ static bool is_v3header(size_t size, co
   * by the integrity subsystem, which really wants the unconverted values -
   * so that's good.
   */
 -int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
 +int cap_inode_getsecurity(struct user_namespace *mnt_userns,
 +                        struct inode *inode, const char *name, void **buffer,
                          bool alloc)
  {
        int size, ret;
                return -EINVAL;
  
        size = sizeof(struct vfs_ns_cap_data);
 -      ret = (int) vfs_getxattr_alloc(dentry, XATTR_NAME_CAPS,
 -                               &tmpbuf, size, GFP_NOFS);
 +      ret = (int)vfs_getxattr_alloc(mnt_userns, dentry, XATTR_NAME_CAPS,
 +                                    &tmpbuf, size, GFP_NOFS);
        dput(dentry);
  
-       if (ret < 0)
+       if (ret < 0 || !tmpbuf)
                return ret;
  
        fs_ns = inode->i_sb->s_user_ns;
  
        kroot = make_kuid(fs_ns, root);
  
 +      /* If this is an idmapped mount shift the kuid. */
 +      kroot = kuid_into_mnt(mnt_userns, kroot);
 +
        /* If the root kuid maps to a valid uid in current ns, then return
         * this as a nscap. */
        mappedroot = from_kuid(current_user_ns(), kroot);
@@@ -481,33 -469,16 +481,33 @@@ out_free
        return size;
  }
  
 +/**
 + * rootid_from_xattr - translate root uid of vfs caps
 + *
 + * @value:    vfs caps value which may be modified by this function
 + * @size:     size of @ivalue
 + * @task_ns:  user namespace of the caller
 + * @mnt_userns:       user namespace of the mount the inode was found from
 + *
 + * If the inode has been found through an idmapped mount the user namespace of
 + * the vfsmount must be passed through @mnt_userns. This function will then
 + * take care to map the inode according to @mnt_userns before checking
 + * permissions. On non-idmapped mounts or if permission checking is to be
 + * performed on the raw inode simply passs init_user_ns.
 + */
  static kuid_t rootid_from_xattr(const void *value, size_t size,
 -                              struct user_namespace *task_ns)
 +                              struct user_namespace *task_ns,
 +                              struct user_namespace *mnt_userns)
  {
        const struct vfs_ns_cap_data *nscap = value;
 +      kuid_t rootkid;
        uid_t rootid = 0;
  
        if (size == XATTR_CAPS_SZ_3)
                rootid = le32_to_cpu(nscap->rootid);
  
 -      return make_kuid(task_ns, rootid);
 +      rootkid = make_kuid(task_ns, rootid);
 +      return kuid_from_mnt(mnt_userns, rootkid);
  }
  
  static bool validheader(size_t size, const struct vfs_cap_data *cap)
        return is_v2header(size, cap) || is_v3header(size, cap);
  }
  
 -/*
 +/**
 + * cap_convert_nscap - check vfs caps
 + *
 + * @mnt_userns:       user namespace of the mount the inode was found from
 + * @dentry:   used to retrieve inode to check permissions on
 + * @ivalue:   vfs caps value which may be modified by this function
 + * @size:     size of @ivalue
 + *
   * User requested a write of security.capability.  If needed, update the
   * xattr to change from v2 to v3, or to fixup the v3 rootid.
   *
-  * If all is ok, we return the new size, on error return < 0.
 + * If the inode has been found through an idmapped mount the user namespace of
 + * the vfsmount must be passed through @mnt_userns. This function will then
 + * take care to map the inode according to @mnt_userns before checking
 + * permissions. On non-idmapped mounts or if permission checking is to be
 + * performed on the raw inode simply passs init_user_ns.
 + *
+  * Return: On success, return the new size; on error, return < 0.
   */
 -int cap_convert_nscap(struct dentry *dentry, const void **ivalue, size_t size)
 +int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,
 +                    const void **ivalue, size_t size)
  {
        struct vfs_ns_cap_data *nscap;
        uid_t nsrootid;
                return -EINVAL;
        if (!validheader(size, cap))
                return -EINVAL;
 -      if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
 +      if (!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_SETFCAP))
                return -EPERM;
 -      if (size == XATTR_CAPS_SZ_2)
 +      if (size == XATTR_CAPS_SZ_2 && (mnt_userns == &init_user_ns))
                if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP))
                        /* user is privileged, just write the v2 */
                        return size;
  
 -      rootid = rootid_from_xattr(*ivalue, size, task_ns);
 +      rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns);
        if (!uid_valid(rootid))
                return -EINVAL;
  
@@@ -626,24 -583,10 +626,24 @@@ static inline int bprm_caps_from_vfs_ca
        return *effective ? ret : 0;
  }
  
 -/*
 +/**
 + * get_vfs_caps_from_disk - retrieve vfs caps from disk
 + *
 + * @mnt_userns:       user namespace of the mount the inode was found from
 + * @dentry:   dentry from which @inode is retrieved
 + * @cpu_caps: vfs capabilities
 + *
   * Extract the on-exec-apply capability sets for an executable file.
 + *
 + * If the inode has been found through an idmapped mount the user namespace of
 + * the vfsmount must be passed through @mnt_userns. This function will then
 + * take care to map the inode according to @mnt_userns before checking
 + * permissions. On non-idmapped mounts or if permission checking is to be
 + * performed on the raw inode simply passs init_user_ns.
   */
 -int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
 +int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
 +                         const struct dentry *dentry,
 +                         struct cpu_vfs_cap_data *cpu_caps)
  {
        struct inode *inode = d_backing_inode(dentry);
        __u32 magic_etc;
        /* Limit the caps to the mounter of the filesystem
         * or the more limited uid specified in the xattr.
         */
 +      rootkuid = kuid_into_mnt(mnt_userns, rootkuid);
        if (!rootid_owns_currentns(rootkuid))
                return -ENODATA;
  
@@@ -745,8 -687,7 +745,8 @@@ static int get_file_caps(struct linux_b
        if (!current_in_userns(file->f_path.mnt->mnt_sb->s_user_ns))
                return 0;
  
 -      rc = get_vfs_caps_from_disk(file->f_path.dentry, &vcaps);
 +      rc = get_vfs_caps_from_disk(file_mnt_user_ns(file),
 +                                  file->f_path.dentry, &vcaps);
        if (rc < 0) {
                if (rc == -EINVAL)
                        printk(KERN_NOTICE "Invalid argument reading file caps for %s\n",
@@@ -881,7 -822,9 +881,9 @@@ static inline bool nonroot_raised_pE(st
   *
   * Set up the proposed credentials for a new execution context being
   * constructed by execve().  The proposed creds in @bprm->cred is altered,
-  * which won't take effect immediately.  Returns 0 if successful, -ve on error.
+  * which won't take effect immediately.
+  *
+  * Return: 0 if successful, -ve on error.
   */
  int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file)
  {
@@@ -1011,25 -954,16 +1013,25 @@@ int cap_inode_setxattr(struct dentry *d
  
  /**
   * cap_inode_removexattr - Determine whether an xattr may be removed
 - * @dentry: The inode/dentry being altered
 - * @name: The name of the xattr to be changed
 + *
 + * @mnt_userns:       User namespace of the mount the inode was found from
 + * @dentry:   The inode/dentry being altered
 + * @name:     The name of the xattr to be changed
   *
   * Determine whether an xattr may be removed from an inode, returning 0 if
   * permission is granted, -ve if denied.
   *
 + * If the inode has been found through an idmapped mount the user namespace of
 + * the vfsmount must be passed through @mnt_userns. This function will then
 + * take care to map the inode according to @mnt_userns before checking
 + * permissions. On non-idmapped mounts or if permission checking is to be
 + * performed on the raw inode simply passs init_user_ns.
 + *
   * This is used to make sure security xattrs don't get removed by those who
   * aren't privileged to remove them.
   */
 -int cap_inode_removexattr(struct dentry *dentry, const char *name)
 +int cap_inode_removexattr(struct user_namespace *mnt_userns,
 +                        struct dentry *dentry, const char *name)
  {
        struct user_namespace *user_ns = dentry->d_sb->s_user_ns;
  
                struct inode *inode = d_backing_inode(dentry);
                if (!inode)
                        return -EINVAL;
 -              if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
 +              if (!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_SETFCAP))
                        return -EPERM;
                return 0;
        }
@@@ -1117,7 -1051,9 +1119,9 @@@ static inline void cap_emulate_setxuid(
   * @flags: Indications of what has changed
   *
   * Fix up the results of setuid() call before the credential changes are
-  * actually applied, returning 0 to grant the changes, -ve to deny them.
+  * actually applied.
+  *
+  * Return: 0 to grant the changes, -ve to deny them.
   */
  int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
  {
@@@ -1187,7 -1123,9 +1191,9 @@@ static int cap_safe_nice(struct task_st
   * @p: The task to affect
   *
   * Detemine if the requested scheduler policy change is permitted for the
-  * specified task, returning 0 if permission is granted, -ve if denied.
+  * specified task.
+  *
+  * Return: 0 if permission is granted, -ve if denied.
   */
  int cap_task_setscheduler(struct task_struct *p)
  {
  }
  
  /**
-  * cap_task_ioprio - Detemine if I/O priority change is permitted
+  * cap_task_setioprio - Detemine if I/O priority change is permitted
   * @p: The task to affect
   * @ioprio: The I/O priority to set
   *
   * Detemine if the requested I/O priority change is permitted for the specified
-  * task, returning 0 if permission is granted, -ve if denied.
+  * task.
+  *
+  * Return: 0 if permission is granted, -ve if denied.
   */
  int cap_task_setioprio(struct task_struct *p, int ioprio)
  {
  }
  
  /**
-  * cap_task_ioprio - Detemine if task priority change is permitted
+  * cap_task_setnice - Detemine if task priority change is permitted
   * @p: The task to affect
   * @nice: The nice value to set
   *
   * Detemine if the requested task priority change is permitted for the
-  * specified task, returning 0 if permission is granted, -ve if denied.
+  * specified task.
+  *
+  * Return: 0 if permission is granted, -ve if denied.
   */
  int cap_task_setnice(struct task_struct *p, int nice)
  {
@@@ -1243,12 -1185,15 +1253,15 @@@ static int cap_prctl_drop(unsigned lon
  /**
   * cap_task_prctl - Implement process control functions for this security module
   * @option: The process control function requested
-  * @arg2, @arg3, @arg4, @arg5: The argument data for this function
+  * @arg2: The argument data for this function
+  * @arg3: The argument data for this function
+  * @arg4: The argument data for this function
+  * @arg5: The argument data for this function
   *
   * Allow process control functions (sys_prctl()) to alter capabilities; may
   * also deny access to other functions not otherwise implemented here.
   *
-  * Returns 0 or +ve on success, -ENOSYS if this function is not implemented
+  * Return: 0 or +ve on success, -ENOSYS if this function is not implemented
   * here, other -ve on error.  If -ENOSYS is returned, sys_prctl() and other LSM
   * modules will consider performing the function.
   */
@@@ -1383,7 -1328,9 +1396,9 @@@ int cap_task_prctl(int option, unsigne
   * @pages: The size of the mapping
   *
   * Determine whether the allocation of a new virtual mapping by the current
-  * task is permitted, returning 1 if permission is granted, 0 if not.
+  * task is permitted.
+  *
+  * Return: 1 if permission is granted, 0 if not.
   */
  int cap_vm_enough_memory(struct mm_struct *mm, long pages)
  {
        return cap_sys_admin;
  }
  
- /*
+ /**
   * cap_mmap_addr - check if able to map given addr
   * @addr: address attempting to be mapped
   *
   * If the process is attempting to map memory below dac_mmap_min_addr they need
   * CAP_SYS_RAWIO.  The other parameters to this function are unused by the
-  * capability security module.  Returns 0 if this mapping should be allowed
-  * -EPERM if not.
+  * capability security module.
+  *
+  * Return: 0 if this mapping should be allowed or -EPERM if not.
   */
  int cap_mmap_addr(unsigned long addr)
  {