Clarify sandbox causal edge descriptors

This commit is contained in:
ms2k 2026-07-15 19:17:30 +09:00
commit b653293840
3 changed files with 52 additions and 8 deletions

View file

@ -60,6 +60,12 @@ impl TargetCommand {
self
}
#[must_use]
pub fn with_parent_death_kill_edge(mut self) -> Self {
self.parent_action = ParentAction::Kill;
self
}
#[allow(clippy::disallowed_types)]
fn append_to(&self, command: &mut std::process::Command) {
command

View file

@ -44,7 +44,7 @@ fn exit(result: std::io::Result<()>) -> ExitCode {
fn run_all() -> std::io::Result<()> {
successful_acquisition()?;
lifetime_pipe_acquisition()?;
lifetime_pipe_descriptor_contract()?;
failed_stages_and_acknowledgments()?;
production_wrapper_refuses_former_harness_path()?;
malformed_barriers_refuse()?;
@ -54,11 +54,11 @@ fn run_all() -> std::io::Result<()> {
}
#[allow(clippy::disallowed_methods, clippy::disallowed_types)]
fn lifetime_pipe_acquisition() -> std::io::Result<()> {
let marker = marker("lifetime-pipe");
fn lifetime_pipe_descriptor_contract() -> std::io::Result<()> {
let held_pipe_marker = marker("lifetime-pipe");
let parent = current_process_identity()?;
let target = TargetCommand::new("/usr/bin/touch")
.argument(&marker)
.argument(&held_pipe_marker)
.with_lifetime_pipe_parent_edge();
let (lifetime_reader, lifetime_writer) = pipe_with(PipeFlags::CLOEXEC)?;
let process = child_broker().acquire_with_stdio(
@ -71,12 +71,49 @@ fn lifetime_pipe_acquisition() -> std::io::Result<()> {
)?;
child_broker().reap(process)?;
drop(lifetime_writer);
if !marker.is_file() {
if !held_pipe_marker.is_file() {
return Err(std::io::Error::other(
"lifetime-pipe acquisition did not execute its target",
));
}
std::fs::remove_file(marker)
std::fs::remove_file(held_pipe_marker)?;
let wrong_descriptor_marker = marker("lifetime-pipe-wrong-descriptor");
run_lifetime_pipe_target(&wrong_descriptor_marker, Stdio::null())?;
if wrong_descriptor_marker.exists() {
return Err(std::io::Error::other(
"non-pipe lifetime descriptor released its target",
));
}
let closed_pipe_marker = marker("lifetime-pipe-closed");
let (closed_reader, closed_writer) = pipe_with(PipeFlags::CLOEXEC)?;
drop(closed_writer);
run_lifetime_pipe_target(&closed_pipe_marker, Stdio::from(closed_reader))?;
if closed_pipe_marker.exists() {
return Err(std::io::Error::other(
"closed lifetime pipe released its target",
));
}
Ok(())
}
#[allow(clippy::disallowed_methods, clippy::disallowed_types)]
fn run_lifetime_pipe_target(marker: &std::path::Path, stderr: Stdio) -> std::io::Result<()> {
let parent = current_process_identity()?;
let target = TargetCommand::new("/usr/bin/touch")
.argument(marker)
.with_lifetime_pipe_parent_edge();
let process = child_broker().acquire_with_stdio(
parent,
context(),
&target,
ChildStandardIo::redirected(Stdio::null(), stderr),
|_| Ok(()),
|staged| Ok(ProcessOwnershipCommitAck::v1(staged)),
)?;
child_broker().reap(process)?;
Ok(())
}
fn marker(name: &str) -> std::path::PathBuf {

View file

@ -344,7 +344,7 @@ fn runsc_target(arguments: &RuntimeArguments, pid_file: i32) -> io::Result<Targe
for argument in &arguments.runsc_arguments[run + 1..] {
target = target.argument(argument);
}
Ok(target)
Ok(target.with_parent_death_kill_edge())
}
fn wait_for_runsc_ready(pid_file: &File, process: &RetainedProcess) -> io::Result<u32> {