Skip to content

Check storage-admission observation ownership - #1206

Merged
rmcdaniel merged 1 commit into
mainfrom
fix/server-951-admission-owner
Nov 13, 2026
Merged

rmcdaniel merged 1 commit into
mainfrom
fix/server-951-admission-owner

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

A storage-admission record owned by an unrelated UID can currently look trustworthy because its mode is 0644. Check ownership on the same opened descriptor as type, mode and size: accept root or the Server effective UID, and turn a foreign-owned record into the existing fenced storage_admission_unavailable snapshot.

Document collector ownership, atomic replacement, container UID mapping and trusted parent directories. Final-component no-follow checks require trusted ancestors; the documentation makes that operational boundary explicit.

Validation: all four focused storage-admission tests pass, including real foreign-owned production readback, root/same-UID acceptance and atomic replacement. The ownership regression also passes separately as unprivileged UID 65534. Full exact-head required CI and Security review pass at cd59a48a; whitespace, public-boundary and added-source credential-pattern checks pass.

Follow-up to #951/#1192. The per-lease draining-upload slice remains on #951, and Cloud owns installed native mapping/file/missing/stale acceptance under Cloud#752. Immutable 3.9.1 is unchanged; this source fix ships in a later qualified release.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Downstream consumer review of cd59a48ab4913876e7377ef86f28f02c6858311b: the documented owner boundary is compatible with a root-run producer that creates a same-directory temporary file, sets0644, and atomically renames it into a trusted directory mounted read-only to a non-root Server. Mounting the directory preserves replacement visibility. The requirement to evaluate UID ownership inside the Server container is essential when user namespaces or other UID mappings are involved.

Installed consumer acceptance is still pending: it must demonstrate each replacement's descriptor owner/mode, trusted non-symlinked/non-writable ancestors, the actual container UID mapping, and missing/stale refusal against the exact published image. This review does not certify an enabled downstream native mapping or end-to-end adoption; those consumer gates remain open. No draining completion-upload acceptance is inferred.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security source review: PASS (content) at exact head cd59a48ab4913876e7377ef86f28f02c6858311b, tree dce70385a6cd769f852d9dcd96b3903d8a1bc0a1.

The trust decision is applied to the already-open observation descriptor: the final component is opened with O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC, regular-file/size/mode/UID checks use File::metadata() (descriptor metadata), and the bounded read uses that same descriptor. The accepted owners are exactly root or the process effective UID; group/other-writable files still fail closed. Atomic path replacement cannot substitute a different object between these checks and this read.

The root/current-user/foreign-user and atomic-replacement controls exercise the policy both through the production snapshot path and directly as an unprivileged reader. The documented deployment boundary is also accurate: trusted, non-untrusted-writable, non-symlinked ancestors remain an operator requirement and are not claimed as native runtime enforcement. This avoids overstating what the final-component O_NOFOLLOW check provides.

I found no draining-upload authority, route-classification, schema, 3.9.1, or Cloud deployment change in this two-file delta; git diff --check is clean. The initial 4 GiB SIGKILL remains correctly recorded as NONPASS and the 8 GiB focused result is properly scoped.

Merge remains held for the current exact-head required CI aggregate. This is not #951 closure or installed Cloud acceptance: Cloud still needs an admitted native observation bind and exact in-container UID/ancestor/missing/stale mapping under #752 before deployment. No live ancestor or user-namespace trust is inferred from this source review.

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 13, 2026 12:53
@rmcdaniel
rmcdaniel added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit 27c2eee Nov 13, 2026
64 checks passed
@rmcdaniel
rmcdaniel deleted the fix/server-951-admission-owner branch November 13, 2026 13:01
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security source review PASS for exact head cd59a48ab4913876e7377ef86f28f02c6858311b.

The ownership check is applied to metadata from the same already-opened, O_NOFOLLOW/nonblocking descriptor used for the bounded read. It accepts only root or the Server process's captured effective UID, while retaining the existing regular-file, size, group/other-write, JSON, schema/source, timestamp, and depth checks. A foreign-owned record therefore maps to the existing fail-closed storage_admission_unavailable snapshot; it does not create a new admission or error shape.

The focused regression covers production read() with a genuinely foreign-owned file when privileged, direct root/same-reader policy checks when unprivileged, root-owned acceptance, and atomic replacement back to the reader's ownership. All current exact-head required checks are green.

The documentation correctly keeps trusted ancestors as an operator requirement and explicitly states that native only refuses a symlink in the final component and does not establish parent-directory trust. This PASS therefore does not claim runtime ancestor enforcement, physical-capacity qualification, Cloud/container UID mapping acceptance, draining-upload authority, a #951 closure, or inclusion in immutable 3.9.1. Those remain separate gates as recorded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant