History

Merge tag 'fs.idmapped.v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux

Pull fs idmapping updates from Christian Brauner: "This contains the work to enable the idmapping infrastructure to support idmapped mounts of filesystems mounted with an idmapping. In addition this contains various cleanups that avoid repeated open-coding of the same functionality and simplify the code in quite a few places. We also finish the renaming of the mapping helpers we started a few kernel releases back and move them to a dedicated header to not continue polluting the fs header needlessly with low-level idmapping helpers. With this series the fs header only contains idmapping helpers that interact with fs objects. Currently we only support idmapped mounts for filesystems mounted without an idmapping themselves. This was a conscious decision mentioned in multiple places (cf. [1]). As explained at length in [3] it is perfectly fine to extend support for idmapped mounts to filesystem's mounted with an idmapping should the need arise. The need has been there for some time now (cf. [2]). Before we can port any filesystem that is mountable with an idmapping to support idmapped mounts in the coming cycles, we need to first extend the mapping helpers to account for the filesystem's idmapping. This again, is explained at length in our documentation at [3] and also in the individual commit messages so here's an overview. Currently, the low-level mapping helpers implement the remapping algorithms described in [3] in a simplified manner as we could rely on the fact that all filesystems supporting idmapped mounts are mounted without an idmapping. In contrast, filesystems mounted with an idmapping are very likely to not use an identity mapping and will instead use a non-identity mapping. So the translation step from or into the filesystem's idmapping in the remapping algorithm cannot be skipped for such filesystems. Non-idmapped filesystems and filesystems not supporting idmapped mounts are unaffected by this change as the remapping algorithms can take the same shortcut as before. If the low-level helpers detect that they are dealing with an idmapped mount but the underlying filesystem is mounted without an idmapping we can rely on the previous shortcut and can continue to skip the translation step from or into the filesystem's idmapping. And of course, if the low-level helpers detect that they are not dealing with an idmapped mount they can simply return the relevant id unchanged; no remapping needs to be performed at all. These checks guarantee that only the minimal amount of work is performed. As before, if idmapped mounts aren't used the low-level helpers are idempotent and no work is performed at all" Link: 2ca4dcc4909d ("fs/mount_setattr: tighten permission checks") [1] Link: https://github.com/containers/podman/issues/10374 [2] Link: Documentations/filesystems/idmappings.rst [3] Link: a65e58e791a1 ("fs: document and rename fsid helpers") [4] * tag 'fs.idmapped.v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: fs: support mapped mounts of mapped filesystems fs: add i_user_ns() helper fs: port higher-level mapping helpers fs: remove unused low-level mapping helpers fs: use low-level mapping helpers docs: update mapping documentation fs: account for filesystem mappings fs: tweak fsuidgid_has_mapping() fs: move mapping helpers fs: add is_idmapped_mnt() helper

Linus Torvalds committed 4 years ago

Commit 5dfbfe72 parents 84bfcc0 bd3033617 files · +356 −231Browse files

Unified · Split

17 files
  1. Documentation/filesystems/idmappings.rst +0 −72
  2. fs/cachefiles/bind.c +1 −1
  3. fs/ecryptfs/main.c +1 −1
  4. fs/ksmbd/smbacl.c +3 −16
  5. fs/ksmbd/smbacl.h +3 −2
  6. fs/namespace.c +39 −14
  7. fs/nfsd/export.c +1 −1
  8. fs/open.c +5 −3
  9. fs/overlayfs/super.c +1 −1
  10. fs/posix_acl.c +11 −6
  11. fs/proc_namespace.c +1 −1
  12. fs/xfs/xfs_inode.c +4 −4
  13. fs/xfs/xfs_linux.h +1 −0
  14. fs/xfs/xfs_symlink.c +2 −2
  15. include/linux/fs.h +40 −101
  16. include/linux/mnt_idmapping.h +234 −0
  17. security/commoncap.c +9 −6
