Compose cold-start resources under Runtime Supervisor ownership
This commit is contained in:
parent
510dfccf5a
commit
33ac0ba4ee
2 changed files with 1827 additions and 139 deletions
|
|
@ -2,13 +2,22 @@ use std::collections::BTreeMap;
|
|||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use lazaret_core::configuration::{
|
||||
ConfigurationLoadRequest, SandboxLayoutV1, load_trusted_configuration,
|
||||
};
|
||||
use lazaret_state_anchor::{ProtectedRuntimeFiles, StateAnchorLayout};
|
||||
use lazaret_core::identity::{
|
||||
DeviceId, HostPath, IdMapDigest, InodeId, PolicyId, PreparedArtifactId, SelectedManifestDigest,
|
||||
SourceIdentity,
|
||||
};
|
||||
use lazaret_core::records::{ArtifactState, PreparedArtifact};
|
||||
use lazaret_state_anchor::{
|
||||
ProtectedRuntimeFiles, RuntimeStateAnchorAuthority, StateAnchorLaunchAuthority,
|
||||
StateAnchorLayout,
|
||||
};
|
||||
|
||||
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
|
|
@ -48,6 +57,45 @@ fn replaced_runtime_root_is_refused_before_runtime_file_write() {
|
|||
assert!(!replacement_files.join("hosts").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inherited_runtime_authority_accepts_only_the_exact_prepared_lower() {
|
||||
let tree = TestTree::new();
|
||||
let configuration = configuration(&tree);
|
||||
let layout = StateAnchorLayout::create(&configuration).unwrap();
|
||||
let lower = tree.path.join("prepared-lower");
|
||||
fs::create_dir(&lower).unwrap();
|
||||
let metadata = lower.metadata().unwrap();
|
||||
let artifact = PreparedArtifact {
|
||||
prepared_artifact_id: PreparedArtifactId::new([8; 32]),
|
||||
source_identity: SourceIdentity::new(b"fixture".to_vec()),
|
||||
selected_manifest_digest: SelectedManifestDigest::new([9; 32]),
|
||||
policy_id: PolicyId::new([10; 32]),
|
||||
id_map_digest: IdMapDigest::new([11; 32]),
|
||||
path: HostPath::new(lower.as_os_str().as_encoded_bytes().to_vec()),
|
||||
device: DeviceId::new(metadata.dev()),
|
||||
inode: InodeId::new(metadata.ino()),
|
||||
state: ArtifactState::Available,
|
||||
};
|
||||
let launch = StateAnchorLaunchAuthority::capture(&layout, &artifact).unwrap();
|
||||
let expected = launch.expected_lower();
|
||||
RuntimeStateAnchorAuthority::from_inherited(
|
||||
launch.lower_fd(),
|
||||
launch.persistent_anchor_fd(),
|
||||
launch.runtime_anchor_fd(),
|
||||
expected,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
RuntimeStateAnchorAuthority::from_inherited(
|
||||
launch.lower_fd(),
|
||||
launch.persistent_anchor_fd(),
|
||||
launch.runtime_anchor_fd(),
|
||||
(expected.0, expected.1 + 1),
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
|
||||
struct TestTree {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ use lazaret_linux::process::{
|
|||
ProcessOwnershipContext, current_process_identity, dispatch_private_process_role,
|
||||
};
|
||||
use lazaret_state_anchor::{
|
||||
FuseOverlayfsMount, ProtectedRuntimeFiles, StateAnchorAcquisition, StateAnchorLayout,
|
||||
StateAnchorSandboxView, unmount_after_coordinator_loss,
|
||||
FuseOverlayfsMount, ProtectedRuntimeFiles, RuntimeStateAnchorAuthority, StateAnchorAcquisition,
|
||||
StateAnchorLaunchAuthority, StateAnchorLayout, StateAnchorSandboxView,
|
||||
unmount_after_coordinator_loss,
|
||||
};
|
||||
use rustix::process::Signal;
|
||||
|
||||
|
|
@ -77,6 +78,45 @@ fn run() -> io::Result<()> {
|
|||
};
|
||||
let layout = StateAnchorLayout::create(&configuration).map_err(io::Error::other)?;
|
||||
|
||||
let launch =
|
||||
StateAnchorLaunchAuthority::capture(&layout, &artifact).map_err(io::Error::other)?;
|
||||
let runtime_authority = RuntimeStateAnchorAuthority::from_inherited(
|
||||
launch.lower_fd(),
|
||||
launch.persistent_anchor_fd(),
|
||||
launch.runtime_anchor_fd(),
|
||||
launch.expected_lower(),
|
||||
)
|
||||
.map_err(io::Error::other)?;
|
||||
let expected = std::cell::Cell::new(None);
|
||||
let runtime_mount = runtime_authority
|
||||
.acquire(
|
||||
current_process_identity()?,
|
||||
ProcessOwnershipContext {
|
||||
domain_id: DomainId::new([1; 32]),
|
||||
generation_id: GenerationId::new(1),
|
||||
coordinator_id: CoordinatorId::new([3; 32]),
|
||||
slot: HostProcessOwnershipSlot::StateAnchorDaemon,
|
||||
},
|
||||
|staged| {
|
||||
expected.set(Some(staged));
|
||||
Ok(())
|
||||
},
|
||||
|staged| Ok(ProcessOwnershipCommitAck::v1(staged)),
|
||||
|readiness| {
|
||||
if expected.get() != Some(readiness.staged())
|
||||
|| lazaret_linux::filesystem::current_mount_identity(layout.merged())?
|
||||
!= readiness.mount()
|
||||
{
|
||||
return Err(io::Error::other(
|
||||
"inherited State Anchor readiness changed authority",
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.map_err(io::Error::other)?;
|
||||
runtime_mount.unmount().map_err(io::Error::other)?;
|
||||
|
||||
let first = acquire(&layout, &artifact)?;
|
||||
fs::write(
|
||||
layout.merged().join("usr/bin/installed-tool"),
|
||||
|
|
|
|||
Loading…
Reference in a new issue