@@ -412,7 +412,12 @@ pub(crate) async fn handle_proc_open(
412412 // sensitive-path deny, the per-PID filter, and the virtualization
413413 // string-matches below all see the same canonical form regardless of
414414 // how the caller spelled it (dirfd-relative, `..`-laden, etc.).
415- let resolved = match resolve_open_target ( notif, notif_fd) {
415+ let resolved = match resolve_open_target (
416+ notif,
417+ notif_fd,
418+ policy. chroot_root . as_deref ( ) ,
419+ & policy. chroot_mounts ,
420+ ) {
416421 Some ( p) => p,
417422 None => return NotifAction :: Continue ,
418423 } ;
@@ -600,8 +605,10 @@ pub(crate) fn handle_hostname_open(
600605 notif : & SeccompNotif ,
601606 hostname : & str ,
602607 notif_fd : RawFd ,
608+ chroot_root : Option < & std:: path:: Path > ,
609+ chroot_mounts : & [ ( std:: path:: PathBuf , std:: path:: PathBuf ) ] ,
603610) -> Option < NotifAction > {
604- let resolved = resolve_open_target ( notif, notif_fd) ?;
611+ let resolved = resolve_open_target ( notif, notif_fd, chroot_root , chroot_mounts ) ?;
605612 if resolved != std:: path:: Path :: new ( "/etc/hostname" ) {
606613 return None ;
607614 }
@@ -620,8 +627,10 @@ pub(crate) fn handle_etc_hosts_open(
620627 notif : & SeccompNotif ,
621628 etc_hosts_content : & str ,
622629 notif_fd : RawFd ,
630+ chroot_root : Option < & std:: path:: Path > ,
631+ chroot_mounts : & [ ( std:: path:: PathBuf , std:: path:: PathBuf ) ] ,
623632) -> Option < NotifAction > {
624- let resolved = resolve_open_target ( notif, notif_fd) ?;
633+ let resolved = resolve_open_target ( notif, notif_fd, chroot_root , chroot_mounts ) ?;
625634 if resolved != std:: path:: Path :: new ( "/etc/hosts" ) {
626635 return None ;
627636 }
@@ -646,6 +655,8 @@ pub(crate) fn handle_etc_hosts_open(
646655pub ( crate ) fn resolve_open_target (
647656 notif : & SeccompNotif ,
648657 notif_fd : RawFd ,
658+ chroot_root : Option < & std:: path:: Path > ,
659+ chroot_mounts : & [ ( std:: path:: PathBuf , std:: path:: PathBuf ) ] ,
649660) -> Option < std:: path:: PathBuf > {
650661 let nr = notif. data . nr as i64 ;
651662 let ( dirfd, path_ptr) : ( i64 , u64 ) = if Some ( nr) == crate :: arch:: sys_open ( ) {
@@ -659,7 +670,7 @@ pub(crate) fn resolve_open_target(
659670 return None ;
660671 } ;
661672 let path = read_path ( notif, path_ptr, notif_fd) ?;
662- resolve_to_normalized_absolute ( notif. pid , dirfd, & path)
673+ resolve_to_normalized_absolute ( notif. pid , dirfd, & path, chroot_root , chroot_mounts )
663674}
664675
665676/// Lexical normalization of `(pid, dirfd, path)`:
@@ -677,6 +688,8 @@ fn resolve_to_normalized_absolute(
677688 pid : u32 ,
678689 dirfd : i64 ,
679690 path : & str ,
691+ chroot_root : Option < & std:: path:: Path > ,
692+ chroot_mounts : & [ ( std:: path:: PathBuf , std:: path:: PathBuf ) ] ,
680693) -> Option < std:: path:: PathBuf > {
681694 use std:: path:: { Component , Path , PathBuf } ;
682695
@@ -688,6 +701,18 @@ fn resolve_to_normalized_absolute(
688701 } else {
689702 std:: fs:: read_link ( format ! ( "/proc/{}/fd/{}" , pid, dirfd as i32 ) ) . ok ( ) ?
690703 } ;
704+ // The dirfd/cwd symlink target is the *real* host directory. Under
705+ // chroot, sandlock services /proc, /etc and /dev via on-behalf opens,
706+ // so that target is e.g. `<chroot>/proc` while the child's absolute
707+ // spelling of the same file is `/proc/...`. Map the base back into the
708+ // sandbox's virtual namespace so relative and absolute spellings
709+ // resolve identically and the open-family shims (proc synthesis,
710+ // /etc/hosts, /etc/hostname, random seed, CA inject) match either way.
711+ let base = match chroot_root {
712+ Some ( root) => crate :: chroot:: resolve:: host_to_virtual ( root, chroot_mounts, & base)
713+ . unwrap_or ( base) ,
714+ None => base,
715+ } ;
691716 base. join ( path)
692717 } ;
693718
0 commit comments