Own the patched runsc artifact and bind recovery identity

This commit is contained in:
ms2k 2026-07-26 18:01:03 +09:00
commit 2c420012bd
3 changed files with 1967 additions and 130 deletions

View file

@ -11,8 +11,9 @@ use lazaret_core::identity::{
HostPidLocator, IdMapDigest, InodeId, MountId, MountIdentity, NamespaceIdentity,
NetworkSidecarId, PidfsDeviceId, PidfsInodeId, PidfsProcessAuthorityV1, PidfsProcessIdentityV1,
PolicyId, PrepareOperationId, PreparedArtifactId, ProcessStartTimeTicks, ProtocolCredentialId,
ReadinessFingerprint, RequestDigest, RequestId, SandboxId, SelectedManifestDigest,
SessionAnchorId, SessionId, SourceIdentity, StreamDigest, TrustManifestDigest,
ReadinessFingerprint, RequestDigest, RequestId, RunscBuildId, RunscDigest, SandboxId,
SelectedManifestDigest, SessionAnchorId, SessionId, SourceIdentity, StreamDigest,
TrustManifestDigest,
};
use lazaret_core::network::readiness_fingerprint as derive_readiness_fingerprint;
use lazaret_core::protocol::{BootstrapWaitOutcome, BootstrapWaitRequest};
@ -27,6 +28,33 @@ struct SchemaCorpus {
digest: Sha256,
}
#[test]
fn sandbox_ownership_decodes_records_without_runsc_identity() {
#[derive(Serialize)]
struct LegacySandboxOwnership {
container_id: Option<ContainerId>,
runtime_root: Option<HostPath>,
runtime_root_identity: Option<MountIdentity>,
bundle_digest: Option<BundleDigest>,
host_coordinator: PersistedHostProcessOwnership,
runtime_supervisor: PersistedHostProcessOwnership,
attached_runsc: PersistedHostProcessOwnership,
}
let encoded = postcard::to_stdvec(&LegacySandboxOwnership {
container_id: None,
runtime_root: None,
runtime_root_identity: None,
bundle_digest: None,
host_coordinator: PersistedHostProcessOwnership::unassigned(),
runtime_supervisor: PersistedHostProcessOwnership::unassigned(),
attached_runsc: PersistedHostProcessOwnership::unassigned(),
})
.unwrap();
let decoded = postcard::from_bytes::<SandboxOwnership>(&encoded).unwrap();
assert!(decoded.attached_runsc.is_unassigned());
}
impl SchemaCorpus {
fn insert(&mut self, name: &'static str, encoded: &[u8]) -> bool {
self.digest.update(name.len().to_be_bytes());
@ -529,7 +557,13 @@ fn complete_ownership(role: ParticipantRole, state: ParticipantState) -> Partici
bundle_digest: Some(BundleDigest::new(opaque(43))),
host_coordinator: owned_process(30),
runtime_supervisor: owned_process(21),
attached_runsc: owned_process(44),
attached_runsc: PersistedHostProcessOwnership::Runsc {
build_id: RunscBuildId::new(opaque(44)),
digest: RunscDigest::new(opaque(45)),
process: RunscProcessOwnership::Committed(HostProcessIdentity::pidfs_v1(process(
44,
))),
},
}),
ParticipantRole::Publication => ParticipantOwnership::Publication(PublicationOwnership {
staged_socket_path: Some(HostPath::new(b"staged-socket".to_vec())),

View file

@ -129,6 +129,7 @@ fn every_schema_shape_round_trips_and_rejects_malformed_or_unknown_versions() {
PersistedHostProcessOwnership::staged(pidfs_identity),
&mut seen,
);
verify_shape(RunscProcessOwnership::Staged(pidfs_identity), &mut seen);
verify_shape(
HostProcessOwnershipSlot::SessionTerminalExecClient(session_id()),
&mut seen,
@ -425,7 +426,13 @@ fn every_schema_shape_round_trips_and_rejects_malformed_or_unknown_versions() {
bundle_digest: Some(BundleDigest::new(opaque(66))),
host_coordinator: owned_process(30),
runtime_supervisor: owned_process(21),
attached_runsc: owned_process(67),
attached_runsc: PersistedHostProcessOwnership::Runsc {
build_id: RunscBuildId::new(opaque(67)),
digest: RunscDigest::new(opaque(71)),
process: RunscProcessOwnership::Committed(HostProcessIdentity::pidfs_v1(process(
67,
))),
},
},
&mut seen,
);
@ -642,8 +649,8 @@ persistent_dirs = []
assert_eq!(
seen.digest(),
[
23, 80, 80, 177, 148, 141, 234, 213, 240, 108, 167, 148, 252, 121, 212, 128, 5, 195,
176, 126, 71, 76, 141, 196, 174, 125, 212, 31, 115, 155, 178, 139,
54, 187, 13, 149, 227, 157, 1, 54, 234, 66, 127, 9, 34, 65, 173, 20, 214, 200, 126, 67,
1, 216, 152, 76, 167, 32, 177, 218, 0, 192, 175, 28,
]
);
}

View file

@ -52,6 +52,17 @@ fn lifecycle_corpus(digest: &mut Sha256) {
PersistedHostProcessOwnership::Unassigned => PersistedHostProcessOwnership::unassigned(),
PersistedHostProcessOwnership::Staged(_) => PersistedHostProcessOwnership::staged(process(1)),
PersistedHostProcessOwnership::Committed(_) => PersistedHostProcessOwnership::committed(process(2)),
PersistedHostProcessOwnership::Runsc { .. } => PersistedHostProcessOwnership::runsc_unassigned(
RunscBuildId::new(opaque(3)),
RunscDigest::new(opaque(4)),
),
});
enum_corpus!(digest, RunscProcessOwnership, {
RunscProcessOwnership::Unassigned => RunscProcessOwnership::Unassigned,
RunscProcessOwnership::Staged(_) => RunscProcessOwnership::Staged(process(5)),
RunscProcessOwnership::Committed(_) => RunscProcessOwnership::Committed(
HostProcessIdentity::pidfs_v1(process(6)),
),
});
enum_corpus!(digest, ProcessOwnershipMessageVersion, {
ProcessOwnershipMessageVersion::V1 => ProcessOwnershipMessageVersion::V1,
@ -314,8 +325,8 @@ fn every_serialized_enum_variant_has_fixed_shape_evidence() {
assert_eq!(
digest.finalize().as_slice(),
[
199, 150, 218, 48, 172, 14, 153, 234, 245, 198, 178, 249, 47, 35, 217, 83, 28, 188,
123, 152, 3, 15, 150, 61, 79, 255, 244, 107, 132, 27, 167, 123,
63, 126, 242, 211, 164, 165, 11, 185, 180, 135, 109, 135, 92, 142, 111, 169, 142, 215,
49, 4, 170, 169, 119, 237, 235, 161, 192, 89, 92, 93, 88, 35,
]
);
}