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