Skip to content

Resolve /dev/shm host paths in one place#228

Merged
jserv merged 1 commit into
sysprog21:mainfrom
henrybear327:fix/dev-shm-path-redirect
Jul 22, 2026
Merged

Resolve /dev/shm host paths in one place#228
jserv merged 1 commit into
sysprog21:mainfrom
henrybear327:fix/dev-shm-path-redirect

Conversation

@henrybear327

@henrybear327 henrybear327 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

macOS has no /dev/shm, so elfuse backs POSIX shared memory with a per-UID host directory, /tmp/elfuse-shm-<uid>/<name>, via the validated resolver proc_dev_shm_resolve (flat leaf only; "..", embedded '/', and empty names rejected).

Only three syscalls performed that redirect by hand: open, stat, and unlinkat. Every other path syscall fell through path_translate_at, which prepends the sysroot instead, so the same guest path resolved two different ways:

    /dev/shm/foo
      open  -> /tmp/elfuse-shm-1000/foo   (backing dir, created)
      chmod -> <sysroot>/dev/shm/foo      (nothing here -> ENOENT)

LTP's library startup (lib/tst_test.c setup_ipc) is failing to run all tests due to the following:

  • An open(O_CREAT|O_EXCL) on a /dev/shm path followed by SAFE_CHMOD of the same path
  • The open landed in the backing dir and succeeded
  • The chmod resolved the sysroot path, hit ENOENT, and aborted the process in common setup, so all 24 conformance tests failed before any test body ran.

The fix is to do the redirect once, in path_translate_at, through the same resolver and a new shm_redirect flag, so chmod, chown, truncate, utimensat, rename, link, symlink, mknod, readlink, mkdir, statfs, and the xattr family all inherit the backing path from one choke point.

The backing path is absolute and POSIX ignores dirfd for absolute paths, so path_tx_dirfd() selects AT_FDCWD and the hand-rolled unlinkat rewrite folds away.


Summary by cubic

Centralized /dev/shm path resolution so all path syscalls and exec use the same per-UID backing directory on macOS. Enforced never-follow and tmpfs reporting so shm symlinks cannot escape to the host; fixes LTP setup_ipc open(O_CREAT) → chmod failure.

  • Bug Fixes
    • Redirect /dev/shm/ in path_translate_at via the validated resolver and set is_dev_shm; use path_translation_dirfd for absolute redirects; remove the unlinkat special-case.
    • Enforce never-follow on shm paths: path_translation_at_flags adds AT_SYMLINK_NOFOLLOW on *at and xattr; lstat for stat and statfs leaf checks; exec image/interpreter opened with O_NOFOLLOW; truncate/chdir reach the leaf via a nofollow fd (O_NONBLOCK for FIFOs); clear AT_SYMLINK_FOLLOW on linkat; report /dev/shm and leaves as tmpfs (synthetic statfs, TMPFS_MAGIC).
    • Tighten name gate: allow flat names containing ".."; reject exact "..", '/', and empty with EACCES; return ENAMETOOLONG on overflow; use lstat in proc stat; refuse a /dev/shm interpreter during bootstrap.
    • Add test-dev-shm-paths: covers open→chmod, metadata ops, chdir/getcwd, rename/link/unlink, tmpfs statfs for root/leaves and FIFOs, symlink containment, exec of symlink refused and real binary runs, and name-shape/oversize gates; enabled in tests/manifest.txt.

Written for commit a89a59c. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

@jserv
jserv requested a review from Max042004 July 19, 2026 06:11

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Centralizing the /dev/shm redirect in path_translate_at is the right call, but the shared primitive now reaches follow-capable callers that were never taught to force nofollow. Inline notes below. Test gap: tests/test-dev-shm-paths.c exercises the symlink-not-followed case only for the metadata ops, not for statfs/chdir/execve on a symlink leaf.

Comment thread src/syscall/path.c Outdated
Comment thread src/syscall/fs.c Outdated
Comment thread src/syscall/fs.c Outdated
Comment thread src/runtime/procemu.c Outdated
@henrybear327
henrybear327 force-pushed the fix/dev-shm-path-redirect branch from 8cee1c5 to a93fac7 Compare July 20, 2026 18:53
Comment thread tests/test-dev-shm-paths.c Outdated
@henrybear327
henrybear327 force-pushed the fix/dev-shm-path-redirect branch 2 times, most recently from aa70bbf to 8769937 Compare July 22, 2026 18:28
macOS has no /dev/shm, so elfuse backs POSIX shared memory with a
per-UID host directory, /tmp/elfuse-shm-<uid>/<name>, via the validated
resolver proc_dev_shm_resolve. Only open, stat, and unlinkat did that
redirect by hand; every other path syscall fell through
path_translate_at, which prepends the sysroot, so one guest path
resolved two ways:

    /dev/shm/foo
      open  -> /tmp/elfuse-shm-1000/foo   (backing dir, created)
      chmod -> <sysroot>/dev/shm/foo      (absent -> ENOENT)

LTP's setup_ipc (lib/tst_test.c) hits this exactly: open(O_CREAT|O_EXCL)
then SAFE_CHMOD on the same path. The open succeeded in the backing
dir, the chmod hit ENOENT and aborted common setup, failing all 24
conformance tests before any test body ran.

Do the redirect once, in path_translate_at, behind an is_dev_shm flag,
so chmod, chown, truncate, utimensat, rename, link, symlink, mknod,
readlink, mkdir, statfs, and xattr all inherit the backing path from one
choke point. The backing path is absolute, so path_translation_dirfd()
selects AT_FDCWD and the hand-rolled unlinkat rewrite folds away.
@henrybear327
henrybear327 force-pushed the fix/dev-shm-path-redirect branch from 8769937 to a89a59c Compare July 22, 2026 19:17
@jserv
jserv merged commit c88bd27 into sysprog21:main Jul 22, 2026
10 checks passed
@jserv

jserv commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Thank @henrybear327 for contributing!

@henrybear327
henrybear327 deleted the fix/dev-shm-path-redirect branch July 22, 2026 19:26
@henrybear327
henrybear327 restored the fix/dev-shm-path-redirect branch July 22, 2026 19:57
@henrybear327
henrybear327 deleted the fix/dev-shm-path-redirect branch July 22, 2026 20:05
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.

2 participants