Skip to content

Resolve macOS system symlinks before the storage ancestor link assertion - #104

Merged
Blogbotana merged 2 commits into
Apibim-com:masterfrom
axisrow:ao/task-next-fork/promotion/macos-usd-symlink
Oct 20, 2026
Merged

Blogbotana merged 2 commits into
Apibim-com:masterfrom
axisrow:ao/task-next-fork/promotion/macos-usd-symlink

Conversation

@axisrow

@axisrow axisrow commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

Mirror of the fork's #24 (axisrow/BeamCraft), rebased onto upstream master 73c3597.
Two commits, verbatim:

  • Resolve macOS system symlinks before the storage ancestor link assertion (7882d18):
    the BlobStore's ancestor-link check canonicalises system symlink components (/var →
    /private/var) on macOS before asserting the root is link-free; the root itself stays
    link-free.
  • State the actual macOS ancestor link rule in the storage docs (d02fd16).

Without this, every usd_process store test fails on macOS, because std::env::temp_dir()
sits behind the /var symlink. Upstream master is red on macOS for the same reason
(verified 2026-10-20 on fd6fde9 and unchanged since).

How you verified it

  • cargo clippy -p beamcraft-host --all-targets -- -D warnings
  • cargo test -p beamcraft-host (host storage suite) and
    cargo test -p beamcraft-cli --test usd_process on macOS with a canonical TMPDIR
  • CI on this PR for Windows/Linux.

Provenance (clean-room)

  • Verbatim fork material, same MPL-2.0 project; no new assets or dependencies.

🤖 Generated with Claude Code

Issue tracking

Fixes #347

On macOS ordinary roots such as the temp directory sit behind sanctioned
system links (/var -> /private/var), so BlobStore::new rejected every
temp-dir root with UnsafeEntry and the usd_process suite failed on any
pristine macOS checkout while CI (Windows/Linux) stayed green. Canonicalise
ancestor components before the link assertion there and assert the resolved
directory instead; the supplied root itself and the behaviour on other
platforms stay unchanged. The ancestor-link storage test now expects the
store to bind to the resolved directory on macOS.

(cherry picked from commit 7882d18)
The comments claimed only sanctioned system links are canonicalised, but the code resolves any ancestor link on macOS; a reviewer pointed out the test's own user-created link proves it. Say exactly that so the documented contract matches the behaviour.

(cherry picked from commit d02fd16)

@axisrow axisrow left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Verdict: approved

Promotion of the fork macOS store-root fix, reviewed as a two-commit diff against upstream/master.

The relaxation is sound and correctly scoped:

  • absolute_directory is only ever called with the store root (host configuration, never an asset path — BlobStore::with_limit and check_root are the only callers), so the looser macOS ancestor rule does not touch any asset-derived path.
  • On macOS every non-final prefix is fs::canonicalize-ed and then asserted a real directory by directory (symlink-metadata based), so a dangling or non-directory ancestor still fails; each later iteration re-canonicalises the whole grown prefix, so there is no gap between a resolved ancestor and its children. The supplied root itself keeps the strict no-link check on every platform.
  • Off-macOS behaviour is byte-for-byte the old reject-all rule (cfg!(target_os = "macos") is a compile-time constant, both branches are portable std).
  • Post-open integrity is preserved: check_root re-runs the walk and compares canonicalize(root) against the stored canonical_root, so an ancestor link retargeted after open is still caught — either by the resolved-directory assertion or by the canonical-equality check. The same holds under the pre-existing, documented TOCTOU disclaimer.
  • ParentDir components are rejected before the walk, so the canonicalise branch can never be used to launder .. traversal on macOS.
  • The test split asserts the new macOS acceptance and keeps the non-macOS UnsafeEntry assertion; the honest "a user-created ancestor link passes too" limitation is stated in all three doc/comment sites.

Optional, not required: the macOS test could also assert store.canonical_root() equals the canonical target of the link to pin the "binds to the resolved directory" claim to the observable API; the shared canonical_root = canonicalize(root) code already guarantees it today.

@Blogbotana

Copy link
Copy Markdown
Member

Thank you for tracking down the macOS /var → /private/var failure.

We would like to keep this open but not merge it in its current form. On macOS the change canonicalises every ancestor link of the store root, so a user-created symlink above the root now passes as well. The ancestor check exists precisely to refuse such links (see the module doc in crates/host/src/storage.rs), so this widens what the store accepts on one platform.

Could you narrow it to one of these?

  1. Resolve only the sanctioned system links (/var, /tmp, /etc → /private/...) and keep refusing any other ancestor link, with a test that a user-created ancestor link is still refused on macOS; or
  2. Leave BlobStore strict and canonicalise the root at the caller that builds it from std::env::temp_dir(), as Canonicalise the usd_process temp root on macOS #105 already does for the usd_process fixtures.

If #105 alone makes the macOS suite green, option 2 may mean this PR is not needed at all — please let us know what you find.

@axisrow

axisrow commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

Extends the fix tracked in #133 (mirror of axisrow#23): resolves macOS system symlinks before the storage ancestor link assertion.

@Blogbotana
Blogbotana merged commit 07afcde into Apibim-com:master Oct 20, 2026
4 checks passed
@axisrow
axisrow deleted the ao/task-next-fork/promotion/macos-usd-symlink branch October 24, 2026 06:54
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.

PR #104: Resolve macOS system symlinks before the storage ancestor link assertion

2 participants