Restore persistent system path composition

This commit is contained in:
ms2k 2026-07-22 03:07:42 +09:00
commit 7aff8e542e
2 changed files with 338 additions and 30 deletions

View file

@ -25,6 +25,7 @@ use crate::network::{
NetworkAttestationContext, PreparedNetwork, enter_generation_filesystem_namespaces,
enter_generation_network_namespace, prepare_network,
};
use crate::sandbox::RUNTIME_FILE_DESTINATIONS;
use super::runtime::{
attached_runsc_standard_io, fail_network, fail_runtime_components, fail_with_runtime_cleanup,
@ -134,6 +135,19 @@ fn prepare_state_anchor(
mount
.require_persistent_destinations(&state.persistent_destinations)
.map_err(io::Error::other)?;
let transient_targets = RUNTIME_FILE_DESTINATIONS
.iter()
.map(|(_, destination)| PathBuf::from(destination.trim_start_matches('/')))
.filter(|target| {
state
.persistent_destinations
.iter()
.any(|persistent| target.starts_with(persistent) && target != persistent)
})
.collect::<Vec<_>>();
mount
.require_transient_override_targets(&transient_targets)
.map_err(io::Error::other)?;
Ok(Some(mount))
}

View file

@ -50,7 +50,7 @@ default_allow = ["192.0.2.10/32"]
[profiles.default]
image = "example.invalid/agent:v1"
persistent_dirs = ["/root"]
persistent_dirs = ["/root", "/usr", "/var", "/etc", "/opt"]
env = {{ SELECTED_SECRET = "env:SELECTED_HOST_SECRET" }}
volumes = [
{{ host = "{{profile_dir}}/read-only", container = "/root/read-only", kind = "directory", access = "read-only", create = true }},
@ -164,6 +164,10 @@ env = {{ UNSELECTED_SECRET = "env:UNSELECTED_HOST_SECRET" }}
"runsc".to_owned(),
format!("runsc-overlay/{container}"),
"state-anchor/merged/root".to_owned(),
"state-anchor/merged/usr".to_owned(),
"state-anchor/merged/var".to_owned(),
"state-anchor/merged/etc".to_owned(),
"state-anchor/merged/opt".to_owned(),
"state-anchor/runtime-files".to_owned(),
format!("sandbox-control/{container}/credentials"),
format!("sandbox-control/{container}/mailbox/requests"),
@ -247,6 +251,15 @@ fn mounts(specification: &Value) -> BTreeMap<&str, &Value> {
.collect()
}
fn mount_destinations(specification: &Value) -> Vec<&str> {
specification["mounts"]
.as_array()
.unwrap()
.iter()
.map(|mount| mount["destination"].as_str().unwrap())
.collect()
}
fn options(mount: &Value) -> BTreeSet<&str> {
mount["options"]
.as_array()
@ -468,6 +481,25 @@ fn trusted_init_environment_is_empty_and_volume_modes_are_preserved() {
.ends_with(&format!("state-anchor/runtime-files/{name}"))
);
}
let destinations = mount_destinations(&specification);
let persistent_etc = destinations
.iter()
.position(|path| *path == "/etc")
.unwrap();
for runtime_file in [
RESOLV_CONF_DESTINATION,
HOSTS_DESTINATION,
HOSTNAME_DESTINATION,
] {
assert!(
persistent_etc
< destinations
.iter()
.position(|path| *path == runtime_file)
.unwrap()
);
}
}
#[test]