Skip to content

Commit 0fac198

Browse files
committed
Merge tag 'fs.idmapped.overlay.acl.v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux
Pull acl updates from Christian Brauner: "Last cycle we introduced support for mounting overlayfs on top of idmapped mounts. While looking into additional testing we realized that posix acls don't really work correctly with stacking filesystems on top of idmapped layers. We already knew what the fix were but it would require work that is more suitable for the merge window so we turned off posix acls for v5.19 for overlayfs on top of idmapped layers with Miklos routing my patch upstream in 72a8e05 ("Merge tag 'ovl-fixes-5.19-rc7' [..]"). This contains the work to support posix acls for overlayfs on top of idmapped layers. Since the posix acl fixes should use the new vfs{g,u}id_t work the associated branch has been merged in. (We sent a pull request for this earlier.) We've also pulled in Miklos pull request containing my patch to turn of posix acls on top of idmapped layers. This allowed us to avoid rebasing the branch which we didn't like because we were already at rc7 by then. Merging it in allows this branch to first fix posix acls and then to cleanly revert the temporary fix it brought in by commit 4a47c63 ("ovl: turn of SB_POSIXACL with idmapped layers temporarily"). The last patch in this series adds Seth Forshee as a co-maintainer for idmapped mounts. Seth has been integral to all of this work and is also the main architect behind the filesystem idmapping work which ultimately made filesystems such as FUSE and overlayfs available in containers. He continues to be active in both development and review. I'm very happy he decided to help and he has my full trust. This increases the bus factor which is always great for work like this. I'm honestly very excited about this because I think in general we don't do great in the bringing on new maintainers department" For more explanations of the ACL issues, see https://lore.kernel.org/all/20220801145520.1532837-1-brauner@kernel.org/ * tag 'fs.idmapped.overlay.acl.v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: Add Seth Forshee as co-maintainer for idmapped mounts Revert "ovl: turn of SB_POSIXACL with idmapped layers temporarily" ovl: handle idmappings in ovl_get_acl() acl: make posix_acl_clone() available to overlayfs acl: port to vfs{g,u}id_t acl: move idmapped mount fixup into vfs_{g,s}etxattr() mnt_idmapping: add vfs[g,u]id_into_k[g,u]id()
2 parents bdfae5c + ba40a57 commit 0fac198

13 files changed

Lines changed: 270 additions & 110 deletions

File tree

Documentation/filesystems/overlayfs.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,6 @@ overlay filesystem and the value of st_ino for filesystem objects may not be
466466
persistent and could change even while the overlay filesystem is mounted, as
467467
summarized in the `Inode properties`_ table above.
468468

469-
4) "idmapped mounts"
470-
When the upper or lower layers are idmapped mounts overlayfs will be mounted
471-
without support for POSIX Access Control Lists (ACLs). This limitation will
472-
eventually be lifted.
473469

474470
Changes to underlying filesystems
475471
---------------------------------

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9620,6 +9620,7 @@ F: drivers/input/misc/ideapad_slidebar.c
96209620

96219621
IDMAPPED MOUNTS
96229622
M: Christian Brauner <brauner@kernel.org>
9623+
M: Seth Forshee <sforshee@kernel.org>
96239624
L: linux-fsdevel@vger.kernel.org
96249625
S: Maintained
96259626
T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git

fs/ksmbd/vfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
963963
*/
964964
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
965965
struct dentry *dentry, const char *attr_name,
966-
const void *attr_value, size_t attr_size, int flags)
966+
void *attr_value, size_t attr_size, int flags)
967967
{
968968
int err;
969969

fs/ksmbd/vfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
109109
int attr_name_len);
110110
int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
111111
struct dentry *dentry, const char *attr_name,
112-
const void *attr_value, size_t attr_size, int flags);
112+
void *attr_value, size_t attr_size, int flags);
113113
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
114114
size_t *xattr_stream_name_size, int s_type);
115115
int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,

fs/overlayfs/inode.c

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -454,23 +454,94 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
454454
return res;
455455
}
456456

457+
/*
458+
* Apply the idmapping of the layer to POSIX ACLs. The caller must pass a clone
459+
* of the POSIX ACLs retrieved from the lower layer to this function to not
460+
* alter the POSIX ACLs for the underlying filesystem.
461+
*/
462+
static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
463+
struct posix_acl *acl)
464+
{
465+
for (unsigned int i = 0; i < acl->a_count; i++) {
466+
vfsuid_t vfsuid;
467+
vfsgid_t vfsgid;
468+
469+
struct posix_acl_entry *e = &acl->a_entries[i];
470+
switch (e->e_tag) {
471+
case ACL_USER:
472+
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, e->e_uid);
473+
e->e_uid = vfsuid_into_kuid(vfsuid);
474+
break;
475+
case ACL_GROUP:
476+
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, e->e_gid);
477+
e->e_gid = vfsgid_into_kgid(vfsgid);
478+
break;
479+
}
480+
}
481+
}
482+
483+
/*
484+
* When the relevant layer is an idmapped mount we need to take the idmapping
485+
* of the layer into account and translate any ACL_{GROUP,USER} values
486+
* according to the idmapped mount.
487+
*
488+
* We cannot alter the ACLs returned from the relevant layer as that would
489+
* alter the cached values filesystem wide for the lower filesystem. Instead we
490+
* can clone the ACLs and then apply the relevant idmapping of the layer.
491+
*
492+
* This is obviously only relevant when idmapped layers are used.
493+
*/
457494
struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
458495
{
459496
struct inode *realinode = ovl_inode_real(inode);
460-
const struct cred *old_cred;
461-
struct posix_acl *acl;
497+
struct posix_acl *acl, *clone;
498+
struct path realpath;
462499

463500
if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode))
464501
return NULL;
465502

