Make State Anchor acquisition resumable and descriptor-confined

This commit is contained in:
ms2k 2026-07-15 17:27:39 +09:00
commit 48c10e9a7a

View file

@ -19,8 +19,8 @@ use lazaret_linux::process::{
ProcessOwnershipContext, current_process_identity, dispatch_private_process_role,
};
use lazaret_state_anchor::{
FuseOverlayfsMount, ProtectedRuntimeFiles, StateAnchorLayout, StateAnchorSandboxView,
unmount_after_coordinator_loss,
FuseOverlayfsMount, ProtectedRuntimeFiles, StateAnchorAcquisition, StateAnchorLayout,
StateAnchorSandboxView, unmount_after_coordinator_loss,
};
use rustix::process::Signal;
@ -121,8 +121,9 @@ fn run() -> io::Result<()> {
"runtime-file replacement escaped transient storage",
));
}
drop(view);
let wrong = lazaret_linux::filesystem::current_mount_identity(layout.upper())?;
if unmount_after_coordinator_loss(layout.merged(), wrong).is_ok() {
if unmount_after_coordinator_loss(&layout, wrong).is_ok() {
return Err(io::Error::other(
"ownership mismatch unmounted foreign identity",
));
@ -142,7 +143,7 @@ fn run() -> io::Result<()> {
while !second.process().has_exited()? {
std::thread::yield_now();
}
unmount_after_coordinator_loss(layout.merged(), identity).map_err(io::Error::other)?;
unmount_after_coordinator_loss(&layout, identity).map_err(io::Error::other)?;
second
.finish_after_external_unmount()
.map_err(io::Error::other)?;
@ -150,21 +151,23 @@ fn run() -> io::Result<()> {
Ok(())
}
fn acquire(
layout: &StateAnchorLayout,
fn acquire<'layout, 'configuration>(
layout: &'layout StateAnchorLayout<'configuration>,
artifact: &PreparedArtifact,
) -> io::Result<FuseOverlayfsMount> {
) -> io::Result<FuseOverlayfsMount<'layout, 'configuration>> {
let expected = std::cell::Cell::new(None);
FuseOverlayfsMount::acquire(
layout,
Path::new(std::ffi::OsStr::from_bytes(artifact.path.as_bytes())),
(artifact.device.get(), artifact.inode.get()),
current_process_identity()?,
ProcessOwnershipContext {
domain_id: DomainId::new([1; 32]),
generation_id: GenerationId::new(2),
coordinator_id: CoordinatorId::new([3; 32]),
slot: HostProcessOwnershipSlot::StateAnchorDaemon,
StateAnchorAcquisition {
lower: Path::new(std::ffi::OsStr::from_bytes(artifact.path.as_bytes())),
expected_lower: (artifact.device.get(), artifact.inode.get()),
expected_parent: current_process_identity()?,
ownership: ProcessOwnershipContext {
domain_id: DomainId::new([1; 32]),
generation_id: GenerationId::new(2),
coordinator_id: CoordinatorId::new([3; 32]),
slot: HostProcessOwnershipSlot::StateAnchorDaemon,
},
},
|staged| {
expected.set(Some(staged));
@ -176,6 +179,19 @@ fn acquire(
}
Ok(ProcessOwnershipCommitAck::v1(staged))
},
|readiness| {
if expected.get() != Some(readiness.staged()) {
return Err(io::Error::other("ready process identity changed"));
}
if lazaret_linux::filesystem::current_mount_identity(layout.merged())?
!= readiness.mount()
{
return Err(io::Error::other(
"readiness preceded exact mount verification",
));
}
Ok(())
},
)
.map_err(io::Error::other)
}