xref: /aosp_15_r20/external/crosvm/jail/tests/fork.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
6*bb4ee6a4SAndroid Build Coastguard Worker mod test {
7*bb4ee6a4SAndroid Build Coastguard Worker     use std::thread;
8*bb4ee6a4SAndroid Build Coastguard Worker     use std::time::Duration;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker     use base::getpid;
11*bb4ee6a4SAndroid Build Coastguard Worker     use base::AsRawDescriptor;
12*bb4ee6a4SAndroid Build Coastguard Worker     use base::Tube;
13*bb4ee6a4SAndroid Build Coastguard Worker     use jail::fork::fork_process;
14*bb4ee6a4SAndroid Build Coastguard Worker     use minijail::Minijail;
15*bb4ee6a4SAndroid Build Coastguard Worker 
pid_diff()16*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pid_diff() {
17*bb4ee6a4SAndroid Build Coastguard Worker         let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
18*bb4ee6a4SAndroid Build Coastguard Worker         let jail = Minijail::new().unwrap();
19*bb4ee6a4SAndroid Build Coastguard Worker         let keep_rds = vec![fork_tube.as_raw_descriptor()];
20*bb4ee6a4SAndroid Build Coastguard Worker 
21*bb4ee6a4SAndroid Build Coastguard Worker         let pid = getpid();
22*bb4ee6a4SAndroid Build Coastguard Worker         let child = fork_process(jail, keep_rds, None, || {
23*bb4ee6a4SAndroid Build Coastguard Worker             // checks that this is a genuine fork with a new PID
24*bb4ee6a4SAndroid Build Coastguard Worker             if pid != getpid() {
25*bb4ee6a4SAndroid Build Coastguard Worker                 fork_tube.send(&1).unwrap()
26*bb4ee6a4SAndroid Build Coastguard Worker             } else {
27*bb4ee6a4SAndroid Build Coastguard Worker                 fork_tube.send(&2).unwrap()
28*bb4ee6a4SAndroid Build Coastguard Worker             }
29*bb4ee6a4SAndroid Build Coastguard Worker         })
30*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to fork");
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(tube.recv::<u32>().unwrap(), 1);
33*bb4ee6a4SAndroid Build Coastguard Worker         child.wait().unwrap();
34*bb4ee6a4SAndroid Build Coastguard Worker     }
35*bb4ee6a4SAndroid Build Coastguard Worker 
thread_name()36*bb4ee6a4SAndroid Build Coastguard Worker     pub fn thread_name() {
37*bb4ee6a4SAndroid Build Coastguard Worker         let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
38*bb4ee6a4SAndroid Build Coastguard Worker         let jail = Minijail::new().unwrap();
39*bb4ee6a4SAndroid Build Coastguard Worker         let keep_rds = vec![fork_tube.as_raw_descriptor()];
40*bb4ee6a4SAndroid Build Coastguard Worker         let thread_name = String::from("thread_name");
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker         let child = fork_process(jail, keep_rds, Some(thread_name.clone()), || {
43*bb4ee6a4SAndroid Build Coastguard Worker             fork_tube.send::<u32>(&1).unwrap();
44*bb4ee6a4SAndroid Build Coastguard Worker             thread::sleep(Duration::from_secs(10));
45*bb4ee6a4SAndroid Build Coastguard Worker         })
46*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to fork");
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker         // wait the forked process running.
49*bb4ee6a4SAndroid Build Coastguard Worker         tube.recv::<u32>().unwrap();
50*bb4ee6a4SAndroid Build Coastguard Worker         let thread_comm =
51*bb4ee6a4SAndroid Build Coastguard Worker             std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
52*bb4ee6a4SAndroid Build Coastguard Worker 
53*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(thread_comm, thread_name + "\n");
54*bb4ee6a4SAndroid Build Coastguard Worker 
55*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: child pid is expected to be valid and we wait on the child
56*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { libc::kill(child.pid, libc::SIGKILL) };
57*bb4ee6a4SAndroid Build Coastguard Worker         child.wait().unwrap();
58*bb4ee6a4SAndroid Build Coastguard Worker     }
59*bb4ee6a4SAndroid Build Coastguard Worker 
thread_name_trimmed()60*bb4ee6a4SAndroid Build Coastguard Worker     pub fn thread_name_trimmed() {
61*bb4ee6a4SAndroid Build Coastguard Worker         let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
62*bb4ee6a4SAndroid Build Coastguard Worker         let jail = Minijail::new().unwrap();
63*bb4ee6a4SAndroid Build Coastguard Worker         let keep_rds = vec![fork_tube.as_raw_descriptor()];
64*bb4ee6a4SAndroid Build Coastguard Worker         let thread_name = String::from("12345678901234567890");
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker         let child = fork_process(jail, keep_rds, Some(thread_name), || {
67*bb4ee6a4SAndroid Build Coastguard Worker             fork_tube.send::<u32>(&1).unwrap();
68*bb4ee6a4SAndroid Build Coastguard Worker             thread::sleep(Duration::from_secs(10));
69*bb4ee6a4SAndroid Build Coastguard Worker         })
70*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to fork");
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker         // wait the forked process running.
73*bb4ee6a4SAndroid Build Coastguard Worker         tube.recv::<u32>().unwrap();
74*bb4ee6a4SAndroid Build Coastguard Worker         let thread_comm =
75*bb4ee6a4SAndroid Build Coastguard Worker             std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
76*bb4ee6a4SAndroid Build Coastguard Worker 
77*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(thread_comm, "123456789012345\n");
78*bb4ee6a4SAndroid Build Coastguard Worker 
79*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: child pid is expected to be valid and we wait on the child
80*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { libc::kill(child.pid, libc::SIGKILL) };
81*bb4ee6a4SAndroid Build Coastguard Worker         child.wait().unwrap();
82*bb4ee6a4SAndroid Build Coastguard Worker     }
83*bb4ee6a4SAndroid Build Coastguard Worker 
wait_for_success()84*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait_for_success() {
85*bb4ee6a4SAndroid Build Coastguard Worker         let jail = Minijail::new().unwrap();
86*bb4ee6a4SAndroid Build Coastguard Worker         let child = fork_process(jail, vec![], None, || {
87*bb4ee6a4SAndroid Build Coastguard Worker             // exit successfully
88*bb4ee6a4SAndroid Build Coastguard Worker         })
89*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to fork");
90*bb4ee6a4SAndroid Build Coastguard Worker 
91*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(child.wait().unwrap(), 0);
92*bb4ee6a4SAndroid Build Coastguard Worker     }
93*bb4ee6a4SAndroid Build Coastguard Worker 
wait_for_panic()94*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait_for_panic() {
95*bb4ee6a4SAndroid Build Coastguard Worker         let jail = Minijail::new().unwrap();
96*bb4ee6a4SAndroid Build Coastguard Worker         let child = fork_process(jail, vec![], None, || {
97*bb4ee6a4SAndroid Build Coastguard Worker             panic!("fails");
98*bb4ee6a4SAndroid Build Coastguard Worker         })
99*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to fork");
100*bb4ee6a4SAndroid Build Coastguard Worker 
101*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(child.wait().unwrap(), 101);
102*bb4ee6a4SAndroid Build Coastguard Worker     }
103*bb4ee6a4SAndroid Build Coastguard Worker }
104*bb4ee6a4SAndroid Build Coastguard Worker 
main()105*bb4ee6a4SAndroid Build Coastguard Worker fn main() {
106*bb4ee6a4SAndroid Build Coastguard Worker     let args = libtest_mimic::Arguments {
107*bb4ee6a4SAndroid Build Coastguard Worker         // Force single-threaded execution to allow safe use of libc::fork in these tests.
108*bb4ee6a4SAndroid Build Coastguard Worker         test_threads: Some(1),
109*bb4ee6a4SAndroid Build Coastguard Worker         ..libtest_mimic::Arguments::from_args()
110*bb4ee6a4SAndroid Build Coastguard Worker     };
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker     let tests = vec![
113*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
114*bb4ee6a4SAndroid Build Coastguard Worker         libtest_mimic::Trial::test("pid_diff", move || {
115*bb4ee6a4SAndroid Build Coastguard Worker             test::pid_diff();
116*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
117*bb4ee6a4SAndroid Build Coastguard Worker         }),
118*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
119*bb4ee6a4SAndroid Build Coastguard Worker         libtest_mimic::Trial::test("thread_name", move || {
120*bb4ee6a4SAndroid Build Coastguard Worker             test::thread_name();
121*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
122*bb4ee6a4SAndroid Build Coastguard Worker         }),
123*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
124*bb4ee6a4SAndroid Build Coastguard Worker         libtest_mimic::Trial::test("thread_name_trimmed", move || {
125*bb4ee6a4SAndroid Build Coastguard Worker             test::thread_name_trimmed();
126*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
127*bb4ee6a4SAndroid Build Coastguard Worker         }),
128*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
129*bb4ee6a4SAndroid Build Coastguard Worker         libtest_mimic::Trial::test("wait_for_success", move || {
130*bb4ee6a4SAndroid Build Coastguard Worker             test::wait_for_success();
131*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
132*bb4ee6a4SAndroid Build Coastguard Worker         }),
133*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
134*bb4ee6a4SAndroid Build Coastguard Worker         libtest_mimic::Trial::test("wait_for_panic", move || {
135*bb4ee6a4SAndroid Build Coastguard Worker             test::wait_for_panic();
136*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
137*bb4ee6a4SAndroid Build Coastguard Worker         }),
138*bb4ee6a4SAndroid Build Coastguard Worker     ];
139*bb4ee6a4SAndroid Build Coastguard Worker     libtest_mimic::run(&args, tests).exit();
140*bb4ee6a4SAndroid Build Coastguard Worker }
141