From: Tarun Khandelwal <[email protected]> fuse_fill_super_common() always sets SB_POSIXACL on the superblock, but fuse_fill_super_submount() never does. Submount superblocks are created from an fs_context with no sb_flags, so the superblock of an automounted FUSE_ATTR_SUBMOUNT directory (e.g. a virtiofs export containing another host mount) lacks SB_POSIXACL, even though it shares the fuse_conn, and thus fc->posix_acl, with its parent.
Since IS_POSIXACL() is false on such a submount, the VFS: - fails setting POSIX ACLs with -EOPNOTSUPP and hides existing ACLs, without sending any request to the server; - applies the umask itself on create, so default ACLs on the server are not honoured for new files; - skips ACL checks in acl_permission_check(), so with default_permissions (implied by FUSE_POSIX_ACL) access is decided by the mode bits alone and restrictive ACL entries are not enforced. Copy SB_POSIXACL from the parent superblock, as is already done for the other superblock fields inherited from it. It cannot be set in fuse_sb_defaults(), because fuse_fill_super_common() checks whether the flag was passed at mount time to decide fc->dont_mask before setting it. Reproducer, with virtiofsd 1.10.0 started with --posix-acl and an export containing a nested mount: host# mount -t tmpfs none /srv/share host# mkdir /srv/share/child host# mount -t tmpfs none /srv/share/child host# touch /srv/share/rootfile /srv/share/child/childfile guest# mount -t virtiofs <tag> /mnt guest# setfacl -m u:12345:rw /mnt/rootfile # works guest# setfacl -m u:12345:rw /mnt/child/childfile setfacl: /mnt/child/childfile: Operation not supported With this patch the second setfacl succeeds, ACLs set on the host are reported by getfacl on the submount, and default ACLs and ACL-based access checks behave the same as on the root mount. Tested on v7.3-rc5 in a QEMU guest. Signed-off-by: Tarun Khandelwal <[email protected]> --- I wasn't sure whether leaving SB_POSIXACL off submount superblocks was intentional. I would have opened an issue first, but since the fix is a one-liner I'm sending the patch directly. If there is a reason for the current behaviour, I'm happy to rework this or drop it. fs/fuse/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e9552be36..ef3c7fac4 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1629,6 +1629,8 @@ static int fuse_fill_super_submount(struct super_block *sb, WARN_ON(sb->s_bdi != &noop_backing_dev_info); sb->s_bdi = bdi_get(parent_sb->s_bdi); + sb->s_flags |= parent_sb->s_flags & SB_POSIXACL; + sb->s_xattr = parent_sb->s_xattr; sb->s_export_op = parent_sb->s_export_op; sb->s_time_gran = parent_sb->s_time_gran; -- 2.43.0

