Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions crates/sandlock-core/src/procfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
pub(crate) mod net;
mod sock_diag;
pub(crate) mod net_dispatch;
mod metadata;
mod net_metadata;
pub(crate) use net_dispatch::{handle_net_open, handle_net_directory};
pub(crate) use net_metadata::{handle_net_metadata, handle_pinned_metadata};
pub(crate) use metadata::handle_pinned_metadata;
pub(crate) use net_metadata::handle_net_metadata;

use std::collections::HashSet;
use std::ffi::CString;
Expand Down Expand Up @@ -881,7 +883,44 @@ pub(crate) fn resolve_to_normalized_absolute(
chroot_mounts: &[(std::path::PathBuf, std::path::PathBuf)],
processes: &ProcessIndex,
) -> Option<std::path::PathBuf> {
use std::path::{Component, Path, PathBuf};
use std::path::{Component, PathBuf};

let joined = joined_absolute(pid, dirfd, path, chroot_root, chroot_mounts, processes)?;
let mut out = PathBuf::new();
for comp in joined.components() {
match comp {
Component::Prefix(p) => out.push(p.as_os_str()),
Component::RootDir => out.push("/"),
Component::CurDir => {}
Component::ParentDir => {
// pop the last regular component; refuse to walk above
// the root (out becomes empty after popping "/").
if !out.pop() {
return None;
}
if out.as_os_str().is_empty() {
return None;
}
}
Component::Normal(c) => out.push(c),
}
}
Some(match chroot_root {
None => through_task_root_and_cwd(out, pid, processes),
Some(_) => out,
})
}

/// `path` joined to the base it resolves against, without normalization.
pub(crate) fn joined_absolute(
pid: u32,
dirfd: i64,
path: &str,
chroot_root: Option<&std::path::Path>,
chroot_mounts: &[(std::path::PathBuf, std::path::PathBuf)],
processes: &ProcessIndex,
) -> Option<std::path::PathBuf> {
use std::path::{Path, PathBuf};

// The dirfd/cwd symlink target is the *real* host directory. Under
// chroot, sandlock services /proc, /etc and /dev via on-behalf opens,
Expand All @@ -897,7 +936,7 @@ pub(crate) fn resolve_to_normalized_absolute(
None => host,
};

let joined: PathBuf = if Path::new(path).is_absolute() {
Some(if Path::new(path).is_absolute() {
PathBuf::from(path)
} else if dirfd as i32 == libc::AT_FDCWD {
// Under chroot the supervisor services chdir itself and the child's
Expand All @@ -913,30 +952,6 @@ pub(crate) fn resolve_to_normalized_absolute(
} else {
let base = std::fs::read_link(format!("/proc/{}/fd/{}", pid, dirfd as i32)).ok()?;
to_virtual(base).join(path)
};

let mut out = PathBuf::new();
for comp in joined.components() {
match comp {
Component::Prefix(p) => out.push(p.as_os_str()),
Component::RootDir => out.push("/"),
Component::CurDir => {}
Component::ParentDir => {
// pop the last regular component; refuse to walk above
// the root (out becomes empty after popping "/").
if !out.pop() {
return None;
}
if out.as_os_str().is_empty() {
return None;
}
}
Component::Normal(c) => out.push(c),
}
}
Some(match chroot_root {
None => through_task_root_and_cwd(out, pid, processes),
Some(_) => out,
})
}

Expand Down
Loading
Loading