Skip to content

chroot: mediate path-based xattr syscalls under fs_mount#86

Merged
congwang-mk merged 1 commit into
mainfrom
fix/issue-84-xattr-mediation
Jun 2, 2026
Merged

chroot: mediate path-based xattr syscalls under fs_mount#86
congwang-mk merged 1 commit into
mainfrom
fix/issue-84-xattr-mediation

Conversation

@congwang-mk
Copy link
Copy Markdown
Contributor

Fixes #84.

Problem

Under chroot/fs_mount, the supervisor rewrites paths for openat/statx/newfstatat/readlinkat/etc., but not the xattr family. Path-based getxattr/lgetxattr/listxattr on a path under an fs_mount target therefore resolved against the real (empty) mount point and returned ENOENT, even though statx on the same path succeeded. This surfaced as ls -l printing a spurious No such file or directory (it probes xattrs for the ACL + / SELinux . indicator) and exiting non-zero.

Root cause

chroot_path_syscalls() enumerated every path-bearing syscall except the xattr family, so those syscalls never raised SECCOMP_RET_USER_NOTIF and fell straight through to the kernel with an un-rewritten path.

Fix

Three production changes, mirroring the existing statx/readlink handlers:

  1. context.rs — add the 8 path-based xattr syscalls ({,l}{get,set,list,remove}xattr) to the chroot notify set. The fd-based f*xattr variants are intentionally left unmediated (their fd already points at the resolved file).
  2. chroot/dispatch.rshandle_chroot_xattr: a single unified handler that classifies the syscall into one of four ops, resolves the path through the chroot/fs_mount/COW layers, gates on can_read/can_write, then re-issues the real syscall on the rewritten host path, marshalling the value/name/list buffers across the child boundary.
  3. seccomp/dispatch.rs — register the handler for all 8 syscalls.

Edge cases handled: size == 0 probe semantics preserved (passes NULL, returns the kernel's length); output buffer sized from the child's size arg and clamped to XATTR_MAX (64 KiB), which bounds allocation and can never cause a spurious ERANGE; failures on the resolve path return a proper errno rather than falling through to the kernel (which would re-expose the bug).

Tests

TDD: added getxattr/listxattr/setxattr applets to the test helper and three regression tests in test_fs_mount.py (read, list, and write-through), each watched failing (ENOENT, exit 1) before implementing. They skip cleanly on filesystems without user-xattr support.

Verified: exact issue repro now exits 0 with empty stderr; full suites green (315 core lib + 221 chroot integration + 328 Python).

Signed-off-by: Cong Wang <cwang@multikernel.io>
@congwang-mk congwang-mk merged commit eaa2260 into main Jun 2, 2026
9 checks passed
@congwang-mk congwang-mk deleted the fix/issue-84-xattr-mediation branch June 2, 2026 00:04
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.

'ls -l' reports spurious "No such file" under fs_mount (xattr syscalls not mediated)

2 participants