Skip to content

Commit d3cd67d

Browse files
committed
Merge tag 'fs.idmapped.fixes.v6.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping
Pull idmapping fixes from Christian Brauner: - Since Seth joined as co-maintainer for idmapped mounts we decided to use a shared git tree. Konstantin suggested we use vfs/idmapping.git on kernel.org under the vfs/ namespace. So this updates the tree in the maintainers file. - Ensure that POSIX ACLs checking, getting, and setting works correctly for filesystems mountable with a filesystem idmapping that want to support idmapped mounts. Since no filesystems mountable with an fs_idmapping do yet support idmapped mounts there is no problem. But this could change in the future, so add a check to refuse to create idmapped mounts when the mounter is not privileged over the mount's idmapping. - Check that caller is privileged over the idmapping that will be attached to a mount. Currently no FS_USERNS_MOUNT filesystems support idmapped mounts, thus this is not a problem as only CAP_SYS_ADMIN in init_user_ns is allowed to set up idmapped mounts. But this could change in the future, so add a check to refuse to create idmapped mounts when the mounter is not privileged over the mount's idmapping. - Fix POSIX ACLs for ntfs3. While looking at our current POSIX ACL handling in the context of some overlayfs work I went through a range of other filesystems checking how they handle them currently and encountered a few bugs in ntfs3. I've sent this some time ago and the fixes haven't been picked up even though the pull request for other ntfs3 fixes got sent after. This should really be fixed as right now POSIX ACLs are broken in certain circumstances for ntfs3. * tag 'fs.idmapped.fixes.v6.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping: ntfs: fix acl handling fs: require CAP_SYS_ADMIN in target namespace for idmapped mounts MAINTAINERS: update idmapping tree acl: handle idmapped mounts for idmapped filesystems
2 parents b20ee48 + 0c3bc78 commit d3cd67d

5 files changed

Lines changed: 31 additions & 20 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9781,7 +9781,7 @@ M: Christian Brauner <brauner@kernel.org>
97819781
M: Seth Forshee <sforshee@kernel.org>
97829782
L: linux-fsdevel@vger.kernel.org
97839783
S: Maintained
9784-
T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
9784+
T: git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git
97859785
F: Documentation/filesystems/idmappings.rst
97869786
F: tools/testing/selftests/mount_setattr/
97879787
F: include/linux/mnt_idmapping.h

fs/namespace.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4238,6 +4238,13 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
42384238
err = -EPERM;
42394239
goto out_fput;
42404240
}
4241+
4242+
/* We're not controlling the target namespace. */
4243+
if (!ns_capable(mnt_userns, CAP_SYS_ADMIN)) {
4244+
err = -EPERM;
4245+
goto out_fput;
4246+
}
4247+
42414248
kattr->mnt_userns = get_user_ns(mnt_userns);
42424249

42434250
out_fput:

fs/ntfs3/xattr.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,7 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name,
483483
}
484484

485485
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
486-
static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
487-
struct inode *inode, int type,
486+
static struct posix_acl *ntfs_get_acl_ex(struct inode *inode, int type,
488487
int locked)
489488
{
490489
struct ntfs_inode *ni = ntfs_i(inode);
@@ -519,7 +518,7 @@ static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
519518

520519
/* Translate extended attribute to acl. */
521520
if (err >= 0) {
522-
acl = posix_acl_from_xattr(mnt_userns, buf, err);
521+
acl = posix_acl_from_xattr(&init_user_ns, buf, err);
523522
} else if (err == -ENODATA) {
524523
acl = NULL;
525524
} else {
@@ -542,8 +541,7 @@ struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu)
542541
if (rcu)
543542
return ERR_PTR(-ECHILD);
544543

545-
/* TODO: init_user_ns? */
546-
return ntfs_get_acl_ex(&init_user_ns, inode, type, 0);
544+
return ntfs_get_acl_ex(inode, type, 0);
547545
}
548546

549547
static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
@@ -595,7 +593,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
595593
value = kmalloc(size, GFP_NOFS);
596594
if (!value)
597595
return -ENOMEM;
598-
err = posix_acl_to_xattr(mnt_userns, acl, value, size);
596+
err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
599597
if (err < 0)
600598
goto out;
601599
flags = 0;
@@ -646,7 +644,7 @@ static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
646644
if (!acl)
647645
return -ENODATA;
648646

649-
err = posix_acl_to_xattr(mnt_userns, acl, buffer, size);
647+
err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
650648
posix_acl_release(acl);
651649

