Skip to content

devices/fs: fix FUSE_ALLOW_IDMAP regression on Linux 6.12+#584

Closed
JAORMX wants to merge 1 commit intocontainers:mainfrom
JAORMX:fix/fuse-allow-idmap-posix-acl
Closed

devices/fs: fix FUSE_ALLOW_IDMAP regression on Linux 6.12+#584
JAORMX wants to merge 1 commit intocontainers:mainfrom
JAORMX:fix/fuse-allow-idmap-posix-acl

Conversation

@JAORMX
Copy link

@JAORMX JAORMX commented Mar 12, 2026

Context

Linux 6.12 added a check in fs/fuse/inode.c:process_init_reply that requires FUSE_POSIX_ACL to be present whenever FUSE_ALLOW_IDMAP is advertised. Without it, the kernel sets conn_error = 1, silently degrading the virtiofs connection. In this degraded state, reading and modifying existing files still works, but creating new files or directories fails with EPERM.

This breaks any setup where the host user's GID doesn't match the guest user's GID (e.g., host 1000:1001 vs guest 1000:1000), because the idmapped mount that would translate GIDs never gets established.

The problem

ALLOW_IDMAP was advertised from the server-global supported flags in server.rs, which meant it got enabled regardless of whether the backend could actually fulfill the POSIX_ACL contract that the kernel now requires alongside it.

What this does

Moves ALLOW_IDMAP out of the server-global supported mask and into each passthrough backend's init() return value, coupled with POSIX_ACL:

  1. If the kernel is capable of POSIX_ACL and the backend has xattr support enabled, advertise POSIX_ACL.
  2. Only then, if the kernel is also capable of ALLOW_IDMAP, advertise ALLOW_IDMAP alongside it.

This works for passthrough filesystems because the POSIX_ACL contract (mode-ACL synchronization, default ACL inheritance, ACL xattr storage) is fulfilled by the host kernel. The passthrough already forwards all xattr operations, including system.posix_acl_access and system.posix_acl_default, directly to the host via libc calls with no namespace filtering.

On kernels 6.2+, the FUSE VFS layer has fuse_get_acl() / fuse_set_acl() inode operations that handle idmapped UID/GID translation within ACL entries, so the passthrough server doesn't need to interpret ACL binary data itself.

Both the Linux and macOS passthrough backends are updated with the same logic so we don't regress macOS-hosted Linux guests.

Fixes #568

@JAORMX JAORMX marked this pull request as ready for review March 12, 2026 09:53
Linux 6.12 added a check in fs/fuse/inode.c:process_init_reply that
requires FUSE_POSIX_ACL to be present whenever FUSE_ALLOW_IDMAP is
advertised. Without it, the kernel sets conn_error = 1, silently
degrading the virtiofs connection. In this degraded state, reading and
modifying existing files still works, but creating new files or
directories fails with EPERM.

This breaks any setup where the host user's GID doesn't match the guest
user's GID (e.g., host 1000:1001 vs guest 1000:1000), because the
idmapped mount that would translate GIDs never gets established.

The root cause was that ALLOW_IDMAP was advertised from the server-global
"supported" flags in server.rs, which meant it got enabled regardless of
whether the backend could actually fulfill the POSIX_ACL contract that
the kernel now requires alongside it.

The fix moves ALLOW_IDMAP out of the server-global supported mask and
into each passthrough backend's init() return value, coupled with
POSIX_ACL. Now the negotiation looks like this:

  1. If the kernel is capable of POSIX_ACL and the backend has xattr
     support enabled, advertise POSIX_ACL.
  2. Only then, if the kernel is also capable of ALLOW_IDMAP, advertise
     ALLOW_IDMAP alongside it.

This works for passthrough filesystems because the POSIX_ACL contract
(mode-ACL synchronization, default ACL inheritance, ACL xattr storage)
is fulfilled by the host kernel. The passthrough already forwards all
xattr operations, including system.posix_acl_access and
system.posix_acl_default, directly to the host via libc calls with no
namespace filtering.

Note that on kernels 6.2+, the FUSE VFS layer has fuse_get_acl() and
fuse_set_acl() inode operations that handle idmapped UID/GID translation
within ACL entries, so the passthrough server doesn't need to interpret
ACL binary data itself.

Both the Linux and macOS passthrough backends are updated with the same
logic so we don't regress macOS-hosted Linux guests.

Fixes: containers#568
Signed-off-by: Juan Antonio Osorio <ozz@stacklok.com>
@JAORMX JAORMX force-pushed the fix/fuse-allow-idmap-posix-acl branch from 0253b8b to 951b4a4 Compare March 12, 2026 09:54
@slp
Copy link
Collaborator

slp commented Mar 12, 2026

The patch itself is probably right, but I have the same problem I had with #568, I can't reproduce it myself nor figure out in which context it can reproduced.

In both 6.12.x and master, virtio-fs sets ctx->default_permissions = 1, and I can't see any place where this is turned off:

fs/fuse/virtio_fs.c:1528

static inline void virtio_fs_ctx_set_defaults(struct fuse_fs_context *ctx)
{
        ctx->rootmode = S_IFDIR;
        ctx->default_permissions = 1;
        ctx->allow_other = 1;
        ctx->max_read = UINT_MAX;
        ctx->blksize = 512;
        ctx->destroy = true;
        ctx->no_control = true;
        ctx->no_force_umount = true;
}

Do you know where default_permissions is set to 0 in your kernel?

@JAORMX
Copy link
Author

JAORMX commented Mar 12, 2026

I was going down the rabbit hole, debugging a permissions issue I have with a project that leverages libkrun and I stumbled upon this. I did the PR, went for lunch, and afterwards was struggling to test it out.... turns out it doesn't actually solve the issue. So, yeah, I'll abandon this. I thought I had a reproducer but it turns out I don't.

@JAORMX JAORMX closed this Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

virtiofs: FUSE conn_error on Linux 6.12+ due to ALLOW_IDMAP without POSIX_ACL

2 participants