Documentation/filesystems/idmappings.rst+0−72
@@ -952,75 +952,3 @@ The raw userspace id that is put on disk is ``u1000`` so when the user takes · 951 unmodified lines
952their home directory back to their home computer where they are assigned952their home directory back to their home computer where they are assigned
953``u1000`` using the initial idmapping and mount the filesystem with the initial953``u1000`` using the initial idmapping and mount the filesystem with the initial
954idmapping they will see all those files owned by ``u1000``.954idmapping they will see all those files owned by ``u1000``.
955
956Shortcircuting
957--------------
958
959Currently, the implementation of idmapped mounts enforces that the filesystem
960is mounted with the initial idmapping. The reason is simply that none of the
961filesystems that we targeted were mountable with a non-initial idmapping. But
962that might change soon enough. As we've seen above, thanks to the properties of
963idmappings the translation works for both filesystems mounted with the initial
964idmapping and filesystem with non-initial idmappings.
965
966Based on this current restriction to filesystem mounted with the initial
967idmapping two noticeable shortcuts have been taken:
968
9691. We always stash a reference to the initial user namespace in ``struct
970 vfsmount``. Idmapped mounts are thus mounts that have a non-initial user
971 namespace attached to them.
972
973 In order to support idmapped mounts this needs to be changed. Instead of
974 stashing the initial user namespace the user namespace the filesystem was
975 mounted with must be stashed. An idmapped mount is then any mount that has
976 a different user namespace attached then the filesystem was mounted with.
977 This has no user-visible consequences.
978
9792. The translation algorithms in ``mapped_fs*id()`` and ``i_*id_into_mnt()``
980 are simplified.
981
982 Let's consider ``mapped_fs*id()`` first. This function translates the
983 caller's kernel id into a kernel id in the filesystem's idmapping via
984 a mount's idmapping. The full algorithm is::
985
986 mapped_fsuid(kid):
987 /* Map the kernel id up into a userspace id in the mount's idmapping. */
988 from_kuid(mount-idmapping, kid) = uid
989
990 /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
991 make_kuid(filesystem-idmapping, uid) = kuid
992
993 We know that the filesystem is always mounted with the initial idmapping as
994 we enforce this in ``mount_setattr()``. So this can be shortened to::
995
996 mapped_fsuid(kid):
997 /* Map the kernel id up into a userspace id in the mount's idmapping. */
998 from_kuid(mount-idmapping, kid) = uid
999
1000 /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
1001 KUIDT_INIT(uid) = kuid
1002
1003 Similarly, for ``i_*id_into_mnt()`` which translated the filesystem's kernel
1004 id into a mount's kernel id::
1005
1006 i_uid_into_mnt(kid):
1007 /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
1008 from_kuid(filesystem-idmapping, kid) = uid
1009
1010 /* Map the userspace id down into a kernel id in the mounts's idmapping. */
1011 make_kuid(mount-idmapping, uid) = kuid
1012
1013 Again, we know that the filesystem is always mounted with the initial
1014 idmapping as we enforce this in ``mount_setattr()``. So this can be
1015 shortened to::
1016
1017 i_uid_into_mnt(kid):
1018 /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
1019 __kuid_val(kid) = uid
1020
1021 /* Map the userspace id down into a kernel id in the mounts's idmapping. */
1022 make_kuid(mount-idmapping, uid) = kuid
1023
1024Handling filesystems mounted with non-initial idmappings requires that the
1025translation functions be converted to their full form. They can still be
1026shortcircuited on non-idmapped mounts. This has no user-visible consequences.
fs/cachefiles/bind.c+1−1
@@ -117,7 +117,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) · 116 unmodified lines
117 root = path.dentry;117 root = path.dentry;
118 118
119 ret = -EINVAL;119 ret = -EINVAL;
120 if (mnt_user_ns(path.mnt) != &init_user_ns) {120 if (is_idmapped_mnt(path.mnt)) {
121 pr_warn("File cache on idmapped mounts not supported");121 pr_warn("File cache on idmapped mounts not supported");
122 goto error_unsupported;122 goto error_unsupported;
123 }123 }
fs/ecryptfs/main.c+1−1
@@ -537,7 +537,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags · 536 unmodified lines
537 goto out_free;537 goto out_free;
538 }538 }
539 539
540 if (mnt_user_ns(path.mnt) != &init_user_ns) {540 if (is_idmapped_mnt(path.mnt)) {
541 rc = -EINVAL;541 rc = -EINVAL;
542 printk(KERN_ERR "Mounting on idmapped mounts currently disallowed\n");542 printk(KERN_ERR "Mounting on idmapped mounts currently disallowed\n");
543 goto out_free;543 goto out_free;
fs/ksmbd/smbacl.c+3−16
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/fs.h>9#include <linux/fs.h>
10#include <linux/slab.h>10#include <linux/slab.h>
11#include <linux/string.h>11#include <linux/string.h>
12#include <linux/mnt_idmapping.h>
12 13
13#include "smbacl.h"14#include "smbacl.h"
14#include "smb_common.h"15#include "smb_common.h"
@@ -274,14 +275,7 @@ static int sid_to_id(struct user_namespace *user_ns, · 259 unmodified lines
274 uid_t id;275 uid_t id;
275 276
276 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);277 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
277 /*278 uid = mapped_kuid_user(user_ns, &init_user_ns, KUIDT_INIT(id));
278 * Translate raw sid into kuid in the server's user
279 * namespace.
280 */
281 uid = make_kuid(&init_user_ns, id);
282
283 /* If this is an idmapped mount, apply the idmapping. */
284 uid = kuid_from_mnt(user_ns, uid);
285 if (uid_valid(uid)) {279 if (uid_valid(uid)) {
286 fattr->cf_uid = uid;280 fattr->cf_uid = uid;
287 rc = 0;281 rc = 0;
@@ -291,14 +285,7 @@ static int sid_to_id(struct user_namespace *user_ns, · 3 unmodified lines
291 gid_t id;285 gid_t id;
292 286
293 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);287 id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
294 /*288 gid = mapped_kgid_user(user_ns, &init_user_ns, KGIDT_INIT(id));
295 * Translate raw sid into kgid in the server's user
296 * namespace.
297 */
298 gid = make_kgid(&init_user_ns, id);
299
300 /* If this is an idmapped mount, apply the idmapping. */
301 gid = kgid_from_mnt(user_ns, gid);
302 if (gid_valid(gid)) {289 if (gid_valid(gid)) {
303 fattr->cf_gid = gid;290 fattr->cf_gid = gid;
304 rc = 0;291 rc = 0;
fs/ksmbd/smbacl.h+3−2
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <linux/fs.h>11#include <linux/fs.h>
12#include <linux/namei.h>12#include <linux/namei.h>
13#include <linux/posix_acl.h>13#include <linux/posix_acl.h>
14#include <linux/mnt_idmapping.h>
14 15
15#include "mgmt/tree_connect.h"16#include "mgmt/tree_connect.h"
16 17
@@ -216,7 +217,7 @@ static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns, · 199 unmodified lines
216 kuid_t kuid;217 kuid_t kuid;
217 218
218 /* If this is an idmapped mount, apply the idmapping. */219 /* If this is an idmapped mount, apply the idmapping. */
219 kuid = kuid_into_mnt(mnt_userns, pace->e_uid);220 kuid = mapped_kuid_fs(mnt_userns, &init_user_ns, pace->e_uid);
220 221
221 /* Translate the kuid into a userspace id ksmbd would see. */222 /* Translate the kuid into a userspace id ksmbd would see. */
222 return from_kuid(&init_user_ns, kuid);223 return from_kuid(&init_user_ns, kuid);
@@ -228,7 +229,7 @@ static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns, · 5 unmodified lines
228 kgid_t kgid;229 kgid_t kgid;
229 230
230 /* If this is an idmapped mount, apply the idmapping. */231 /* If this is an idmapped mount, apply the idmapping. */
231 kgid = kgid_into_mnt(mnt_userns, pace->e_gid);232 kgid = mapped_kgid_fs(mnt_userns, &init_user_ns, pace->e_gid);
232 233
233 /* Translate the kgid into a userspace id ksmbd would see. */234 /* Translate the kgid into a userspace id ksmbd would see. */
234 return from_kgid(&init_user_ns, kgid);235 return from_kgid(&init_user_ns, kgid);
fs/namespace.c+39−14
@@ -31,6 +31,7 @@ · 30 unmodified lines
31#include <uapi/linux/mount.h>31#include <uapi/linux/mount.h>
32#include <linux/fs_context.h>32#include <linux/fs_context.h>
33#include <linux/shmem_fs.h>33#include <linux/shmem_fs.h>
34#include <linux/mnt_idmapping.h>
34 35
35#include "pnode.h"36#include "pnode.h"
36#include "internal.h"37#include "internal.h"
@@ -561,7 +562,7 @@ static void free_vfsmnt(struct mount *mnt) · 524 unmodified lines
561 struct user_namespace *mnt_userns;562 struct user_namespace *mnt_userns;
562 563
563 mnt_userns = mnt_user_ns(&mnt->mnt);564 mnt_userns = mnt_user_ns(&mnt->mnt);
564 if (mnt_userns != &init_user_ns)565 if (!initial_idmapping(mnt_userns))
565 put_user_ns(mnt_userns);566 put_user_ns(mnt_userns);
566 kfree_const(mnt->mnt_devname);567 kfree_const(mnt->mnt_devname);
567#ifdef CONFIG_SMP568#ifdef CONFIG_SMP
@@ -965,6 +966,7 @@ static struct mount *skip_mnt_tree(struct mount *p) · 397 unmodified lines
965struct vfsmount *vfs_create_mount(struct fs_context *fc)966struct vfsmount *vfs_create_mount(struct fs_context *fc)
966{967{
967 struct mount *mnt;968 struct mount *mnt;
969 struct user_namespace *fs_userns;
968 970
969 if (!fc->root)971 if (!fc->root)
970 return ERR_PTR(-EINVAL);972 return ERR_PTR(-EINVAL);
@@ -982,6 +984,10 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc) · 11 unmodified lines
982 mnt->mnt_mountpoint = mnt->mnt.mnt_root;984 mnt->mnt_mountpoint = mnt->mnt.mnt_root;
983 mnt->mnt_parent = mnt;985 mnt->mnt_parent = mnt;
984 986
987 fs_userns = mnt->mnt.mnt_sb->s_user_ns;
988 if (!initial_idmapping(fs_userns))
989 mnt->mnt.mnt_userns = get_user_ns(fs_userns);
990
985 lock_mount_hash();991 lock_mount_hash();
986 list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);992 list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);
987 unlock_mount_hash();993 unlock_mount_hash();
@@ -1072,7 +1078,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, · 84 unmodified lines
1072 1078
1073 atomic_inc(&sb->s_active);1079 atomic_inc(&sb->s_active);
1074 mnt->mnt.mnt_userns = mnt_user_ns(&old->mnt);1080 mnt->mnt.mnt_userns = mnt_user_ns(&old->mnt);
1075 if (mnt->mnt.mnt_userns != &init_user_ns)1081 if (!initial_idmapping(mnt->mnt.mnt_userns))
1076 mnt->mnt.mnt_userns = get_user_ns(mnt->mnt.mnt_userns);1082 mnt->mnt.mnt_userns = get_user_ns(mnt->mnt.mnt_userns);
1077 mnt->mnt.mnt_sb = sb;1083 mnt->mnt.mnt_sb = sb;
1078 mnt->mnt.mnt_root = dget(root);1084 mnt->mnt.mnt_root = dget(root);
@@ -3927,28 +3933,32 @@ static unsigned int recalc_flags(struct mount_kattr *kattr, struct mount *mnt) · 2848 unmodified lines
3927static int can_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)3933static int can_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)
3928{3934{
3929 struct vfsmount *m = &mnt->mnt;3935 struct vfsmount *m = &mnt->mnt;
3936 struct user_namespace *fs_userns = m->mnt_sb->s_user_ns;
3930 3937
3931 if (!kattr->mnt_userns)3938 if (!kattr->mnt_userns)
3932 return 0;3939 return 0;
3933 3940
3941 /*
3942 * Creating an idmapped mount with the filesystem wide idmapping
3943 * doesn't make sense so block that. We don't allow mushy semantics.
3944 */
3945 if (kattr->mnt_userns == fs_userns)
3946 return -EINVAL;
3947
3934 /*3948 /*
3935 * Once a mount has been idmapped we don't allow it to change its3949 * Once a mount has been idmapped we don't allow it to change its
3936 * mapping. It makes things simpler and callers can just create3950 * mapping. It makes things simpler and callers can just create
3937 * another bind-mount they can idmap if they want to.3951 * another bind-mount they can idmap if they want to.
3938 */3952 */
3939 if (mnt_user_ns(m) != &init_user_ns)3953 if (is_idmapped_mnt(m))
3940 return -EPERM;3954 return -EPERM;
3941 3955
3942 /* The underlying filesystem doesn't support idmapped mounts yet. */3956 /* The underlying filesystem doesn't support idmapped mounts yet. */
3943 if (!(m->mnt_sb->s_type->fs_flags & FS_ALLOW_IDMAP))3957 if (!(m->mnt_sb->s_type->fs_flags & FS_ALLOW_IDMAP))
3944 return -EINVAL;3958 return -EINVAL;
3945 3959
3946 /* Don't yet support filesystem mountable in user namespaces. */
3947 if (m->mnt_sb->s_user_ns != &init_user_ns)
3948 return -EINVAL;
3949
3950 /* We're not controlling the superblock. */3960 /* We're not controlling the superblock. */
3951 if (!capable(CAP_SYS_ADMIN))3961 if (!ns_capable(fs_userns, CAP_SYS_ADMIN))
3952 return -EPERM;3962 return -EPERM;
3953 3963
3954 /* Mount has already been visible in the filesystem hierarchy. */3964 /* Mount has already been visible in the filesystem hierarchy. */
@@ -4002,14 +4012,27 @@ out: · 47 unmodified lines
4002 4012
4003static void do_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)4013static void do_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)
4004{4014{
4005 struct user_namespace *mnt_userns;4015 struct user_namespace *mnt_userns, *old_mnt_userns;
4006 4016
4007 if (!kattr->mnt_userns)4017 if (!kattr->mnt_userns)
4008 return;4018 return;
4009 4019
4020 /*
4021 * We're the only ones able to change the mount's idmapping. So
4022 * mnt->mnt.mnt_userns is stable and we can retrieve it directly.
4023 */
4024 old_mnt_userns = mnt->mnt.mnt_userns;
4025
4010 mnt_userns = get_user_ns(kattr->mnt_userns);4026 mnt_userns = get_user_ns(kattr->mnt_userns);
4011 /* Pairs with smp_load_acquire() in mnt_user_ns(). */4027 /* Pairs with smp_load_acquire() in mnt_user_ns(). */
4012 smp_store_release(&mnt->mnt.mnt_userns, mnt_userns);4028 smp_store_release(&mnt->mnt.mnt_userns, mnt_userns);
4029
4030 /*
4031 * If this is an idmapped filesystem drop the reference we've taken
4032 * in vfs_create_mount() before.
4033 */
4034 if (!initial_idmapping(old_mnt_userns))
4035 put_user_ns(old_mnt_userns);
4013}4036}
4014 4037
4015static void mount_setattr_commit(struct mount_kattr *kattr,4038static void mount_setattr_commit(struct mount_kattr *kattr,
@@ -4133,13 +4156,15 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize, · 117 unmodified lines
4133 }4156 }
4134 4157
4135 /*4158 /*
4136 * The init_user_ns is used to indicate that a vfsmount is not idmapped.4159 * The initial idmapping cannot be used to create an idmapped
4137 * This is simpler than just having to treat NULL as unmapped. Users4160 * mount. We use the initial idmapping as an indicator of a mount
4138 * wanting to idmap a mount to init_user_ns can just use a namespace4161 * that is not idmapped. It can simply be passed into helpers that
4139 * with an identity mapping.4162 * are aware of idmapped mounts as a convenient shortcut. A user
4163 * can just create a dedicated identity mapping to achieve the same
4164 * result.
4140 */4165 */
4141 mnt_userns = container_of(ns, struct user_namespace, ns);4166 mnt_userns = container_of(ns, struct user_namespace, ns);
4142 if (mnt_userns == &init_user_ns) {4167 if (initial_idmapping(mnt_userns)) {
4143 err = -EPERM;4168 err = -EPERM;
4144 goto out_fput;4169 goto out_fput;
4145 }4170 }
fs/nfsd/export.c+1−1
@@ -427,7 +427,7 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) · 426 unmodified lines
427 return -EINVAL;427 return -EINVAL;
428 }428 }
429 429
430 if (mnt_user_ns(path->mnt) != &init_user_ns) {430 if (is_idmapped_mnt(path->mnt)) {
431 dprintk("exp_export: export of idmapped mounts not yet supported.\n");431 dprintk("exp_export: export of idmapped mounts not yet supported.\n");
432 return -EINVAL;432 return -EINVAL;
433 }433 }
fs/open.c+5−3
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include <linux/ima.h>32#include <linux/ima.h>
33#include <linux/dnotify.h>33#include <linux/dnotify.h>
34#include <linux/compat.h>34#include <linux/compat.h>
35#include <linux/mnt_idmapping.h>
35 36
36#include "internal.h"37#include "internal.h"
37 38
@@ -640,7 +641,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode) · 602 unmodified lines
640 641
641int chown_common(const struct path *path, uid_t user, gid_t group)642int chown_common(const struct path *path, uid_t user, gid_t group)
642{643{
643 struct user_namespace *mnt_userns;644 struct user_namespace *mnt_userns, *fs_userns;
644 struct inode *inode = path->dentry->d_inode;645 struct inode *inode = path->dentry->d_inode;
645 struct inode *delegated_inode = NULL;646 struct inode *delegated_inode = NULL;
646 int error;647 int error;
@@ -652,8 +653,9 @@ int chown_common(const struct path *path, uid_t user, gid_t group) · 5 unmodified lines
652 gid = make_kgid(current_user_ns(), group);653 gid = make_kgid(current_user_ns(), group);
653 654
654 mnt_userns = mnt_user_ns(path->mnt);655 mnt_userns = mnt_user_ns(path->mnt);
655 uid = kuid_from_mnt(mnt_userns, uid);656 fs_userns = i_user_ns(inode);
656 gid = kgid_from_mnt(mnt_userns, gid);657 uid = mapped_kuid_user(mnt_userns, fs_userns, uid);
658 gid = mapped_kgid_user(mnt_userns, fs_userns, gid);
657 659
658retry_deleg:660retry_deleg:
659 newattrs.ia_valid = ATTR_CTIME;661 newattrs.ia_valid = ATTR_CTIME;
fs/overlayfs/super.c+1−1
@@ -873,7 +873,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path) · 872 unmodified lines
873 pr_err("filesystem on '%s' not supported\n", name);873 pr_err("filesystem on '%s' not supported\n", name);
874 goto out_put;874 goto out_put;
875 }875 }
876 if (mnt_user_ns(path->mnt) != &init_user_ns) {876 if (is_idmapped_mnt(path->mnt)) {
877 pr_err("idmapped layers are currently not supported\n");877 pr_err("idmapped layers are currently not supported\n");
878 goto out_put;878 goto out_put;
879 }879 }
fs/posix_acl.c+11−6
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#include <linux/export.h>23#include <linux/export.h>
24#include <linux/user_namespace.h>24#include <linux/user_namespace.h>
25#include <linux/namei.h>25#include <linux/namei.h>
26#include <linux/mnt_idmapping.h>
26 27
27static struct posix_acl **acl_by_type(struct inode *inode, int type)28static struct posix_acl **acl_by_type(struct inode *inode, int type)
28{29{
@@ -374,7 +375,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode, · 345 unmodified lines
374 goto check_perm;375 goto check_perm;
375 break;376 break;
376 case ACL_USER:377 case ACL_USER:
377 uid = kuid_into_mnt(mnt_userns, pa->e_uid);378 uid = mapped_kuid_fs(mnt_userns,
379 i_user_ns(inode),
380 pa->e_uid);
378 if (uid_eq(uid, current_fsuid()))381 if (uid_eq(uid, current_fsuid()))
379 goto mask;382 goto mask;
380 break;383 break;
@@ -387,7 +390,9 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode, · 6 unmodified lines
387 }390 }
388 break;391 break;
389 case ACL_GROUP:392 case ACL_GROUP:
390 gid = kgid_into_mnt(mnt_userns, pa->e_gid);393 gid = mapped_kgid_fs(mnt_userns,
394 i_user_ns(inode),
395 pa->e_gid);
391 if (in_group_p(gid)) {396 if (in_group_p(gid)) {
392 found = 1;397 found = 1;
393 if ((pa->e_perm & want) == want)398 if ((pa->e_perm & want) == want)
@@ -734,17 +739,17 @@ static void posix_acl_fix_xattr_userns( · 340 unmodified lines
734 case ACL_USER:739 case ACL_USER:
735 uid = make_kuid(from, le32_to_cpu(entry->e_id));740 uid = make_kuid(from, le32_to_cpu(entry->e_id));
736 if (from_user)741 if (from_user)
737 uid = kuid_from_mnt(mnt_userns, uid);742 uid = mapped_kuid_user(mnt_userns, &init_user_ns, uid);
738 else743 else
739 uid = kuid_into_mnt(mnt_userns, uid);744 uid = mapped_kuid_fs(mnt_userns, &init_user_ns, uid);
740 entry->e_id = cpu_to_le32(from_kuid(to, uid));745 entry->e_id = cpu_to_le32(from_kuid(to, uid));
741 break;746 break;
742 case ACL_GROUP:747 case ACL_GROUP:
743 gid = make_kgid(from, le32_to_cpu(entry->e_id));748 gid = make_kgid(from, le32_to_cpu(entry->e_id));
744 if (from_user)749 if (from_user)
745 gid = kgid_from_mnt(mnt_userns, gid);750 gid = mapped_kgid_user(mnt_userns, &init_user_ns, gid);
746 else751 else
747 gid = kgid_into_mnt(mnt_userns, gid);752 gid = mapped_kgid_fs(mnt_userns, &init_user_ns, gid);
748 entry->e_id = cpu_to_le32(from_kgid(to, gid));753 entry->e_id = cpu_to_le32(from_kgid(to, gid));
749 break;754 break;
750 default:755 default:
fs/proc_namespace.c+1−1
@@ -80,7 +80,7 @@ static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt) · 79 unmodified lines
80 seq_puts(m, fs_infop->str);80 seq_puts(m, fs_infop->str);
81 }81 }
82 82
83 if (mnt_user_ns(mnt) != &init_user_ns)83 if (is_idmapped_mnt(mnt))
84 seq_puts(m, ",idmapped");84 seq_puts(m, ",idmapped");
85}85}
86 86
fs/xfs/xfs_inode.c+4−4
@@ -988,8 +988,8 @@ xfs_create( · 987 unmodified lines
988 /*988 /*
989 * Make sure that we have allocated dquot(s) on disk.989 * Make sure that we have allocated dquot(s) on disk.
990 */990 */
991 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns),991 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns),
992 mapped_fsgid(mnt_userns), prid,992 mapped_fsgid(mnt_userns, &init_user_ns), prid,
993 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,993 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
994 &udqp, &gdqp, &pdqp);994 &udqp, &gdqp, &pdqp);
995 if (error)995 if (error)
@@ -1142,8 +1142,8 @@ xfs_create_tmpfile( · 146 unmodified lines
1142 /*1142 /*
1143 * Make sure that we have allocated dquot(s) on disk.1143 * Make sure that we have allocated dquot(s) on disk.
1144 */1144 */
1145 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns),1145 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns),
1146 mapped_fsgid(mnt_userns), prid,1146 mapped_fsgid(mnt_userns, &init_user_ns), prid,
1147 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,1147 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
1148 &udqp, &gdqp, &pdqp);1148 &udqp, &gdqp, &pdqp);
1149 if (error)1149 if (error)
fs/xfs/xfs_linux.h+1−0
@@ -61,6 +61,7 @@ typedef __u32 xfs_nlink_t; · 60 unmodified lines
61#include <linux/ratelimit.h>61#include <linux/ratelimit.h>
62#include <linux/rhashtable.h>62#include <linux/rhashtable.h>
63#include <linux/xattr.h>63#include <linux/xattr.h>
64#include <linux/mnt_idmapping.h>
64 65
65#include <asm/page.h>66#include <asm/page.h>
66#include <asm/div64.h>67#include <asm/div64.h>
fs/xfs/xfs_symlink.c+2−2
@@ -184,8 +184,8 @@ xfs_symlink( · 183 unmodified lines
184 /*184 /*
185 * Make sure that we have allocated dquot(s) on disk.185 * Make sure that we have allocated dquot(s) on disk.
186 */186 */
187 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns),187 error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns),
188 mapped_fsgid(mnt_userns), prid,188 mapped_fsgid(mnt_userns, &init_user_ns), prid,
189 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,189 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
190 &udqp, &gdqp, &pdqp);190 &udqp, &gdqp, &pdqp);
191 if (error)191 if (error)
include/linux/fs.h+40−101
@@ -41,6 +41,7 @@ · 40 unmodified lines
41#include <linux/stddef.h>41#include <linux/stddef.h>
42#include <linux/mount.h>42#include <linux/mount.h>
43#include <linux/cred.h>43#include <linux/cred.h>
44#include <linux/mnt_idmapping.h>
44 45
45#include <asm/byteorder.h>46#include <asm/byteorder.h>
46#include <uapi/linux/fs.h>47#include <uapi/linux/fs.h>
@@ -1599,6 +1600,11 @@ struct super_block { · 1552 unmodified lines
1599 struct list_head s_inodes_wb; /* writeback inodes */1600 struct list_head s_inodes_wb; /* writeback inodes */
1600} __randomize_layout;1601} __randomize_layout;
1601 1602
1603static inline struct user_namespace *i_user_ns(const struct inode *inode)
1604{
1605 return inode->i_sb->s_user_ns;
1606}
1607
1602/* Helper functions so that in most cases filesystems will1608/* Helper functions so that in most cases filesystems will
1603 * not need to deal directly with kuid_t and kgid_t and can1609 * not need to deal directly with kuid_t and kgid_t and can
1604 * instead deal with the raw numeric values that are stored1610 * instead deal with the raw numeric values that are stored
@@ -1606,50 +1612,22 @@ struct super_block { · 1 unmodified line
1606 */1612 */
1607static inline uid_t i_uid_read(const struct inode *inode)1613static inline uid_t i_uid_read(const struct inode *inode)
1608{1614{
1609 return from_kuid(inode->i_sb->s_user_ns, inode->i_uid);1615 return from_kuid(i_user_ns(inode), inode->i_uid);
1610}1616}
1611 1617
1612static inline gid_t i_gid_read(const struct inode *inode)1618static inline gid_t i_gid_read(const struct inode *inode)
1613{1619{
1614 return from_kgid(inode->i_sb->s_user_ns, inode->i_gid);1620 return from_kgid(i_user_ns(inode), inode->i_gid);
1615}1621}
1616 1622
1617static inline void i_uid_write(struct inode *inode, uid_t uid)1623static inline void i_uid_write(struct inode *inode, uid_t uid)
1618{1624{
1619 inode->i_uid = make_kuid(inode->i_sb->s_user_ns, uid);1625 inode->i_uid = make_kuid(i_user_ns(inode), uid);
1620}1626}
1621 1627
1622static inline void i_gid_write(struct inode *inode, gid_t gid)1628static inline void i_gid_write(struct inode *inode, gid_t gid)
1623{1629{
1624 inode->i_gid = make_kgid(inode->i_sb->s_user_ns, gid);1630 inode->i_gid = make_kgid(i_user_ns(inode), gid);
1625}
1626
1627/**
1628 * kuid_into_mnt - map a kuid down into a mnt_userns
1629 * @mnt_userns: user namespace of the relevant mount
1630 * @kuid: kuid to be mapped
1631 *
1632 * Return: @kuid mapped according to @mnt_userns.
1633 * If @kuid has no mapping INVALID_UID is returned.
1634 */
1635static inline kuid_t kuid_into_mnt(struct user_namespace *mnt_userns,
1636 kuid_t kuid)
1637{
1638 return make_kuid(mnt_userns, __kuid_val(kuid));
1639}
1640
1641/**
1642 * kgid_into_mnt - map a kgid down into a mnt_userns
1643 * @mnt_userns: user namespace of the relevant mount
1644 * @kgid: kgid to be mapped
1645 *
1646 * Return: @kgid mapped according to @mnt_userns.
1647 * If @kgid has no mapping INVALID_GID is returned.
1648 */
1649static inline kgid_t kgid_into_mnt(struct user_namespace *mnt_userns,
1650 kgid_t kgid)
1651{
1652 return make_kgid(mnt_userns, __kgid_val(kgid));
1653}1631}
1654 1632
1655/**1633/**
@@ -1663,7 +1641,7 @@ static inline kgid_t kgid_into_mnt(struct user_namespace *mnt_userns, · 7 unmodified lines
1663static inline kuid_t i_uid_into_mnt(struct user_namespace *mnt_userns,1641static inline kuid_t i_uid_into_mnt(struct user_namespace *mnt_userns,
1664 const struct inode *inode)1642 const struct inode *inode)
1665{1643{
1666 return kuid_into_mnt(mnt_userns, inode->i_uid);1644 return mapped_kuid_fs(mnt_userns, i_user_ns(inode), inode->i_uid);
1667}1645}
1668 1646
1669/**1647/**
@@ -1677,69 +1655,7 @@ static inline kuid_t i_uid_into_mnt(struct user_namespace *mnt_userns, · 7 unmodified lines
1677static inline kgid_t i_gid_into_mnt(struct user_namespace *mnt_userns,1655static inline kgid_t i_gid_into_mnt(struct user_namespace *mnt_userns,
1678 const struct inode *inode)1656 const struct inode *inode)
1679{1657{
1680 return kgid_into_mnt(mnt_userns, inode->i_gid);1658 return mapped_kgid_fs(mnt_userns, i_user_ns(inode), inode->i_gid);
1681}
1682
1683/**
1684 * kuid_from_mnt - map a kuid up into a mnt_userns
1685 * @mnt_userns: user namespace of the relevant mount
1686 * @kuid: kuid to be mapped
1687 *
1688 * Return: @kuid mapped up according to @mnt_userns.
1689 * If @kuid has no mapping INVALID_UID is returned.
1690 */
1691static inline kuid_t kuid_from_mnt(struct user_namespace *mnt_userns,
1692 kuid_t kuid)
1693{
1694 return KUIDT_INIT(from_kuid(mnt_userns, kuid));
1695}
1696
1697/**
1698 * kgid_from_mnt - map a kgid up into a mnt_userns
1699 * @mnt_userns: user namespace of the relevant mount
1700 * @kgid: kgid to be mapped
1701 *
1702 * Return: @kgid mapped up according to @mnt_userns.
1703 * If @kgid has no mapping INVALID_GID is returned.
1704 */
1705static inline kgid_t kgid_from_mnt(struct user_namespace *mnt_userns,
1706 kgid_t kgid)
1707{
1708 return KGIDT_INIT(from_kgid(mnt_userns, kgid));
1709}
1710
1711/**
1712 * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns
1713 * @mnt_userns: user namespace of the relevant mount
1714 *
1715 * Use this helper to initialize a new vfs or filesystem object based on
1716 * the caller's fsuid. A common example is initializing the i_uid field of
1717 * a newly allocated inode triggered by a creation event such as mkdir or
1718 * O_CREAT. Other examples include the allocation of quotas for a specific
1719 * user.
1720 *
1721 * Return: the caller's current fsuid mapped up according to @mnt_userns.
1722 */
1723static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns)
1724{
1725 return kuid_from_mnt(mnt_userns, current_fsuid());
1726}
1727
1728/**
1729 * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns
1730 * @mnt_userns: user namespace of the relevant mount
1731 *
1732 * Use this helper to initialize a new vfs or filesystem object based on
1733 * the caller's fsgid. A common example is initializing the i_gid field of
1734 * a newly allocated inode triggered by a creation event such as mkdir or
1735 * O_CREAT. Other examples include the allocation of quotas for a specific
1736 * user.
1737 *
1738 * Return: the caller's current fsgid mapped up according to @mnt_userns.
1739 */
1740static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns)
1741{
1742 return kgid_from_mnt(mnt_userns, current_fsgid());
1743}1659}
1744 1660
1745/**1661/**
@@ -1753,7 +1669,7 @@ static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns) · 7 unmodified lines
1753static inline void inode_fsuid_set(struct inode *inode,1669static inline void inode_fsuid_set(struct inode *inode,
1754 struct user_namespace *mnt_userns)1670 struct user_namespace *mnt_userns)
1755{1671{
1756 inode->i_uid = mapped_fsuid(mnt_userns);1672 inode->i_uid = mapped_fsuid(mnt_userns, i_user_ns(inode));
1757}1673}
1758 1674
1759/**1675/**
@@ -1767,7 +1683,7 @@ static inline void inode_fsuid_set(struct inode *inode, · 7 unmodified lines
1767static inline void inode_fsgid_set(struct inode *inode,1683static inline void inode_fsgid_set(struct inode *inode,
1768 struct user_namespace *mnt_userns)1684 struct user_namespace *mnt_userns)
1769{1685{
1770 inode->i_gid = mapped_fsgid(mnt_userns);1686 inode->i_gid = mapped_fsgid(mnt_userns, i_user_ns(inode));
1771}1687}
1772 1688
1773/**1689/**
@@ -1784,10 +1700,18 @@ static inline void inode_fsgid_set(struct inode *inode, · 10 unmodified lines
1784static inline bool fsuidgid_has_mapping(struct super_block *sb,1700static inline bool fsuidgid_has_mapping(struct super_block *sb,
1785 struct user_namespace *mnt_userns)1701 struct user_namespace *mnt_userns)
1786{1702{
1787 struct user_namespace *s_user_ns = sb->s_user_ns;1703 struct user_namespace *fs_userns = sb->s_user_ns;
1704 kuid_t kuid;
1705 kgid_t kgid;
1788 1706
1789 return kuid_has_mapping(s_user_ns, mapped_fsuid(mnt_userns)) &&1707 kuid = mapped_fsuid(mnt_userns, fs_userns);
1790 kgid_has_mapping(s_user_ns, mapped_fsgid(mnt_userns));1708 if (!uid_valid(kuid))
1709 return false;
1710 kgid = mapped_fsgid(mnt_userns, fs_userns);
1711 if (!gid_valid(kgid))
1712 return false;
1713 return kuid_has_mapping(fs_userns, kuid) &&
1714 kgid_has_mapping(fs_userns, kgid);
1791}1715}
1792 1716
1793extern struct timespec64 current_time(struct inode *inode);1717extern struct timespec64 current_time(struct inode *inode);
@@ -2724,6 +2648,21 @@ static inline struct user_namespace *file_mnt_user_ns(struct file *file) · 930 unmodified lines
2724{2648{
2725 return mnt_user_ns(file->f_path.mnt);2649 return mnt_user_ns(file->f_path.mnt);
2726}2650}
2651
2652/**
2653 * is_idmapped_mnt - check whether a mount is mapped
2654 * @mnt: the mount to check
2655 *
2656 * If @mnt has an idmapping attached different from the
2657 * filesystem's idmapping then @mnt is mapped.
2658 *
2659 * Return: true if mount is mapped, false if not.
2660 */
2661static inline bool is_idmapped_mnt(const struct vfsmount *mnt)
2662{
2663 return mnt_user_ns(mnt) != mnt->mnt_sb->s_user_ns;
2664}
2665
2727extern long vfs_truncate(const struct path *, loff_t);2666extern long vfs_truncate(const struct path *, loff_t);
2728int do_truncate(struct user_namespace *, struct dentry *, loff_t start,2667int do_truncate(struct user_namespace *, struct dentry *, loff_t start,
2729 unsigned int time_attrs, struct file *filp);2668 unsigned int time_attrs, struct file *filp);
include/linux/mnt_idmapping.h+234−0
@@ -0,0 +1,234 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_MNT_IDMAPPING_H
3#define _LINUX_MNT_IDMAPPING_H
4
5#include <linux/types.h>
6#include <linux/uidgid.h>
7
8struct user_namespace;
9/*
10 * Carries the initial idmapping of 0:0:4294967295 which is an identity
11 * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is
12 * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...].
13 */
14extern struct user_namespace init_user_ns;
15
16/**
17 * initial_idmapping - check whether this is the initial mapping
18 * @ns: idmapping to check
19 *
20 * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1,
21 * [...], 1000 to 1000 [...].
22 *
23 * Return: true if this is the initial mapping, false if not.
24 */
25static inline bool initial_idmapping(const struct user_namespace *ns)
26{
27 return ns == &init_user_ns;
28}
29
30/**
31 * no_idmapping - check whether we can skip remapping a kuid/gid
32 * @mnt_userns: the mount's idmapping
33 * @fs_userns: the filesystem's idmapping
34 *
35 * This function can be used to check whether a remapping between two
36 * idmappings is required.
37 * An idmapped mount is a mount that has an idmapping attached to it that
38 * is different from the filsystem's idmapping and the initial idmapping.
39 * If the initial mapping is used or the idmapping of the mount and the
40 * filesystem are identical no remapping is required.
41 *
42 * Return: true if remapping can be skipped, false if not.
43 */
44static inline bool no_idmapping(const struct user_namespace *mnt_userns,
45 const struct user_namespace *fs_userns)
46{
47 return initial_idmapping(mnt_userns) || mnt_userns == fs_userns;
48}
49
50/**
51 * mapped_kuid_fs - map a filesystem kuid into a mnt_userns
52 * @mnt_userns: the mount's idmapping
53 * @fs_userns: the filesystem's idmapping
54 * @kuid : kuid to be mapped
55 *
56 * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this
57 * function when preparing a @kuid to be reported to userspace.
58 *
59 * If no_idmapping() determines that this is not an idmapped mount we can
60 * simply return @kuid unchanged.
61 * If initial_idmapping() tells us that the filesystem is not mounted with an
62 * idmapping we know the value of @kuid won't change when calling
63 * from_kuid() so we can simply retrieve the value via __kuid_val()
64 * directly.
65 *
66 * Return: @kuid mapped according to @mnt_userns.
67 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is
68 * returned.
69 */
70static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns,
71 struct user_namespace *fs_userns,
72 kuid_t kuid)
73{
74 uid_t uid;
75
76 if (no_idmapping(mnt_userns, fs_userns))
77 return kuid;
78 if (initial_idmapping(fs_userns))
79 uid = __kuid_val(kuid);
80 else
81 uid = from_kuid(fs_userns, kuid);
82 if (uid == (uid_t)-1)
83 return INVALID_UID;
84 return make_kuid(mnt_userns, uid);
85}
86
87/**
88 * mapped_kgid_fs - map a filesystem kgid into a mnt_userns
89 * @mnt_userns: the mount's idmapping
90 * @fs_userns: the filesystem's idmapping
91 * @kgid : kgid to be mapped
92 *
93 * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this
94 * function when preparing a @kgid to be reported to userspace.
95 *
96 * If no_idmapping() determines that this is not an idmapped mount we can
97 * simply return @kgid unchanged.
98 * If initial_idmapping() tells us that the filesystem is not mounted with an
99 * idmapping we know the value of @kgid won't change when calling
100 * from_kgid() so we can simply retrieve the value via __kgid_val()
101 * directly.
102 *
103 * Return: @kgid mapped according to @mnt_userns.
104 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is
105 * returned.
106 */
107static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns,
108 struct user_namespace *fs_userns,
109 kgid_t kgid)
110{
111 gid_t gid;
112
113 if (no_idmapping(mnt_userns, fs_userns))
114 return kgid;
115 if (initial_idmapping(fs_userns))
116 gid = __kgid_val(kgid);
117 else
118 gid = from_kgid(fs_userns, kgid);
119 if (gid == (gid_t)-1)
120 return INVALID_GID;
121 return make_kgid(mnt_userns, gid);
122}
123
124/**
125 * mapped_kuid_user - map a user kuid into a mnt_userns
126 * @mnt_userns: the mount's idmapping
127 * @fs_userns: the filesystem's idmapping
128 * @kuid : kuid to be mapped
129 *
130 * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this
131 * function when preparing a @kuid to be written to disk or inode.
132 *
133 * If no_idmapping() determines that this is not an idmapped mount we can
134 * simply return @kuid unchanged.
135 * If initial_idmapping() tells us that the filesystem is not mounted with an
136 * idmapping we know the value of @kuid won't change when calling
137 * make_kuid() so we can simply retrieve the value via KUIDT_INIT()
138 * directly.
139 *
140 * Return: @kuid mapped according to @mnt_userns.
141 * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is
142 * returned.
143 */
144static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns,
145 struct user_namespace *fs_userns,
146 kuid_t kuid)
147{
148 uid_t uid;
149
150 if (no_idmapping(mnt_userns, fs_userns))
151 return kuid;
152 uid = from_kuid(mnt_userns, kuid);
153 if (uid == (uid_t)-1)
154 return INVALID_UID;
155 if (initial_idmapping(fs_userns))
156 return KUIDT_INIT(uid);
157 return make_kuid(fs_userns, uid);
158}
159
160/**
161 * mapped_kgid_user - map a user kgid into a mnt_userns
162 * @mnt_userns: the mount's idmapping
163 * @fs_userns: the filesystem's idmapping
164 * @kgid : kgid to be mapped
165 *
166 * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this
167 * function when preparing a @kgid to be written to disk or inode.
168 *
169 * If no_idmapping() determines that this is not an idmapped mount we can
170 * simply return @kgid unchanged.
171 * If initial_idmapping() tells us that the filesystem is not mounted with an
172 * idmapping we know the value of @kgid won't change when calling
173 * make_kgid() so we can simply retrieve the value via KGIDT_INIT()
174 * directly.
175 *
176 * Return: @kgid mapped according to @mnt_userns.
177 * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is
178 * returned.
179 */
180static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns,
181 struct user_namespace *fs_userns,
182 kgid_t kgid)
183{
184 gid_t gid;
185
186 if (no_idmapping(mnt_userns, fs_userns))
187 return kgid;
188 gid = from_kgid(mnt_userns, kgid);
189 if (gid == (gid_t)-1)
190 return INVALID_GID;
191 if (initial_idmapping(fs_userns))
192 return KGIDT_INIT(gid);
193 return make_kgid(fs_userns, gid);
194}
195
196/**
197 * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns
198 * @mnt_userns: the mount's idmapping
199 * @fs_userns: the filesystem's idmapping
200 *
201 * Use this helper to initialize a new vfs or filesystem object based on
202 * the caller's fsuid. A common example is initializing the i_uid field of
203 * a newly allocated inode triggered by a creation event such as mkdir or
204 * O_CREAT. Other examples include the allocation of quotas for a specific
205 * user.
206 *
207 * Return: the caller's current fsuid mapped up according to @mnt_userns.
208 */
209static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns,
210 struct user_namespace *fs_userns)
211{
212 return mapped_kuid_user(mnt_userns, fs_userns, current_fsuid());
213}
214
215/**
216 * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns
217 * @mnt_userns: the mount's idmapping
218 * @fs_userns: the filesystem's idmapping
219 *
220 * Use this helper to initialize a new vfs or filesystem object based on
221 * the caller's fsgid. A common example is initializing the i_gid field of
222 * a newly allocated inode triggered by a creation event such as mkdir or
223 * O_CREAT. Other examples include the allocation of quotas for a specific
224 * user.
225 *
226 * Return: the caller's current fsgid mapped up according to @mnt_userns.
227 */
228static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns,
229 struct user_namespace *fs_userns)
230{
231 return mapped_kgid_user(mnt_userns, fs_userns, current_fsgid());
232}
233
234#endif /* _LINUX_MNT_IDMAPPING_H */
security/commoncap.c+9−6
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#include <linux/user_namespace.h>24#include <linux/user_namespace.h>
25#include <linux/binfmts.h>25#include <linux/binfmts.h>
26#include <linux/personality.h>26#include <linux/personality.h>
27#include <linux/mnt_idmapping.h>
27 28
28/*29/*
29 * If a non-root user executes a setuid-root binary in30 * If a non-root user executes a setuid-root binary in
@@ -418,7 +419,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns, · 388 unmodified lines
418 kroot = make_kuid(fs_ns, root);419 kroot = make_kuid(fs_ns, root);
419 420
420 /* If this is an idmapped mount shift the kuid. */421 /* If this is an idmapped mount shift the kuid. */
421 kroot = kuid_into_mnt(mnt_userns, kroot);422 kroot = mapped_kuid_fs(mnt_userns, fs_ns, kroot);
422 423
423 /* If the root kuid maps to a valid uid in current ns, then return424 /* If the root kuid maps to a valid uid in current ns, then return
424 * this as a nscap. */425 * this as a nscap. */
@@ -488,6 +489,7 @@ out_free: · 63 unmodified lines
488 * @size: size of @ivalue489 * @size: size of @ivalue
489 * @task_ns: user namespace of the caller490 * @task_ns: user namespace of the caller
490 * @mnt_userns: user namespace of the mount the inode was found from491 * @mnt_userns: user namespace of the mount the inode was found from
492 * @fs_userns: user namespace of the filesystem
491 *493 *
492 * If the inode has been found through an idmapped mount the user namespace of494 * If the inode has been found through an idmapped mount the user namespace of
493 * the vfsmount must be passed through @mnt_userns. This function will then495 * the vfsmount must be passed through @mnt_userns. This function will then
@@ -497,7 +499,8 @@ out_free: · 3 unmodified lines
497 */499 */
498static kuid_t rootid_from_xattr(const void *value, size_t size,500static kuid_t rootid_from_xattr(const void *value, size_t size,
499 struct user_namespace *task_ns,501 struct user_namespace *task_ns,
500 struct user_namespace *mnt_userns)502 struct user_namespace *mnt_userns,
503 struct user_namespace *fs_userns)
501{504{
502 const struct vfs_ns_cap_data *nscap = value;505 const struct vfs_ns_cap_data *nscap = value;
503 kuid_t rootkid;506 kuid_t rootkid;
@@ -507,7 +510,7 @@ static kuid_t rootid_from_xattr(const void *value, size_t size, · 3 unmodified lines
507 rootid = le32_to_cpu(nscap->rootid);510 rootid = le32_to_cpu(nscap->rootid);
508 511
509 rootkid = make_kuid(task_ns, rootid);512 rootkid = make_kuid(task_ns, rootid);
510 return kuid_from_mnt(mnt_userns, rootkid);513 return mapped_kuid_user(mnt_userns, fs_userns, rootkid);
511}514}
512 515
513static bool validheader(size_t size, const struct vfs_cap_data *cap)516static bool validheader(size_t size, const struct vfs_cap_data *cap)
@@ -553,12 +556,12 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry, · 39 unmodified lines
553 return -EINVAL;556 return -EINVAL;
554 if (!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_SETFCAP))557 if (!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_SETFCAP))
555 return -EPERM;558 return -EPERM;
556 if (size == XATTR_CAPS_SZ_2 && (mnt_userns == &init_user_ns))559 if (size == XATTR_CAPS_SZ_2 && (mnt_userns == fs_ns))
557 if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP))560 if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP))
558 /* user is privileged, just write the v2 */561 /* user is privileged, just write the v2 */
559 return size;562 return size;
560 563
561 rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns);564 rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns, fs_ns);
562 if (!uid_valid(rootid))565 if (!uid_valid(rootid))
563 return -EINVAL;566 return -EINVAL;
564 567
@@ -699,7 +702,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, · 134 unmodified lines
699 /* Limit the caps to the mounter of the filesystem702 /* Limit the caps to the mounter of the filesystem
700 * or the more limited uid specified in the xattr.703 * or the more limited uid specified in the xattr.
701 */704 */
702 rootkuid = kuid_into_mnt(mnt_userns, rootkuid);705 rootkuid = mapped_kuid_fs(mnt_userns, fs_ns, rootkuid);
703 if (!rootid_owns_currentns(rootkuid))706 if (!rootid_owns_currentns(rootkuid))
704 return -ENODATA;707 return -ENODATA;
705 708

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t