Preserve inherited target stdin authority
This commit is contained in:
parent
39307f4281
commit
f5455d1d6c
1 changed files with 109 additions and 7 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::os::fd::AsFd;
|
||||
use std::process::{ExitCode, Stdio};
|
||||
|
|
@ -50,6 +50,7 @@ fn run_all() -> std::io::Result<()> {
|
|||
successful_acquisition()?;
|
||||
transient_captured_child_preserves_streams_and_exit()?;
|
||||
terminal_child_restores_slave_stdin_and_merges_output()?;
|
||||
target_stdin_does_not_gain_write_authority()?;
|
||||
acknowledged_transition_precedes_exact_wrapper_release()?;
|
||||
failed_acknowledged_transition_refuses_exact_wrapper_release()?;
|
||||
lifetime_pipe_descriptor_contract()?;
|
||||
|
|
@ -61,6 +62,54 @@ fn run_all() -> std::io::Result<()> {
|
|||
concurrent_acquisitions_serialize()
|
||||
}
|
||||
|
||||
fn target_stdin_does_not_gain_write_authority() -> std::io::Result<()> {
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"lazaret-target-stdin-authority-{}-{}",
|
||||
std::process::id(),
|
||||
SEQUENCE.fetch_add(1, Ordering::Relaxed)
|
||||
));
|
||||
let mut source = OpenOptions::new()
|
||||
.create_new(true)
|
||||
.write(true)
|
||||
.open(&path)?;
|
||||
source.write_all(b"unchanged")?;
|
||||
drop(source);
|
||||
let stdin = OpenOptions::new().read(true).open(&path)?;
|
||||
let target = TargetCommand::new("/bin/sh")
|
||||
.argument("-c")
|
||||
.argument("printf changed >&0")
|
||||
.with_target_stdin(stdin)?;
|
||||
let expected_parent = current_process_identity()?;
|
||||
let ownership = ProcessOwnershipContext {
|
||||
domain_id: DomainId::new([45; 32]),
|
||||
generation_id: GenerationId::new(46),
|
||||
coordinator_id: CoordinatorId::new([47; 32]),
|
||||
slot: HostProcessOwnershipSlot::SessionTerminalExecClient(
|
||||
lazaret_core::identity::SessionId::new([48; 32]),
|
||||
),
|
||||
};
|
||||
let process = child_broker().acquire_with_stdio(
|
||||
expected_parent,
|
||||
ownership,
|
||||
&target,
|
||||
ChildStandardIo::silenced(),
|
||||
|_| Ok(()),
|
||||
|staged| Ok(ProcessOwnershipCommitAck::v1(staged)),
|
||||
)?;
|
||||
while !process.has_exited()? {
|
||||
std::thread::yield_now();
|
||||
}
|
||||
let exit = child_broker().reap_status(process)?;
|
||||
let contents = std::fs::read(&path);
|
||||
let _ = std::fs::remove_file(&path);
|
||||
if exit.exit_code == Some(0) || contents? != b"unchanged" {
|
||||
return Err(std::io::Error::other(format!(
|
||||
"read-only target stdin gained write authority: {exit:?}"
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn terminal_child_restores_slave_stdin_and_merges_output() -> std::io::Result<()> {
|
||||
let master = openpt(OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC)?;
|
||||
grantpt(&master)?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue