Limit MXC volume expansion probes to symbolic links (#57515)

## What changed

Use directory-entry file types when expanding volume-root grants, and resolve metadata only for symbolic links. Skip links whose targets cannot be resolved, while preserving grants for ordinary children and valid links.

## Testing

Extend the volume-expansion test to cover dangling and self-referential links alongside an ordinary file, a valid symbolic link, and an explicit deny grant.

GitOrigin-RevId: 8acb4072a1f5edd4351738b5780ac659fdf94f01
This commit is contained in:
iceweasel-oai
2026-10-27 17:07:43 +00:00
committed by copyberry
parent d257beb16a
commit 77f0cbfdd5
2 changed files with 15 additions and 8 deletions
+4 -6
View File
@@ -17,8 +17,6 @@ use codex_windows_sandbox::resolve_windows_deny_read_paths;
use mxc_sdk::mxc_common::cmdline::CommandLineContext;
use mxc_sdk::mxc_common::cmdline::CommandLineError;
use mxc_sdk::mxc_common::cmdline::cmdline_from_argv_for_context;
use mxc_sdk::mxc_common::filesystem_object::ExistingObjectComparison;
use mxc_sdk::mxc_common::filesystem_object::compare_existing_filesystem_objects;
use mxc_sdk::mxc_common::models::BaseProcessUiConfig;
use mxc_sdk::mxc_common::models::ContainerPolicy;
use mxc_sdk::mxc_common::models::ExecutionRequest;
@@ -373,10 +371,10 @@ fn expand_volume_roots(
if child.to_str().is_none() {
continue;
}
// A self-comparison is MXC's public object-identity probe.
// Generated grants can be skipped; explicit paths go to BaseContainer.
if compare_existing_filesystem_objects(&child, &child)
!= ExistingObjectComparison::Same
// Windows supplies the file type with directory entries.
// Only resolve links: broken targets prevent PSEC startup.
if entry.file_type().is_ok_and(|kind| kind.is_symlink())
&& std::fs::metadata(&child).is_err()
{
continue;
}
+11 -2
View File
@@ -324,11 +324,16 @@ fn volume_expansion_does_not_turn_read_only_child_writable() -> Result<()> {
#[cfg(unix)]
#[test]
fn volume_expansion_skips_uninspectable_children() -> Result<()> {
fn volume_expansion_skips_broken_links_and_preserves_other_grants() -> Result<()> {
let temp = tempfile::tempdir()?;
let root = canonical_root(&temp)?;
let uninspectable = root.join("loop");
std::os::unix::fs::symlink(&uninspectable, &uninspectable)?;
std::os::unix::fs::symlink(root.join("missing"), root.join("dangling"))?;
let readable = root.join("readable");
std::fs::write(&readable, "readable")?;
let alias = root.join("alias");
std::os::unix::fs::symlink(&readable, &alias)?;
let denied = root.join("secret");
std::fs::write(&denied, "secret")?;
let fs = FileSystemSandboxPolicy::restricted(vec![
@@ -347,7 +352,11 @@ fn volume_expansion_skips_uninspectable_children() -> Result<()> {
assert_eq!(
(request.policy.readwrite_paths, request.policy.denied_paths),
(
vec![root.to_str().unwrap().to_owned()],
vec![
root.to_str().unwrap().to_owned(),
alias.to_str().unwrap().to_owned(),
readable.to_str().unwrap().to_owned()
],
vec![denied.to_str().unwrap().to_owned()],
)
);