diff options
author | Allen Webb <allenwebb@google.com> | 2021-04-15 22:22:35 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-04-15 22:22:35 +0000 |
commit | dcb0854a69f48d6e5e71ecd7571845aa8c78face (patch) | |
tree | 1005371ec1af6a9ace515b979847999e37c90724 | |
parent | 729e99759dc7cbb764979309cf6e3a15120ca988 (diff) | |
parent | 1dd3905d7f578b110791e9e0d08d4a78b8aad74c (diff) | |
download | minijail-dcb0854a69f48d6e5e71ecd7571845aa8c78face.tar.gz |
rust/minijail: Add fork_remap test. am: 3f5a830277 am: da98682f01 am: 331c0792f1 am: 1dd3905d7f
Original change: https://android-review.googlesource.com/c/platform/external/minijail/+/1675746
Change-Id: Idd06b1a19759a4f019526633e09feb7604e78cd4
-rw-r--r-- | rust/minijail/Cargo.toml | 5 | ||||
-rw-r--r-- | rust/minijail/tests/fork_remap.rs | 81 |
2 files changed, 86 insertions, 0 deletions
diff --git a/rust/minijail/Cargo.toml b/rust/minijail/Cargo.toml index 6cf9837..db0652f 100644 --- a/rust/minijail/Cargo.toml +++ b/rust/minijail/Cargo.toml @@ -8,3 +8,8 @@ edition = "2018" [dependencies] libc = "0.2.44" minijail-sys = { path = "../minijail-sys" } # provided by ebuild + +[[test]] +name = "fork_remap" +path = "tests/fork_remap.rs" +harness = false diff --git a/rust/minijail/tests/fork_remap.rs b/rust/minijail/tests/fork_remap.rs new file mode 100644 index 0000000..8ace83b --- /dev/null +++ b/rust/minijail/tests/fork_remap.rs @@ -0,0 +1,81 @@ +// Copyright 2021 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! A test of Minijail::fork_remap. +//! +//! It needs to be run on its own because it forks the process and by default cargo test is +//! multi-threaded, and we do not want copies of the other worker threads leaking into the child +//! process. + +use std::fs::{read_link, File, OpenOptions}; +use std::io::{self, Read}; +use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::path::Path; + +use minijail::Minijail; + +const DEV_NULL: &str = "/dev/null"; +const DEV_ZERO: &str = "/dev/zero"; + +const DEST_FD1: RawFd = 7; +const DEST_FD2: RawFd = 8; + +fn open_dev_zero() -> Result<File, io::Error> { + OpenOptions::new() + .read(true) + .write(true) + .open(Path::new(DEV_ZERO)) +} + +fn main() { + let mut check_file1 = open_dev_zero().unwrap(); + let mut check_file2 = open_dev_zero().unwrap(); + let j = Minijail::new().unwrap(); + + for p in &[0, 1, 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 unsafe { + j.fork_remap(&[ + (2, 2), + (check_file1.as_raw_fd(), DEST_FD1), + (check_file2.as_raw_fd(), DEST_FD2), + ]) + } + .unwrap() + != 0 + { + j.wait().unwrap(); + eprintln!("Parent done."); + 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) }; + + for (p, expected) in &[ + (0, DEV_NULL), + (1, DEV_NULL), + (DEST_FD1, DEV_ZERO), + (DEST_FD2, DEV_ZERO), + ] { + let path = format!("/proc/self/fd/{}", p); + let target = read_link(Path::new(&path)); + eprintln!("C: {} -> {:?}", p, &target); + if !matches!(&target, Ok(p) if p == Path::new(expected)) { + panic!("C: got {:?}; expected Ok({:?})", target, expected); + } + } + + const BUFFER_LEN: usize = 16; + let mut buffer = [0xffu8; BUFFER_LEN]; + check_file1.read_exact(&mut buffer).unwrap(); + assert_eq!(&buffer, &[0u8; BUFFER_LEN]); + + eprintln!("Child done."); +} |