use std::path::PathBuf;
use super::{
developer_toolchain_system_read_roots, network_name_service_read_roots,
proc_runtime_reads_are_contained, push_rule, read_only_access, standard_device_rules,
system_read_roots, workspace_access, FilesystemProfile, ProcessFilesystemScope,
LANDLOCK_ACCESS_FS_EXECUTE, LANDLOCK_ACCESS_FS_MAKE_DIR, LANDLOCK_ACCESS_FS_MAKE_SOCK,
LANDLOCK_ACCESS_FS_READ_DIR, LANDLOCK_ACCESS_FS_READ_FILE, LANDLOCK_ACCESS_FS_REMOVE_FILE,
LANDLOCK_ACCESS_FS_WRITE_FILE,
};
use crate::orchestration::CapabilityPolicy;
use crate::stdlib::sandbox::{
policy_allows_child_writes, process_sandbox_developer_toolchain_read_roots,
process_sandbox_package_manager_config_read_roots, process_sandbox_policy_read_roots,
process_sandbox_policy_write_roots, process_sandbox_readonly_roots, process_sandbox_roots,
sandbox_rejection,
};
use crate::VmError;
pub(super) fn filesystem_profile(
program: &str,
policy: &CapabilityPolicy,
handled_access_fs: u64,
process_scope: ProcessFilesystemScope,
) -> Result<FilesystemProfile, VmError> {
let mut profile = FilesystemProfile {
rules: Vec::new(),
symlinks: std::collections::BTreeMap::new(),
handled_access_fs,
read_deny_roots: super::super::process_sandbox_read_deny_roots(policy),
};
for (path, access) in standard_device_rules() {
push_rule(&mut profile, path, access, true)?;
}
for path in system_read_roots() {
push_rule(
&mut profile,
path,
LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_EXECUTE,
true,
)?;
}
for path in network_name_service_read_roots(policy) {
push_rule(&mut profile, path, LANDLOCK_ACCESS_FS_READ_FILE, true)?;
}
if policy.process_sandbox.allow_process_self_introspection {
if matches!(process_scope, ProcessFilesystemScope::Host)
&& !proc_runtime_reads_are_contained()
{
return Err(sandbox_rejection(
"process self-introspection needs a kernel that keeps a sandboxed task from inspecting its neighbours; this host permits it, so the grant would widen past the process it names"
.to_string(),
));
}
push_rule(
&mut profile,
PathBuf::from("/proc"),
LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR,
true,
)?;
} else if proc_runtime_reads_are_contained()
|| matches!(process_scope, ProcessFilesystemScope::PrivatePidNamespace)
{
push_rule(
&mut profile,
PathBuf::from("/proc"),
LANDLOCK_ACCESS_FS_READ_FILE,
true,
)?;
}
let program_path = std::path::Path::new(program);
if program_path.is_absolute() {
push_rule(
&mut profile,
program_path.to_path_buf(),
LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_EXECUTE,
true,
)?;
}
for root in process_sandbox_developer_toolchain_read_roots(policy) {
push_rule(&mut profile, root, read_only_access(), true)?;
}
for root in developer_toolchain_system_read_roots(policy) {
push_rule(&mut profile, root, read_only_access(), true)?;
}
for grant in super::super::read_roots::path_grants::process_sandbox_path_entry_grants(policy) {
push_rule(&mut profile, grant.root, read_only_access(), true)?;
}
let workspace_access = workspace_access(policy);
for root in process_sandbox_roots(policy) {
push_rule(&mut profile, root, workspace_access, false)?;
}
for root in process_sandbox_readonly_roots(policy) {
push_rule(&mut profile, root, read_only_access(), false)?;
}
for root in process_sandbox_policy_read_roots(policy) {
push_rule(&mut profile, root, read_only_access(), false)?;
}
for root in process_sandbox_package_manager_config_read_roots(policy) {
push_rule(&mut profile, root, read_only_access(), true)?;
}
let toolchain_cache_roots =
super::super::process_sandbox_developer_toolchain_cache_roots(policy);
let toolchain_cache_access = if policy_allows_child_writes(policy) {
workspace_access
} else {
read_only_access()
};
for root in toolchain_cache_roots {
push_rule(&mut profile, root, toolchain_cache_access, true)?;
}
if policy_allows_child_writes(policy) {
for root in process_sandbox_policy_write_roots(policy) {
push_rule(&mut profile, root, workspace_access, false)?;
}
}
if !policy.process_sandbox.unix_socket_roots.is_empty() {
for root in super::super::process_sandbox_unix_socket_roots(policy) {
push_rule(
&mut profile,
root,
LANDLOCK_ACCESS_FS_MAKE_SOCK
| LANDLOCK_ACCESS_FS_READ_FILE
| LANDLOCK_ACCESS_FS_READ_DIR
| LANDLOCK_ACCESS_FS_WRITE_FILE
| LANDLOCK_ACCESS_FS_MAKE_DIR
| LANDLOCK_ACCESS_FS_REMOVE_FILE,
true,
)?;
}
}
Ok(profile)
}