fix(sandbox): the four calls a compiler tree makes and a module does not - #4
Merged
Merged
Conversation
`dev/verify.sh` finally ran stages 58 and 59 under a kernel that denies
rather than watches, and both died: `cargo exited 159`, and
`` `initialize`: the server stopped``. Neither sentence names a syscall,
because `SECCOMP_RET_KILL_PROCESS` tells the program nothing — it tells
the kernel's audit log, and that is where these came from:
comm="cargo" syscall=73 flock
comm="rustc" syscall=265 linkat
comm="cargo" syscall=219 restart_syscall
comm="VfsLoader" syscall=294 inotify_init1
Reproduced here by installing the real filter and running a real
`cargo check` and a real `rust-analyzer` over LSP: every one of the four
was found by running the thing, and not one is visible in the source of
anything Thalyx wrote. `dev/foreign-agent-needs.sh` named the first two
on its own; `dmesg` named the rest.
- `restart_syscall` goes to `module_standard`, because the *kernel*
issues it: a signal that interrupts a blocking call rewrites the
register and re-enters, and the filter sees the re-entry. Without it
any module inside `futex` or `poll` when a signal lands is killed at a
moment nothing in the module chose. It permits nothing new — the only
call it can resume is one this filter already let through.
- `flock`, `linkat` and the three `inotify` calls go to a filter of the
provider's own, built from the module's rather than written out beside
it. Cargo locks its package cache, `rustc` hard-links its output into
place, and rust-analyzer's VfsLoader thread opens an inotify
descriptor the moment the server answers `initialize` — a thread, so
`KILL_PROCESS` took the whole server down.
- `socketpair` is **guarded to `AF_UNIX`** rather than allowed: Rust's
`std::process` hands a child's `execve` errno back over one of these,
and a compiler tree is nothing but spawned children. `socket` stays
denied on both filters, which is the decree the guard exists to keep,
and `a_socket_pair_is_not_a_socket` is the test that keeps it.
The `rust` check's Cargo now runs under `semantic_provider` too. It was
running under the module profile, which is what killed it — and a whole
`cargo check` does not fit in a module's gigabyte or its 512 processes
either. A check that names somebody else's program still gets the module
profile; widening that to suit Cargo would hand every named program a
compiler tree's filter for nothing.
Also: the five `contexto` tests had their own `$HOME/.rustup` search,
which is the exact failure `toolchain.rs` exists to end. Under `sudo`,
`HOME` is `/root`, so all five reported NOT PROVEN about a machine whose
analyzer `verify.sh` had just found and named in `THALYX_RUST_ANALYZER`.
They ask `thalyx_rust::analyzer::find()` now, like every other caller.
Still denied, and named here so it is not rediscovered as a bug:
rust-analyzer's `cargo metadata` over the *sysroot* calls `socket(AF_INET6)`
and is killed. It is a child, not the server — the server survives and
finishes loading — so it costs standard-library metadata and nothing else.
Allowing `socket` to buy it back would be the one door `Sandbox-Ejecucion.md`
refuses.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186Yyjz7VQsekbhvtFxQs4x
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.
dev/verify.shfinally ran stages 58 and 59 under a kernel that denies rather than watches, and both died:cargo exited 159, and`initialize`: the server stopped. Neither sentence names a syscall, becauseSECCOMP_RET_KILL_PROCESStells the program nothing — it tells the kernel's audit log, and that is where these came from:Reproduced here by installing the real filter and running a real
cargo checkand a realrust-analyzerover LSP: every one of the four was found by running the thing, and not one is visible in the source of anything Thalyx wrote.dev/foreign-agent-needs.shnamed the first two on its own;dmesgnamed the rest.restart_syscallgoes tomodule_standard, because the kernel issues it: a signal that interrupts a blocking call rewrites the register and re-enters, and the filter sees the re-entry. Without it any module insidefutexorpollwhen a signal lands is killed at a moment nothing in the module chose. It permits nothing new — the only call it can resume is one this filter already let through.flock,linkatand the threeinotifycalls go to a filter of the provider's own, built from the module's rather than written out beside it. Cargo locks its package cache,rustchard-links its output into place, and rust-analyzer's VfsLoader thread opens an inotify descriptor the moment the server answersinitialize— a thread, soKILL_PROCESStook the whole server down.socketpairis guarded toAF_UNIXrather than allowed: Rust'sstd::processhands a child'sexecveerrno back over one of these, and a compiler tree is nothing but spawned children.socketstays denied on both filters, which is the decree the guard exists to keep, anda_socket_pair_is_not_a_socketis the test that keeps it.The
rustcheck's Cargo now runs undersemantic_providertoo. It was running under the module profile, which is what killed it — and a wholecargo checkdoes not fit in a module's gigabyte or its 512 processes either. A check that names somebody else's program still gets the module profile; widening that to suit Cargo would hand every named program a compiler tree's filter for nothing.Also: the five
contextotests had their own$HOME/.rustupsearch, which is the exact failuretoolchain.rsexists to end. Undersudo,HOMEis/root, so all five reported NOT PROVEN about a machine whose analyzerverify.shhad just found and named inTHALYX_RUST_ANALYZER. They askthalyx_rust::analyzer::find()now, like every other caller.Still denied, and named here so it is not rediscovered as a bug: rust-analyzer's
cargo metadataover the sysroot callssocket(AF_INET6)and is killed. It is a child, not the server — the server survives and finishes loading — so it costs standard-library metadata and nothing else. Allowingsocketto buy it back would be the one doorSandbox-Ejecucion.mdrefuses.Claude-Session: https://claude.ai/code/session_0186Yyjz7VQsekbhvtFxQs4x