Protect every product-owned sandbox destination

This commit is contained in:
ms2k 2026-07-19 05:42:17 +09:00
commit 8a85b2387d
4 changed files with 31 additions and 12 deletions

View file

@ -12,9 +12,10 @@ use lazaret_core::identity::{ConfigurationFingerprint, ContainerId, DomainId, Na
use lazaret_core::records::VolumeAccess; use lazaret_core::records::VolumeAccess;
pub use lazaret_sandbox_contract::{ pub use lazaret_sandbox_contract::{
CONTROL_ROOT_DESTINATION, CREDENTIALS_DESTINATION, DEV_DESTINATION, CONTROL_ROOT_DESTINATION, CREDENTIALS_DESTINATION, DEV_DESTINATION,
ESCALATION_CLIENT_DESTINATION, MAILBOX_REQUESTS_DESTINATION, MAILBOX_RESULTS_DESTINATION, ESCALATION_CLIENT_DESTINATION, HOSTNAME_DESTINATION, HOSTS_DESTINATION,
PROC_DESTINATION, SANDBOX_INIT_DESTINATION, SYS_DESTINATION, TERMINFO_ROOT_DESTINATION, MAILBOX_REQUESTS_DESTINATION, MAILBOX_RESULTS_DESTINATION, PROC_DESTINATION,
WORKSPACE_DESTINATION, RESOLV_CONF_DESTINATION, RUNTIME_FILE_DESTINATIONS, SANDBOX_INIT_DESTINATION, SYS_DESTINATION,
TERMINFO_ROOT_DESTINATION, WORKSPACE_DESTINATION,
}; };
use oci_spec::runtime::{ use oci_spec::runtime::{
Capabilities, LinuxBuilder, LinuxCapabilitiesBuilder, LinuxIdMappingBuilder, Capabilities, LinuxBuilder, LinuxCapabilitiesBuilder, LinuxIdMappingBuilder,

View file

@ -2,8 +2,8 @@ use super::{
AtFlags, BTreeMap, Capabilities, ContainerId, DEFAULT_PATH, File, FileIdentity, FileType, AtFlags, BTreeMap, Capabilities, ContainerId, DEFAULT_PATH, File, FileIdentity, FileType,
HandoffPathType, LinuxBuilder, LinuxCapabilitiesBuilder, LinuxIdMappingBuilder, HandoffPathType, LinuxBuilder, LinuxCapabilitiesBuilder, LinuxIdMappingBuilder,
LinuxNamespaceBuilder, LinuxNamespaceType, Mode, Mount, NETWORK_NAMESPACE_PATH, OFlags, LinuxNamespaceBuilder, LinuxNamespaceType, Mode, Mount, NETWORK_NAMESPACE_PATH, OFlags,
OsString, OwnedFd, Path, PathBuf, ProcessBuilder, Read, ResolveFlags, OsString, OwnedFd, Path, PathBuf, ProcessBuilder, RUNTIME_FILE_DESTINATIONS, Read,
ResolvedDomainConfiguration, RootProcess, RunscCommand, RuntimeHandoffSource, ResolveFlags, ResolvedDomainConfiguration, RootProcess, RunscCommand, RuntimeHandoffSource,
SandboxBuildError, SandboxBuildErrorKind, StagedHostTerminal, StatxFlags, SandboxBuildError, SandboxBuildErrorKind, StagedHostTerminal, StatxFlags,
TERMINFO_ROOT_DESTINATION, UserBuilder, VolumeAccess, WORKSPACE_DESTINATION, bind_mount, TERMINFO_ROOT_DESTINATION, UserBuilder, VolumeAccess, WORKSPACE_DESTINATION, bind_mount,
control_mounts, hex_lower, host_path, oci_error, openat2, staging_error, standard_mounts, control_mounts, hex_lower, host_path, oci_error, openat2, staging_error, standard_mounts,
@ -74,7 +74,7 @@ pub(super) fn handoff_runtime_sources(
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for name in ["resolv.conf", "hosts", "hostname"] { for (name, _) in RUNTIME_FILE_DESTINATIONS {
sources.push(RuntimeHandoffSource { sources.push(RuntimeHandoffSource {
relative_path: Path::new("state-anchor/runtime-files").join(name), relative_path: Path::new("state-anchor/runtime-files").join(name),
expected_type: HandoffPathType::RegularFile, expected_type: HandoffPathType::RegularFile,
@ -227,10 +227,10 @@ pub(super) fn build_mounts(
)?); )?);
} }
mounts.extend(control_mounts(control_sources)?); mounts.extend(control_mounts(control_sources)?);
for name in ["resolv.conf", "hosts", "hostname"] { for (name, destination) in RUNTIME_FILE_DESTINATIONS {
mounts.push(bind_mount( mounts.push(bind_mount(
runtime_domain.join("state-anchor/runtime-files").join(name), runtime_domain.join("state-anchor/runtime-files").join(name),
Path::new("/etc").join(name), PathBuf::from(destination),
true, true,
true, true,
)?); )?);

View file

@ -10,10 +10,11 @@ use lazaret_core::configuration::{
use lazaret_core::identity::{ContainerId, DeviceId, InodeId, NamespaceIdentity}; use lazaret_core::identity::{ContainerId, DeviceId, InodeId, NamespaceIdentity};
use lazaret_runtime_supervisor::sandbox::{ use lazaret_runtime_supervisor::sandbox::{
CONTROL_ROOT_DESTINATION, CREDENTIALS_DESTINATION, DEV_DESTINATION, CONTROL_ROOT_DESTINATION, CREDENTIALS_DESTINATION, DEV_DESTINATION,
ESCALATION_CLIENT_DESTINATION, HostTerminal, MAILBOX_REQUESTS_DESTINATION, ESCALATION_CLIENT_DESTINATION, HOSTNAME_DESTINATION, HOSTS_DESTINATION, HostTerminal,
MAILBOX_RESULTS_DESTINATION, NETWORK_NAMESPACE_PATH, PROC_DESTINATION, RootProcess, MAILBOX_REQUESTS_DESTINATION, MAILBOX_RESULTS_DESTINATION, NETWORK_NAMESPACE_PATH,
SANDBOX_INIT_DESTINATION, SYS_DESTINATION, SandboxBuildErrorKind, SandboxBuildRequest, PROC_DESTINATION, RESOLV_CONF_DESTINATION, RootProcess, SANDBOX_INIT_DESTINATION,
SandboxBundle, TERMINFO_ROOT_DESTINATION, WORKSPACE_DESTINATION, build_sandbox_bundle, SYS_DESTINATION, SandboxBuildErrorKind, SandboxBuildRequest, SandboxBundle,
TERMINFO_ROOT_DESTINATION, WORKSPACE_DESTINATION, build_sandbox_bundle,
build_sandbox_bundle_with_workspace, default_sandbox_layout, stage_host_terminal, build_sandbox_bundle_with_workspace, default_sandbox_layout, stage_host_terminal,
}; };
use serde_json::Value; use serde_json::Value;
@ -650,8 +651,11 @@ fn default_layout_reserves_every_mount_root() {
layout.protected_destinations(), layout.protected_destinations(),
&BTreeSet::from([ &BTreeSet::from([
DEV_DESTINATION.to_owned(), DEV_DESTINATION.to_owned(),
HOSTNAME_DESTINATION.to_owned(),
HOSTS_DESTINATION.to_owned(),
PROC_DESTINATION.to_owned(), PROC_DESTINATION.to_owned(),
CONTROL_ROOT_DESTINATION.to_owned(), CONTROL_ROOT_DESTINATION.to_owned(),
RESOLV_CONF_DESTINATION.to_owned(),
SYS_DESTINATION.to_owned(), SYS_DESTINATION.to_owned(),
WORKSPACE_DESTINATION.to_owned(), WORKSPACE_DESTINATION.to_owned(),
]) ])

View file

@ -10,6 +10,14 @@ pub const MAILBOX_RESULTS_DESTINATION: &str = "/run/lazaret/mailbox/results";
pub const ESCALATION_CLIENT_DESTINATION: &str = "/run/lazaret/bin/lazaret-escalate"; pub const ESCALATION_CLIENT_DESTINATION: &str = "/run/lazaret/bin/lazaret-escalate";
pub const SANDBOX_INIT_DESTINATION: &str = "/run/lazaret/bin/lazaret-sandbox-init"; pub const SANDBOX_INIT_DESTINATION: &str = "/run/lazaret/bin/lazaret-sandbox-init";
pub const TERMINFO_ROOT_DESTINATION: &str = "/run/lazaret/terminfo"; pub const TERMINFO_ROOT_DESTINATION: &str = "/run/lazaret/terminfo";
pub const RESOLV_CONF_DESTINATION: &str = "/etc/resolv.conf";
pub const HOSTS_DESTINATION: &str = "/etc/hosts";
pub const HOSTNAME_DESTINATION: &str = "/etc/hostname";
pub const RUNTIME_FILE_DESTINATIONS: &[(&str, &str)] = &[
("resolv.conf", RESOLV_CONF_DESTINATION),
("hosts", HOSTS_DESTINATION),
("hostname", HOSTNAME_DESTINATION),
];
pub const PROC_DESTINATION: &str = "/proc"; pub const PROC_DESTINATION: &str = "/proc";
pub const SYS_DESTINATION: &str = "/sys"; pub const SYS_DESTINATION: &str = "/sys";
pub const DEV_DESTINATION: &str = "/dev"; pub const DEV_DESTINATION: &str = "/dev";
@ -25,6 +33,9 @@ pub fn default_sandbox_layout() -> Result<SandboxLayoutV1, ConfigurationError> {
PROC_DESTINATION.to_owned(), PROC_DESTINATION.to_owned(),
SYS_DESTINATION.to_owned(), SYS_DESTINATION.to_owned(),
DEV_DESTINATION.to_owned(), DEV_DESTINATION.to_owned(),
RESOLV_CONF_DESTINATION.to_owned(),
HOSTS_DESTINATION.to_owned(),
HOSTNAME_DESTINATION.to_owned(),
]) ])
} }
@ -40,8 +51,11 @@ mod tests {
default_sandbox_layout().unwrap().protected_destinations(), default_sandbox_layout().unwrap().protected_destinations(),
&BTreeSet::from([ &BTreeSet::from([
DEV_DESTINATION.to_owned(), DEV_DESTINATION.to_owned(),
HOSTNAME_DESTINATION.to_owned(),
HOSTS_DESTINATION.to_owned(),
PROC_DESTINATION.to_owned(), PROC_DESTINATION.to_owned(),
CONTROL_ROOT_DESTINATION.to_owned(), CONTROL_ROOT_DESTINATION.to_owned(),
RESOLV_CONF_DESTINATION.to_owned(),
SYS_DESTINATION.to_owned(), SYS_DESTINATION.to_owned(),
WORKSPACE_DESTINATION.to_owned(), WORKSPACE_DESTINATION.to_owned(),
]) ])