Skip to content

fix(sandbox): document unsafe blocks and enforce SAFETY comments with clippy - #5232

Open
EmilienM wants to merge 1 commit into
NVIDIA:mainfrom
EmilienM:fix/5188-sandbox-safety-comments/EmilienM
Open

EmilienM wants to merge 1 commit into
NVIDIA:mainfrom
EmilienM:fix/5188-sandbox-safety-comments/EmilienM

Conversation

@EmilienM

@EmilienM EmilienM commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Every non-test unsafe block in openshell-sandbox now carries a // SAFETY: comment stating its invariant, and clippy::undocumented_unsafe_blocks is enabled at warn level in the crate roots, so the CI clippy lanes fail the build on new undocumented blocks. The lint fires 89 times on main and zero times after this change.

reset_child_signal_dispositions gains a # Safety section. The vsock control stream reinterpreted as a UnixStream is documented in place: which operations it relies on being family-agnostic, which AF_UNIX members must never be called on it, and where the dial side does the same reinterpretation.

Related Issue

Closes #5188

Note: the issue is still awaiting state:accepted, so the PR Issue Acceptance job stays red until a maintainer accepts it.

Changes

  • 20 // SAFETY: comments on non-test unsafe blocks across boundary_server.rs (7), main.rs (6), network_broker.rs (3), process.rs (2), sandbox/linux/seccomp.rs (1), linux/seccomp_notify.rs (1)
  • # Safety section on reset_child_signal_dispositions (forked pre-exec child only)
  • #![warn(clippy::undocumented_unsafe_blocks)] in lib.rs, main.rs, and bin/seccomp-perf.rs, each with cfg_attr(test, allow) for the test-only blocks (after rebasing on fix(sandbox): zero-initialize sigset_t before assume_init #5194's signal-mask tests, main.rs needs the exemption too: their SAFETY comments sit above the assert_*! line, where the line-anchored lint can't see them)
  • 9 hoists/nested-if restructures and 2 statement reorderings so each comment sits on the line directly above its block (the lint is line-anchored); short-circuits and the errno adjacency the probe helpers rely on are preserved
  • 4 new tests pinning those properties: two run the self-protection probes against seccomp filters (one lets the FIOSETOWN ioctl through to the kernel, so a probe reading another syscall's errno fails), two cover the F_SETFL error arms in connect_exact

This is not a comment-only change: the movements are mechanical but real, and the tests exist because the existing suites are end-state based and cannot catch a wrong hoist.

Left as follow-ups on purpose:

  • multiple_unsafe_ops_per_block stays off: it is restriction-group and needs block splits at 7 production sites, one owned by bug: workload pre_exec hooks compile the seccomp filter and log after fork #5180
  • the ~70 test-only blocks stay exempt through cfg_attr(test, allow); documenting them would let the allow drop
  • a family-abstracted control-stream type would make the vsock constraint structural instead of comment-enforced
  • clippy::missing_safety_doc never fires on private bin fns, so the # Safety half of the acceptance criteria has no enforcement after this PR

Release Notes

Testing

  • Checks appropriate to the affected code and behavior pass: cargo clippy -p openshell-sandbox --all-targets (with and without --features perf-harness) with -D warnings, the workspace clippy lanes, and cargo fmt --check
  • Unit tests added/updated: the 4 tests above; cargo test -p openshell-sandbox green, plus the full workspace suite, server tests, and nextest groups locally
  • E2E tests added/updated: not applicable, no behavior change

The musl cross-check could not run locally (no musl C cross-compiler on this host); the only change near cfg(musl) code is a comment move.

@copy-pr-bot

copy-pr-bot Bot commented Nov 4, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@EmilienM
EmilienM marked this pull request as ready for review November 4, 2026 03:36
@mrunalp mrunalp added the area:sandbox Sandbox runtime and isolation work label Nov 4, 2026
@mrunalp

mrunalp commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

/ok to test 16d0012

@purp purp added area:runtime and removed area:sandbox Sandbox runtime and isolation work labels Nov 4, 2026
Comment thread crates/openshell-sandbox/src/main.rs Outdated
/// pipe. Assertions belong in the parent: a panic in the child would
/// unwind into a copy of the test harness.
#[allow(unsafe_code)]
fn fork_capture(child: impl FnOnce() -> Vec<u8>) -> Vec<u8> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could we run these probes in a fresh executable process using the existing current_exe() and --exact pattern?

Both fork_capture helpers run allocating Rust code after a raw fork, including filter preparation and to_vec(). This violates nix::fork's safety contract when the parent has multiple threads. Calling _exit afterward avoids inherited destructors, but doesn't make the preceding allocations safe.

If the child stalls on an inherited lock, the parent waits indefinitely in the pipe read.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 0d0372a: fork_capture is gone. Both probe tests now re-exec the test binary (current_exe + --exact + an env-var gate, the same pattern as managed_children), so the rlimit and seccomp changes land in a fresh process and no allocating code runs in a fork child. The parent also requires the child output to show it matched exactly one test, so a wrong --exact name cannot pass vacuously.

Comment thread crates/openshell-sandbox/src/main.rs Resolved
@EmilienM
EmilienM force-pushed the fix/5188-sandbox-safety-comments/EmilienM branch from 16d0012 to 0d0372a Compare November 5, 2026 14:39
shiju-nv
shiju-nv previously approved these changes Nov 5, 2026
… clippy

Every non-test unsafe block in openshell-sandbox now carries a
// SAFETY: comment stating its invariant, and
clippy::undocumented_unsafe_blocks is enabled at warn level in the
crate roots (lib, the sandbox bin, and the seccomp-perf bin), so the
CI clippy lanes with -D warnings fail the build on new undocumented
blocks. Test-only blocks are exempt through cfg_attr(test, allow) to
keep this change free of test-comment churn; the lint fires 89 times
on main and zero times after this change.

reset_child_signal_dispositions gains a # Safety section documenting
its caller contract (forked pre-exec child only), and the vsock
control stream reinterpreted as a UnixStream is documented in place:
the family-agnostic operations it relies on, the AF_UNIX members that
must never be called on it, and the dial-side twin of the same
reinterpretation.

Small mechanical edits were required so each comment sits on the line
directly above its unsafe block (the lint is line-anchored): nine
expressions hoisted into let bindings or nested ifs (five syscall
probes in main.rs, two F_SETFL guards in network_broker.rs, two in
boundary_server.rs), plus two reorderings (a timeout binding in
network_broker.rs, the SAFETY comment placement in seccomp_notify.rs).
Every movement preserves the original short-circuits and the errno
adjacency the probe helpers rely on, and four new tests pin those
properties: two run the self-protection probes against seccomp filters
(one lets the FIOSETOWN ioctl through to the kernel, so a probe that
reads another syscall's errno fails), and two cover the F_SETFL error
arms in connect_exact (an O_PATH descriptor for the transition
failure, a deny filter for the restore failure).

multiple_unsafe_ops_per_block is deliberately not enabled: it is
restriction-group and needs block splits at production sites owned by

Closes NVIDIA#5188

Signed-off-by: Emilien Macchi <emacchi@redhat.com>
@EmilienM
EmilienM force-pushed the fix/5188-sandbox-safety-comments/EmilienM branch from 0d0372a to 32c1957 Compare November 6, 2026 18:22
@FrostGod
FrostGod enabled auto-merge November 6, 2026 18:24
@FrostGod

FrostGod commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

/ok to test 32c1957

This branch has not been deployed

No deployments
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.

bug: unsafe blocks in openshell-sandbox lack // SAFETY: comments and nothing enforces them

5 participants