Conversation
8f51995 to
befeff9
Compare
A rootless macOS host cannot chown a file to an arbitrary uid/gid, so
the existing fallback turns the host EPERM into no-op success. Follow-up
stat still returns the host's real owner instead of the value the guest
just chowned to, which trips programs that diff metadata after extraction
(tar --same-owner, cp -p, rsync -a, install -o user, dpkg, Python
shutil.chown + os.stat).
Add a small (dev, ino) -> (uid, gid) overlay keyed by host stat.
sys_fchown{at} record the intent on EPERM and on host success alike,
with the partial-chown -1 sentinel preserving the prior field. The
stat-family wrappers in src/syscall/fs-stat.c consult the overlay once
before translating struct stat into linux_stat[x]_t, so fstat /
newfstatat / statx all pick up the override automatically. The set helper
auto-prunes entries whose final (uid, gid) matches host's current values,
so a guest that resets to the host owner walks away with a clean table.
Host inode reuse is defended by hooks in sys_unlinkat, sys_renameat2,
and sys_close: stat the identity before the operation, and clear the
overlay only when no other path or open fd still references the same
(dev, ino). Forked children inherit the overlay through a new
chown_overlay_{send,recv} on the existing fork IPC socket. The recv
helper reads records into a transient heap buffer before taking the lock
so blocking IO does not serialize sibling stats; it also rejects
out-of-band record counts.
stat is hot. The lock is a pthread_rwlock_t with apply / send taking the
read lock and set / clear / recv taking the write lock; an atomic entry
counter lets apply skip the lock entirely when no overrides exist.
The fork IPC header drops the standalone version field. The first header
word is the protocol identity: bumping FORK_IPC_PROTOCOL_MAGIC
(0x454C464C, "ELFL") replaces what bumping IPC_VERSION used to do, with
one fewer field on the wire and one fewer concept in the code.
Close #59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A rootless macOS host cannot chown a file to an arbitrary uid/gid, so the existing fallback turns the host EPERM into no-op success. Follow-up stat still returns the host's real owner instead of the value the guest just chowned to, which trips programs that diff metadata after extraction (tar --same-owner, cp -p, rsync -a, install -o user, dpkg, Python shutil.chown + os.stat).
Add a small (dev, ino) -> (uid, gid) overlay keyed by host stat. sys_fchownat and sys_fchown record the intent on EPERM and on host success alike, with the partial-chown -1 sentinel preserving the prior field. The stat-family wrappers in src/syscall/fs-stat.c consult the overlay once before translating struct stat into linux_stat[x]_t, so fstat / newfstatat / statx all pick up the override automatically. The set helper auto-prunes entries whose final (uid, gid) matches host's current values, so a guest that resets to the host owner walks away with a clean table.
Host inode reuse is defended by hooks in sys_unlinkat, sys_renameat2, and sys_close: stat the identity before the operation, and clear the overlay only when no other path or open fd still references the same (dev, ino). Forked children inherit the overlay through a new chown_overlay_send / chown_overlay_recv pair on the existing fork IPC socket. The recv helper reads records into a transient heap buffer before taking the lock so blocking IO does not serialize sibling stats; it also rejects out-of-band record counts.
stat is hot. The lock is a pthread_rwlock_t with apply / send taking the read lock and set / clear / recv taking the write lock; an atomic entry counter lets apply skip the lock entirely when no overrides exist.
The fork IPC header drops the standalone version field. The first header word is the protocol identity: bumping FORK_IPC_PROTOCOL_MAGIC (0x454C464C, "ELFL") replaces what bumping IPC_VERSION used to do, with one fewer field on the wire and one fewer concept in the code.
Summary by cubic
Adds a virtual ownership overlay so
chownon rootless macOS records intended uid/gid even when the host returns EPERM, and thestatfamily returns those values. Also moves fork IPC to a protocol magic, carries the overlay acrossfork, and adds tests.New Features
chownsuccess or EPERM; honor-1partial updates; auto-prune when matching the host.stat/fstat/newfstatat/statx, keyed by(st_dev, st_ino)so it survives renames and covers hard links.unlink, rename-overwrite, and when the last open fd to an unlinked inode closes.chownerrors propagate;fchownaton EPERM returnsEAGAINif the path changed during the call; returnENOMEMif an overlay entry cannot be allocated. Tests: addtest-chown-overlay(chown/fchown/fchownat,-1, symlink nofollow, unlink/last-fd, fork), wired intomake check.Refactors
FORK_IPC_PROTOCOL_MAGIC("ELFL") as the protocol identity; removedIPC_VERSION;has_shmandis_rosettaarebool.test-fork-ipc-protocol-hostand build/test targets; run as part ofmake check.Written for commit c0e6de9. Summary will update on new commits.