fs: port vfs{g,u}id helpers to mnt_idmap
[sfrench/cifs-2.6.git] / fs / attr.c
index b45f30e516fad33ff4f58e3b15f1e754a724cef2..1a100d392dd9a7970c45c312f79aac5fc29c2c8c 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -23,7 +23,7 @@
 /**
  * setattr_should_drop_sgid - determine whether the setgid bit needs to be
  *                            removed
- * @mnt_userns:        user namespace of the mount @inode was found from
+ * @idmap:     idmap of the mount @inode was found from
  * @inode:     inode to check
  *
  * This function determines whether the setgid bit needs to be removed.
@@ -33,7 +33,7 @@
  *
  * Return: ATTR_KILL_SGID if setgid bit needs to be removed, 0 otherwise.
  */
-int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
+int setattr_should_drop_sgid(struct mnt_idmap *idmap,
                             const struct inode *inode)
 {
        umode_t mode = inode->i_mode;
@@ -42,8 +42,7 @@ int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
                return 0;
        if (mode & S_IXGRP)
                return ATTR_KILL_SGID;
-       if (!in_group_or_capable(mnt_userns, inode,
-                                i_gid_into_vfsgid(mnt_userns, inode)))
+       if (!in_group_or_capable(idmap, inode, i_gid_into_vfsgid(idmap, inode)))
                return ATTR_KILL_SGID;
        return 0;
 }
@@ -51,7 +50,7 @@ int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
 /**
  * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
  *                               be dropped
- * @mnt_userns:        user namespace of the mount @inode was found from
+ * @idmap:     idmap of the mount @inode was found from
  * @inode:     inode to check
  *
  * This function determines whether the set{g,u}id bits need to be removed.
@@ -63,7 +62,7 @@ int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
  * Return: A mask of ATTR_KILL_S{G,U}ID indicating which - if any - setid bits
  * to remove, 0 otherwise.
  */
