Skip to content

Commit ecb4393

Browse files
authored
Merge pull request #119 from multikernel/procfs-virtualize-under-chroot
Mount host /proc and /sys into chroot sandboxes, cgroup-aware and read-only
2 parents c6fb814 + 97e51d3 commit ecb4393

17 files changed

Lines changed: 1023 additions & 102 deletions

File tree

crates/sandlock-cli/src/main.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ struct RunArgs {
5656
#[arg(long)]
5757
time_start: Option<String>,
5858

59-
/// Mount a host path inside the sandbox (e.g. --fs-mount /work:/host/path)
60-
#[arg(long = "fs-mount", value_name = "VIRTUAL:HOST")]
59+
/// Mount a host path inside the sandbox; append :ro for read-only
60+
/// (e.g. --fs-mount /work:/host/path or --fs-mount /work:/host/path:ro)
61+
#[arg(long = "fs-mount", value_name = "VIRTUAL:HOST[:ro]")]
6162
fs_mount: Vec<String>,
6263

6364
/// COW branch action on normal sandbox exit: commit | abort | keep
@@ -382,7 +383,13 @@ async fn run_command(args: RunArgs) -> Result<i32> {
382383
// Filesystem extras
383384
if let Some(ref path) = base.chroot { b = b.chroot(path); }
384385
if let Some(ref path) = base.fs_storage { b = b.fs_storage(path); }
385-
for (virt, host) in &base.fs_mount { b = b.fs_mount(virt, host); }
386+
for (virt, host) in &base.fs_mount {
387+
if base.fs_mount_ro.iter().any(|d| d == virt) {
388+
b = b.fs_mount_ro(virt, host);
389+
} else {
390+
b = b.fs_mount(virt, host);
391+
}
392+
}
386393
b = b.on_exit(base.on_exit.clone());
387394
b = b.on_error(base.on_error.clone());
388395
b = b.deterministic_dirs(base.deterministic_dirs);
@@ -451,9 +458,12 @@ async fn run_command(args: RunArgs) -> Result<i32> {
451458
builder = builder.on_error(parse_branch_action("--on-error", s)?);
452459
}
453460
for spec in &args.fs_mount {
454-
let (virt, host) = spec.split_once(':')
455-
.ok_or_else(|| anyhow!("--fs-mount requires VIRTUAL:HOST, got: {}", spec))?;
456-
builder = builder.fs_mount(virt, host);
461+
let (virt, host, read_only) = profile::parse_mount_spec(spec)?;
462+
builder = if read_only {
463+
builder.fs_mount_ro(virt, host)
464+
} else {
465+
builder.fs_mount(virt, host)
466+
};
457467
}
458468
if !args.cpu_cores.is_empty() { builder = builder.cpu_cores(args.cpu_cores.clone()); }
459469
if !args.gpu_devices.is_empty() { builder = builder.gpu_devices(args.gpu_devices.clone()); }

crates/sandlock-core/src/ca_inject.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ pub(crate) fn handle_ca_inject_open(
3939
inject_paths: &[PathBuf],
4040
ca_pem: &[u8],
4141
notif_fd: RawFd,
42+
chroot_root: Option<&std::path::Path>,
43+
chroot_mounts: &[(PathBuf, PathBuf)],
4244
) -> Option<NotifAction> {
43-
let resolved = crate::procfs::resolve_open_target(notif, notif_fd)?;
45+
let resolved = crate::procfs::resolve_open_target(notif, notif_fd, chroot_root, chroot_mounts)?;
4446
if !path_matches(&resolved, inject_paths) {
4547
return None;
4648
}

0 commit comments

Comments
 (0)