diff options
Diffstat (limited to 'rust/minijail/tests/fork_remap.rs')
-rw-r--r-- | rust/minijail/tests/fork_remap.rs | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/rust/minijail/tests/fork_remap.rs b/rust/minijail/tests/fork_remap.rs index 8ace83b..6cf3415 100644 --- a/rust/minijail/tests/fork_remap.rs +++ b/rust/minijail/tests/fork_remap.rs @@ -10,40 +10,51 @@ use std::fs::{read_link, File, OpenOptions}; use std::io::{self, Read}; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::path::Path; use minijail::Minijail; const DEV_NULL: &str = "/dev/null"; const DEV_ZERO: &str = "/dev/zero"; +const PROC_CMDLINE: &str = "/proc/self/cmdline"; -const DEST_FD1: RawFd = 7; -const DEST_FD2: RawFd = 8; - -fn open_dev_zero() -> Result<File, io::Error> { +fn open_path(path: &str) -> Result<File, io::Error> { OpenOptions::new() .read(true) - .write(true) - .open(Path::new(DEV_ZERO)) + .write(false) + .open(Path::new(path)) } fn main() { - let mut check_file1 = open_dev_zero().unwrap(); - let mut check_file2 = open_dev_zero().unwrap(); + let mut check_file1 = open_path(DEV_ZERO).unwrap(); + let mut check_file2 = open_path(PROC_CMDLINE).unwrap(); let j = Minijail::new().unwrap(); - for p in &[0, 1, check_file1.as_raw_fd(), check_file2.as_raw_fd()] { + let mut stdio_expected = String::new(); + let mut file2_expected = String::new(); + for &p in &[0, 1, 2, check_file1.as_raw_fd(), check_file2.as_raw_fd()] { let path = format!("/proc/self/fd/{}", p); let target = read_link(Path::new(&path)); eprintln!("P: {} -> {:?}", p, &target); + if p == 2 { + stdio_expected = target.unwrap().to_string_lossy().to_string(); + } else if p == check_file2.as_raw_fd() { + file2_expected = target.unwrap().to_string_lossy().to_string(); + } } + // Swap fd1 and fd2. + let dest_fd1: RawFd = check_file2.as_raw_fd(); + let dest_fd2: RawFd = check_file1.as_raw_fd(); + if unsafe { j.fork_remap(&[ - (2, 2), - (check_file1.as_raw_fd(), DEST_FD1), - (check_file2.as_raw_fd(), DEST_FD2), + // fd 0 tests stdio mapped to /dev/null. + (2, 1), // One-to-many. + (2, 2), // Identity. + (check_file1.as_raw_fd(), dest_fd1), // Cross-over. + (check_file2.as_raw_fd(), dest_fd2), // Cross-over. ]) } .unwrap() @@ -54,21 +65,27 @@ fn main() { return; } - // Safe because we are re-taking ownership of a remapped fd after forking. - check_file1 = unsafe { File::from_raw_fd(DEST_FD1) }; - check_file2 = unsafe { File::from_raw_fd(DEST_FD2) }; + // Safe because we are re-taking ownership of remapped fds after forking. + unsafe { + check_file1.into_raw_fd(); + check_file1 = File::from_raw_fd(dest_fd1); + + check_file2.into_raw_fd(); + check_file2 = File::from_raw_fd(dest_fd2); + } for (p, expected) in &[ (0, DEV_NULL), - (1, DEV_NULL), - (DEST_FD1, DEV_ZERO), - (DEST_FD2, DEV_ZERO), + (1, &stdio_expected), + (2, &stdio_expected), + (dest_fd1, DEV_ZERO), + (dest_fd2, &file2_expected), ] { let path = format!("/proc/self/fd/{}", p); let target = read_link(Path::new(&path)); - eprintln!("C: {} -> {:?}", p, &target); + eprintln!(" C: {} -> {:?}", p, &target); if !matches!(&target, Ok(p) if p == Path::new(expected)) { - panic!("C: got {:?}; expected Ok({:?})", target, expected); + panic!(" C: got {:?}; expected Ok({:?})", target, expected); } } @@ -77,5 +94,8 @@ fn main() { check_file1.read_exact(&mut buffer).unwrap(); assert_eq!(&buffer, &[0u8; BUFFER_LEN]); - eprintln!("Child done."); + let mut file2_contents = Vec::<u8>::new(); + check_file2.read_to_end(&mut file2_contents).unwrap(); + + eprintln!(" Child done."); } |