652650
return err;
@@ -670,12 +668,12 @@ static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
670668
if (!value) {
671669
acl = NULL;
672670
} else {
673-
acl = posix_acl_from_xattr(mnt_userns, value, size);
671+
acl = posix_acl_from_xattr(&init_user_ns, value, size);
674672
if (IS_ERR(acl))
675673
return PTR_ERR(acl);
676674

677675
if (acl) {
678-
err = posix_acl_valid(mnt_userns, acl);
676+
err = posix_acl_valid(&init_user_ns, acl);
679677
if (err)
680678
goto release_and_out;
681679
}

fs/overlayfs/inode.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,21 +460,24 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
460460
* of the POSIX ACLs retrieved from the lower layer to this function to not
461461
* alter the POSIX ACLs for the underlying filesystem.
462462
*/
463-
static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
463+
static void ovl_idmap_posix_acl(struct inode *realinode,
464+
struct user_namespace *mnt_userns,
464465
struct posix_acl *acl)
465466
{
467+
struct user_namespace *fs_userns = i_user_ns(realinode);
468+
466469
for (unsigned int i = 0; i < acl->a_count; i++) {
467470
vfsuid_t vfsuid;
468471
vfsgid_t vfsgid;
469472

470473
struct posix_acl_entry *e = &acl->a_entries[i];
471474
switch (e->e_tag) {
472475
case ACL_USER:
473-
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, e->e_uid);
476+
vfsuid = make_vfsuid(mnt_userns, fs_userns, e->e_uid);
474477
e->e_uid = vfsuid_into_kuid(vfsuid);
475478
break;
476479
case ACL_GROUP:
477-
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, e->e_gid);
480+
vfsgid = make_vfsgid(mnt_userns, fs_userns, e->e_gid);
478481
e->e_gid = vfsgid_into_kgid(vfsgid);
479482
break;
480483
}
@@ -536,7 +539,7 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
536539
if (!clone)
537540
clone = ERR_PTR(-ENOMEM);
538541
else
539-
ovl_idmap_posix_acl(mnt_user_ns(realpath.mnt), clone);
542+
ovl_idmap_posix_acl(realinode, mnt_user_ns(realpath.mnt), clone);
540543
/*
541544
* Since we're not in RCU path walk we always need to release the
542545
* original ACLs.

fs/posix_acl.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
361361
const struct posix_acl *acl, int want)
362362
{
363363
const struct posix_acl_entry *pa, *pe, *mask_obj;
364+
struct user_namespace *fs_userns = i_user_ns(inode);
364365
int found = 0;
365366
vfsuid_t vfsuid;
366367
vfsgid_t vfsgid;
@@ -376,7 +377,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
376377
goto check_perm;
377378
break;
378379
case ACL_USER:
379-
vfsuid = make_vfsuid(mnt_userns, &init_user_ns,
380+
vfsuid = make_vfsuid(mnt_userns, fs_userns,
380381
pa->e_uid);
381382
if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
382383
goto mask;
@@ -390,7 +391,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
390391
}
391392
break;
392393
case ACL_GROUP:
393-
vfsgid = make_vfsgid(mnt_userns, &init_user_ns,
394+
vfsgid = make_vfsgid(mnt_userns, fs_userns,
394395
pa->e_gid);
395396
if (vfsgid_in_group_p(vfsgid)) {
396397
found = 1;
@@ -736,6 +737,7 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
736737
{
737738
struct posix_acl_xattr_header *header = value;
738739
struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
740+
struct user_namespace *fs_userns = i_user_ns(inode);
739741
int count;
740742
vfsuid_t vfsuid;
741743
vfsgid_t vfsgid;
@@ -753,13 +755,13 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
753755
switch (le16_to_cpu(entry->e_tag)) {
754756
case ACL_USER:
755757
uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
756-
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, uid);
758+
vfsuid = make_vfsuid(mnt_userns, fs_userns, uid);
757759
entry->e_id = cpu_to_le32(from_kuid(&init_user_ns,
758760
vfsuid_into_kuid(vfsuid)));
759761
break;
760762
case ACL_GROUP:
761763
gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
762-
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, gid);
764+
vfsgid = make_vfsgid(mnt_userns, fs_userns, gid);
763765
entry->e_id = cpu_to_le32(from_kgid(&init_user_ns,
764766
vfsgid_into_kgid(vfsgid)));
765767
break;
@@ -775,6 +777,7 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
775777
{
776778
struct posix_acl_xattr_header *header = value;
777779
struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
780+
struct user_namespace *fs_userns = i_user_ns(inode);
778781
int count;
779782
vfsuid_t vfsuid;
780783
vfsgid_t vfsgid;
@@ -793,13 +796,13 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
793796
case ACL_USER:
794797
uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
795798
vfsuid = VFSUIDT_INIT(uid);
796-
uid = from_vfsuid(mnt_userns, &init_user_ns, vfsuid);
799+
uid = from_vfsuid(mnt_userns, fs_userns, vfsuid);
797800
entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, uid));
798801
break;
799802
case ACL_GROUP:
800803
gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
801804
vfsgid = VFSGIDT_INIT(gid);
802-
gid = from_vfsgid(mnt_userns, &init_user_ns, vfsgid);
805+
gid = from_vfsgid(mnt_userns, fs_userns, vfsgid);
803806
entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, gid));
804807
break;
805808
default:

0 commit comments

Comments
 (0)