aboutsummaryrefslogtreecommitdiff
path: root/rust/minijail/tests/fork_remap.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/minijail/tests/fork_remap.rs')
-rw-r--r--rust/minijail/tests/fork_remap.rs64
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.");
}