fs: use low-level mapping helpers
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 3 Dec 2021 11:17:03 +0000 (12:17 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 3 Dec 2021 17:58:11 +0000 (18:58 +0100)
In a few places the vfs needs to interact with bare k{g,u}ids directly
instead of struct inode. These are just a few. In previous patches we
introduced low-level mapping helpers that are able to support
filesystems mounted an idmapping. This patch simply converts the places
to use these new helpers.

Link: https://lore.kernel.org/r/20211123114227.3124056-7-brauner@kernel.org
Link: https://lore.kernel.org/r/20211130121032.3753852-7-brauner@kernel.org
Link: https://lore.kernel.org/r/20211203111707.3901969-7-brauner@kernel.org
Cc: Seth Forshee <sforshee@digitalocean.com>
Cc: Amir Goldstein <amir73il@gmail.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel@vger.kernel.org
Reviewed-by: Seth Forshee <sforshee@digitalocean.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
fs/ksmbd/smbacl.c
fs/ksmbd/smbacl.h
fs/open.c
fs/posix_acl.c
security/commoncap.c

index ab8099e0fd7f28c11e7e7dbfd3983772ebfb4f54..6ecf55ea1fed5ce030518f03f522ad24d6c19e6c 100644 (file)
@@ -275,14 +275,7 @@ static int sid_to_id(struct user_namespace *user_ns,
                uid_t id;
 
                id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
-               /*
-                * Translate raw sid into kuid in the server's user
-                * namespace.
-                */
-               uid = make_kuid(&init_user_ns, id);
-
-               /* If this is an idmapped mount, apply the idmapping. */
-               uid = kuid_from_mnt(user_ns, uid);
+               uid = mapped_kuid_user(user_ns, &init_user_ns, KUIDT_INIT(id));
                if (uid_valid(uid)) {
                        fattr->cf_uid = uid;
                        rc = 0;
@@ -292,14 +285,7 @@ static int sid_to_id(struct user_namespace *user_ns,
                gid_t id;
 
                id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
-               /*
-                * Translate raw sid into kgid in the server's user
-                * namespace.
-                */
-               gid = make_kgid(&init_user_ns, id);
-
-               /* If this is an idmapped mount, apply the idmapping. */
-               gid = kgid_from_mnt(user_ns, gid);
+               gid = mapped_kgid_user(user_ns, &init_user_ns, KGIDT_INIT(id));
                if (gid_valid(gid)) {
                        fattr->cf_gid = gid;
                        rc = 0;
index eba1ebb9e92ec4a9b5adce26d70e70240dd968e6..811af3309429163484b55f6a8a6f206201562adc 100644 (file)
@@ -217,7 +217,7 @@ static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
        kuid_t kuid;
 
        /* If this is an idmapped mount, apply the idmapping. */
-       kuid = kuid_into_mnt(mnt_userns, pace->e_uid);
+       kuid = mapped_kuid_fs(mnt_userns, &init_user_ns, pace->e_uid);
 
        /* Translate the kuid into a userspace id ksmbd would see. */
        return from_kuid(&init_user_ns, kuid);
@@ -229,7 +229,7 @@ static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
        kgid_t kgid;
 
        /* If this is an idmapped mount, apply the idmapping. */
-       kgid = kgid_into_mnt(mnt_userns, pace->e_gid);
+       kgid = mapped_kgid_fs(mnt_userns, &init_user_ns, pace->e_gid);
 
        /* Translate the kgid into a userspace id ksmbd would see. */
        return from_kgid(&init_user_ns, kgid);
index 2450cc1a2f64f68536645bd67198338e460be25f..40a00e71865bab39c8f11f750c3705d84620c82d 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -653,8 +653,8 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
        gid = make_kgid(current_user_ns(), group);
 
        mnt_userns = mnt_user_ns(path->mnt);
-       uid = kuid_from_mnt(mnt_userns, uid);
-       gid = kgid_from_mnt(mnt_userns, gid);
+       uid = mapped_kuid_user(mnt_userns, &init_user_ns, uid);
+       gid = mapped_kgid_user(mnt_userns, &init_user_ns, gid);
 
 retry_deleg:
        newattrs.ia_valid =  ATTR_CTIME;
index 632bfdcf7cc0abc5e9fb7727eb0a8de21e2239de..4b5fb9a9b90fa1e9c991f9655f330766da8de311 100644 (file)
@@ -375,7 +375,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
                                         goto check_perm;
                                 break;
                         case ACL_USER:
-                               uid = kuid_into_mnt(mnt_userns, pa->e_uid);
+                               uid = mapped_kuid_fs(mnt_userns,
+                                                     &init_user_ns,
+                                                     pa->e_uid);
                                if (uid_eq(uid, current_fsuid()))
                                         goto mask;
                                break;
@@ -388,7 +390,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
                                 }
                                break;
                         case ACL_GROUP:
-                               gid = kgid_into_mnt(mnt_userns, pa->e_gid);
+                               gid = mapped_kgid_fs(mnt_userns,
+                                                     &init_user_ns,
+                                                     pa->e_gid);
                                if (in_group_p(gid)) {
                                        found = 1;
                                        if ((pa->e_perm & want) == want)
@@ -735,17 +739,17 @@ static void posix_acl_fix_xattr_userns(
                case ACL_USER:
                        uid = make_kuid(from, le32_to_cpu(entry->e_id));
                        if (from_user)
-                               uid = kuid_from_mnt(mnt_userns, uid);
+                               uid = mapped_kuid_user(mnt_userns, &init_user_ns, uid);
                        else
-                               uid = kuid_into_mnt(mnt_userns, uid);
+                               uid = mapped_kuid_fs(mnt_userns, &init_user_ns, uid);
                        entry->e_id = cpu_to_le32(from_kuid(to, uid));
                        break;
                case ACL_GROUP:
                        gid = make_kgid(from, le32_to_cpu(entry->e_id));
                        if (from_user)
-                               gid = kgid_from_mnt(mnt_userns, gid);
+                               gid = mapped_kgid_user(mnt_userns, &init_user_ns, gid);
                        else
-                               gid = kgid_into_mnt(mnt_userns, gid);
+                               gid = mapped_kgid_fs(mnt_userns, &init_user_ns, gid);
                        entry->e_id = cpu_to_le32(from_kgid(to, gid));
                        break;
                default:
index 09479f71ee2eda7da05fce5d0554a3fef9370238..d288a62e299967f71066a75a4fa547ce7b4a0088 100644 (file)
@@ -419,7 +419,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
        kroot = make_kuid(fs_ns, root);
 
        /* If this is an idmapped mount shift the kuid. */
-       kroot = kuid_into_mnt(mnt_userns, kroot);
+       kroot = mapped_kuid_fs(mnt_userns, &init_user_ns, kroot);
 
        /* If the root kuid maps to a valid uid in current ns, then return
         * this as a nscap. */
@@ -489,6 +489,7 @@ out_free:
  * @size:      size of @ivalue
  * @task_ns:   user namespace of the caller
  * @mnt_userns:        user namespace of the mount the inode was found from
+ * @fs_userns: user namespace of the filesystem
  *
  * 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
@@ -498,7 +499,8 @@ out_free:
  */
 static kuid_t rootid_from_xattr(const void *value, size_t size,
                                struct user_namespace *task_ns,
-                               struct user_namespace *mnt_userns)
+                               struct user_namespace *mnt_userns,
+                               struct user_namespace *fs_userns)
 {
        const struct vfs_ns_cap_data *nscap = value;
        kuid_t rootkid;
@@ -508,7 +510,7 @@ static kuid_t rootid_from_xattr(const void *value, size_t size,
                rootid = le32_to_cpu(nscap->rootid);
 
        rootkid = make_kuid(task_ns, rootid);
-       return kuid_from_mnt(mnt_userns, rootkid);
+       return mapped_kuid_user(mnt_userns, fs_userns, rootkid);
 }
 
 static bool validheader(size_t size, const struct vfs_cap_data *cap)
@@ -559,7 +561,8 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,
                        /* user is privileged, just write the v2 */
                        return size;
 
-       rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns);
+       rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns,
+                                  &init_user_ns);
        if (!uid_valid(rootid))
                return -EINVAL;
 
@@ -700,7 +703,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
        /* 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);
+       rootkuid = mapped_kuid_fs(mnt_userns, &init_user_ns, rootkuid);
        if (!rootid_owns_currentns(rootkuid))
                return -ENODATA;