466-
if (rcu)
467-
return get_cached_acl_rcu(realinode, type);
503+
/* Careful in RCU walk mode */
504+
ovl_i_path_real(inode, &realpath);
505+
if (!realpath.dentry) {
506+
WARN_ON(!rcu);
507+
return ERR_PTR(-ECHILD);
508+
}
468509

469-
old_cred = ovl_override_creds(inode->i_sb);
470-
acl = get_acl(realinode, type);
471-
revert_creds(old_cred);
510+
if (rcu) {
511+
acl = get_cached_acl_rcu(realinode, type);
512+
} else {
513+
const struct cred *old_cred;
514+
515+
old_cred = ovl_override_creds(inode->i_sb);
516+
acl = get_acl(realinode, type);
517+
revert_creds(old_cred);
518+
}
519+
/*
520+
* If there are no POSIX ACLs, or we encountered an error,
521+
* or the layer isn't idmapped we don't need to do anything.
522+
*/
523+
if (!is_idmapped_mnt(realpath.mnt) || IS_ERR_OR_NULL(acl))
524+
return acl;
472525

473-
return acl;
526+
/*
527+
* We only get here if the layer is idmapped. So drop out of RCU path
528+
* walk so we can clone the ACLs. There's no need to release the ACLs
529+
* since get_cached_acl_rcu() doesn't take a reference on the ACLs.
530+
*/
531+
if (rcu)
532+
return ERR_PTR(-ECHILD);
533+
534+
clone = posix_acl_clone(acl, GFP_KERNEL);
535+
if (!clone)
536+
clone = ERR_PTR(-ENOMEM);
537+
else
538+
ovl_idmap_posix_acl(mnt_user_ns(realpath.mnt), clone);
539+
/*
540+
* Since we're not in RCU path walk we always need to release the
541+
* original ACLs.
542+
*/
543+
posix_acl_release(acl);
544+
return clone;
474545
}
475546

476547
int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)

fs/overlayfs/overlayfs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
249249
const char *name, const void *value,
250250
size_t size, int flags)
251251
{
252-
int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name, value, size, flags);
252+
int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name,
253+
(void *)value, size, flags);
253254

254255
pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n",
255256
dentry, name, min((int)size, 48), value, size, flags, err);

fs/overlayfs/super.c

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,9 +1003,6 @@ ovl_posix_acl_xattr_get(const struct xattr_handler *handler,
10031003
struct dentry *dentry, struct inode *inode,
10041004
const char *name, void *buffer, size_t size)
10051005
{
1006-
if (!IS_POSIXACL(inode))
1007-
return -EOPNOTSUPP;
1008-
10091006
return ovl_xattr_get(dentry, inode, handler->name, buffer, size);
10101007
}
10111008

@@ -1021,9 +1018,6 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
10211018
struct posix_acl *acl = NULL;
10221019
int err;
10231020

1024-
if (!IS_POSIXACL(inode))
1025-
return -EOPNOTSUPP;
1026-
10271021
/* Check that everything is OK before copy-up */
10281022
if (value) {
10291023
acl = posix_acl_from_xattr(&init_user_ns, value, size);
@@ -1966,20 +1960,6 @@ static struct dentry *ovl_get_root(struct super_block *sb,
19661960
return root;
19671961
}
19681962

1969-
static bool ovl_has_idmapped_layers(struct ovl_fs *ofs)
1970-
{
1971-
1972-
unsigned int i;
1973-
const struct vfsmount *mnt;
1974-
1975-
for (i = 0; i < ofs->numlayer; i++) {
1976-
mnt = ofs->layers[i].mnt;
1977-
if (mnt && is_idmapped_mnt(mnt))
1978-
return true;
1979-
}
1980-
return false;
1981-
}
1982-
19831963
static int ovl_fill_super(struct super_block *sb, void *data, int silent)
19841964
{
19851965
struct path upperpath = { };
@@ -2149,10 +2129,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
21492129
sb->s_xattr = ofs->config.userxattr ? ovl_user_xattr_handlers :
21502130
ovl_trusted_xattr_handlers;
21512131
sb->s_fs_info = ofs;
2152-
if (ovl_has_idmapped_layers(ofs))
2153-
pr_warn("POSIX ACLs are not yet supported with idmapped layers, mounting without ACL support.\n");
2154-
else
2155-
sb->s_flags |= SB_POSIXACL;
2132+
sb->s_flags |= SB_POSIXACL;
21562133
sb->s_iflags |= SB_I_SKIP_SYNC;
21572134

21582135
err = -ENOMEM;

0 commit comments

Comments
 (0)