-int setattr_should_drop_suidgid(struct user_namespace *mnt_userns,
+int setattr_should_drop_suidgid(struct mnt_idmap *idmap,
                                struct inode *inode)
 {
        umode_t mode = inode->i_mode;
@@ -73,7 +72,7 @@ int setattr_should_drop_suidgid(struct user_namespace *mnt_userns,
        if (unlikely(mode & S_ISUID))
                kill = ATTR_KILL_SUID;
 
-       kill |= setattr_should_drop_sgid(mnt_userns, inode);
+       kill |= setattr_should_drop_sgid(idmap, inode);
 
        if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
                return kill;
@@ -84,24 +83,24 @@ EXPORT_SYMBOL(setattr_should_drop_suidgid);
 
 /**
  * chown_ok - verify permissions to chown inode
- * @mnt_userns:        user namespace of the mount @inode was found from
+ * @idmap:     idmap of the mount @inode was found from
  * @inode:     inode to check permissions on
  * @ia_vfsuid: uid to chown @inode to
  *
- * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  */
-static bool chown_ok(struct user_namespace *mnt_userns,
+static bool chown_ok(struct mnt_idmap *idmap,
                     const struct inode *inode, vfsuid_t ia_vfsuid)
 {
-       vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
+       vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode);
        if (vfsuid_eq_kuid(vfsuid, current_fsuid()) &&
            vfsuid_eq(ia_vfsuid, vfsuid))
                return true;
-       if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
+       if (capable_wrt_inode_uidgid(idmap, inode, CAP_CHOWN))
                return true;
        if (!vfsuid_valid(vfsuid) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
@@ -111,28 +110,28 @@ static bool chown_ok(struct user_namespace *mnt_userns,
 
 /**
  * chgrp_ok - verify permissions to chgrp inode
- * @mnt_userns:        user namespace of the mount @inode was found from
+ * @idmap:     idmap of the mount @inode was found from
  * @inode:     inode to check permissions on
  * @ia_vfsgid: gid to chown @inode to
  *
- * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  */
-static bool chgrp_ok(struct user_namespace *mnt_userns,
+static bool chgrp_ok(struct mnt_idmap *idmap,
                     const struct inode *inode, vfsgid_t ia_vfsgid)
 {
-       vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
-       vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
+       vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode);
+       vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode);
        if (vfsuid_eq_kuid(vfsuid, current_fsuid())) {
                if (vfsgid_eq(ia_vfsgid, vfsgid))
                        return true;
                if (vfsgid_in_group_p(ia_vfsgid))
                        return true;
        }
-       if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
+       if (capable_wrt_inode_uidgid(idmap, inode, CAP_CHOWN))
                return true;
        if (!vfsgid_valid(vfsgid) &&
            ns_capable(inode->i_sb->s_user_ns, CAP_CHOWN))
@@ -142,7 +141,7 @@ static bool chgrp_ok(struct user_namespace *mnt_userns,
 
 /**
  * setattr_prepare - check if attribute changes to a dentry are allowed
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    dentry to check
  * @attr:      attributes to change
  *
@@ -152,16 +151,16 @@ static bool chgrp_ok(struct user_namespace *mnt_userns,
  * SGID bit from mode if user is not allowed to set it. Also file capabilities
  * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set.
  *
- * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply passs @nop_mnt_idmap.
  *
  * Should be called as the first thing in ->setattr implementations,
  * possibly after taking additional locks.
  */
-int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
+int setattr_prepare(struct mnt_idmap *idmap, struct dentry *dentry,
                    struct iattr *attr)
 {
        struct inode *inode = d_inode(dentry);
@@ -183,34 +182,34 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
 
        /* Make sure a caller can chown. */
        if ((ia_valid & ATTR_UID) &&
-           !chown_ok(mnt_userns, inode, attr->ia_vfsuid))
+           !chown_ok(idmap, inode, attr->ia_vfsuid))
                return -EPERM;
 
        /* Make sure caller can chgrp. */
        if ((ia_valid & ATTR_GID) &&
-           !chgrp_ok(mnt_userns, inode, attr->ia_vfsgid))
+           !chgrp_ok(idmap, inode, attr->ia_vfsgid))
                return -EPERM;
 
        /* Make sure a caller can chmod. */
        if (ia_valid & ATTR_MODE) {
                vfsgid_t vfsgid;
 
-               if (!inode_owner_or_capable(mnt_userns, inode))
+               if (!inode_owner_or_capable(idmap, inode))
                        return -EPERM;
 
                if (ia_valid & ATTR_GID)
                        vfsgid = attr->ia_vfsgid;
                else
-                       vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
+                       vfsgid = i_gid_into_vfsgid(idmap, inode);
 
                /* Also check the setgid bit! */
-               if (!in_group_or_capable(mnt_userns, inode, vfsgid))
+               if (!in_group_or_capable(idmap, inode, vfsgid))
                        attr->ia_mode &= ~S_ISGID;
        }
 
        /* Check for setting the inode time. */
        if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {
-               if (!inode_owner_or_capable(mnt_userns, inode))
+               if (!inode_owner_or_capable(idmap, inode))
                        return -EPERM;
        }
 
@@ -219,7 +218,7 @@ kill_priv:
        if (ia_valid & ATTR_KILL_PRIV) {
                int error;
 
-               error = security_inode_killpriv(mnt_userns, dentry);
+               error = security_inode_killpriv(idmap, dentry);
                if (error)
                        return error;
        }
@@ -276,7 +275,7 @@ EXPORT_SYMBOL(inode_newsize_ok);
 
 /**
  * setattr_copy - copy simple metadata updates into the generic inode
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @inode:     the inode to be updated
  * @attr:      the new attributes
  *
@@ -289,23 +288,23 @@ EXPORT_SYMBOL(inode_newsize_ok);
  * Noticeably missing is inode size update, which is more complex
  * as it requires pagecache updates.
  *
- * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  *
  * The inode is not marked as dirty after this operation. The rationale is
  * that for "simple" filesystems, the struct inode is the inode storage.
  * The caller is free to mark the inode dirty afterwards if needed.
  */
-void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
+void setattr_copy(struct mnt_idmap *idmap, struct inode *inode,
                  const struct iattr *attr)
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       i_uid_update(mnt_userns, attr, inode);
-       i_gid_update(mnt_userns, attr, inode);
+       i_uid_update(idmap, attr, inode);
+       i_gid_update(idmap, attr, inode);
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
@@ -314,15 +313,15 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
                inode->i_ctime = attr->ia_ctime;
        if (ia_valid & ATTR_MODE) {
                umode_t mode = attr->ia_mode;
-               if (!in_group_or_capable(mnt_userns, inode,
-                                        i_gid_into_vfsgid(mnt_userns, inode)))
+               if (!in_group_or_capable(idmap, inode,
+                                        i_gid_into_vfsgid(idmap, inode)))
                        mode &= ~S_ISGID;
                inode->i_mode = mode;
        }
 }
 EXPORT_SYMBOL(setattr_copy);
 
-int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
+int may_setattr(struct mnt_idmap *idmap, struct inode *inode,
                unsigned int ia_valid)
 {
        int error;
@@ -340,8 +339,8 @@ int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
                if (IS_IMMUTABLE(inode))
                        return -EPERM;
 
-               if (!inode_owner_or_capable(mnt_userns, inode)) {
-                       error = inode_permission(mnt_userns, inode, MAY_WRITE);
+               if (!inode_owner_or_capable(idmap, inode)) {
+                       error = inode_permission(idmap, inode, MAY_WRITE);
                        if (error)
                                return error;
                }
@@ -352,7 +351,7 @@ EXPORT_SYMBOL(may_setattr);
 
 /**
  * notify_change - modify attributes of a filesytem object
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    object affected
  * @attr:      new attributes
  * @delegated_inode: returns inode, if the inode is delegated
@@ -371,13 +370,13 @@ EXPORT_SYMBOL(may_setattr);
  * the file open for write, as there can be no conflicting delegation in
  * that case.
  *
- * 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
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  */
-int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
+int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
                  struct iattr *attr, struct inode **delegated_inode)
 {
        struct inode *inode = dentry->d_inode;
@@ -388,7 +387,7 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
 
        WARN_ON_ONCE(!inode_is_locked(inode));
 
-       error = may_setattr(mnt_userns, inode, ia_valid);
+       error = may_setattr(idmap, inode, ia_valid);
        if (error)
                return error;
 
@@ -453,11 +452,11 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
         * namespace of the superblock.
         */
        if (ia_valid & ATTR_UID &&
-           !vfsuid_has_fsmapping(mnt_userns, inode->i_sb->s_user_ns,
+           !vfsuid_has_fsmapping(idmap, inode->i_sb->s_user_ns,
                                  attr->ia_vfsuid))
                return -EOVERFLOW;
        if (ia_valid & ATTR_GID &&
-           !vfsgid_has_fsmapping(mnt_userns, inode->i_sb->s_user_ns,
+           !vfsgid_has_fsmapping(idmap, inode->i_sb->s_user_ns,
                                  attr->ia_vfsgid))
                return -EOVERFLOW;
 
@@ -465,13 +464,13 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
         * gids unless those uids & gids are being made valid.
         */
        if (!(ia_valid & ATTR_UID) &&
-           !vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)))
+           !vfsuid_valid(i_uid_into_vfsuid(idmap, inode)))
                return -EOVERFLOW;
        if (!(ia_valid & ATTR_GID) &&
-           !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
+           !vfsgid_valid(i_gid_into_vfsgid(idmap, inode)))
                return -EOVERFLOW;
 
-       error = security_inode_setattr(mnt_userns, dentry, attr);
+       error = security_inode_setattr(idmap, dentry, attr);
        if (error)
                return error;
        error = try_break_deleg(inode, delegated_inode);
@@ -479,13 +478,13 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
                return error;
 
        if (inode->i_op->setattr)
-               error = inode->i_op->setattr(mnt_userns, dentry, attr);
+               error = inode->i_op->setattr(idmap, dentry, attr);
        else
-               error = simple_setattr(mnt_userns, dentry, attr);
+               error = simple_setattr(idmap, dentry, attr);
 
        if (!error) {
                fsnotify_change(dentry, ia_valid);
-               ima_inode_post_setattr(mnt_userns, dentry);
+               ima_inode_post_setattr(idmap, dentry);
                evm_inode_post_setattr(dentry, ia_valid);
        }