1 use std::io::{BufRead, Read};
2 use std::os::raw::c_int;
3 use std::{fs, io};
4
5 use rustix::process::*;
6 #[cfg(feature = "thread")]
7 use rustix::thread::Capability;
8
9 #[test]
test_parent_process_death_signal()10 fn test_parent_process_death_signal() {
11 dbg!(parent_process_death_signal().unwrap());
12 }
13
14 #[test]
test_dumpable_behavior()15 fn test_dumpable_behavior() {
16 dbg!(dumpable_behavior().unwrap());
17 }
18
19 #[test]
test_timing_method()20 fn test_timing_method() {
21 dbg!(timing_method().unwrap());
22 }
23
24 #[test]
test_machine_check_memory_corruption_kill_policy()25 fn test_machine_check_memory_corruption_kill_policy() {
26 dbg!(machine_check_memory_corruption_kill_policy().unwrap());
27 }
28
29 #[cfg(target_arch = "x86")]
30 #[test]
test_time_stamp_counter_readability()31 fn test_time_stamp_counter_readability() {
32 dbg!(time_stamp_counter_readability().unwrap());
33 }
34
35 #[cfg(target_arch = "powerpc")]
36 #[test]
test_unaligned_access_control()37 fn test_unaligned_access_control() {
38 dbg!(unaligned_access_control().unwrap());
39 }
40
41 #[cfg(target_arch = "powerpc")]
42 #[test]
test_floating_point_exception_mode()43 fn test_floating_point_exception_mode() {
44 dbg!(floating_point_exception_mode().unwrap());
45 }
46
47 #[cfg(target_arch = "powerpc")]
48 #[test]
test_endian_mode()49 fn test_endian_mode() {
50 dbg!(endian_mode().unwrap());
51 }
52
53 #[cfg(target_arch = "mips")]
54 #[test]
test_floating_point_mode()55 fn test_floating_point_mode() {
56 dbg!(floating_point_mode().unwrap());
57 }
58
59 #[cfg(target_arch = "aarch64")]
60 #[test]
61 #[ignore = "Only on ARMv8.3 and later"]
test_enabled_pointer_authentication_keys()62 fn test_enabled_pointer_authentication_keys() {
63 dbg!(enabled_pointer_authentication_keys().unwrap());
64 }
65
66 #[test]
67 #[ignore = "?"]
test_child_subreaper()68 fn test_child_subreaper() {
69 dbg!(child_subreaper().unwrap());
70 }
71
72 #[test]
73 #[ignore = "?"]
test_speculative_feature_state()74 fn test_speculative_feature_state() {
75 dbg!(speculative_feature_state(SpeculationFeature::SpeculativeStoreBypass).unwrap());
76 dbg!(speculative_feature_state(SpeculationFeature::IndirectBranchSpeculation).unwrap());
77 dbg!(
78 speculative_feature_state(SpeculationFeature::FlushL1DCacheOnContextSwitchOutOfTask)
79 .unwrap()
80 );
81 }
82
83 #[cfg(feature = "thread")]
84 #[test]
test_is_io_flusher()85 fn test_is_io_flusher() {
86 if !thread_has_capability(Capability::SystemResource).unwrap() {
87 eprintln!("test_is_io_flusher: Test skipped due to missing capability: CAP_SYS_RESOURCE.");
88 return;
89 }
90
91 dbg!(is_io_flusher().unwrap());
92 }
93
94 #[cfg(feature = "thread")]
95 #[test]
test_virtual_memory_map_config_struct_size()96 fn test_virtual_memory_map_config_struct_size() {
97 if !thread_has_capability(Capability::SystemResource).unwrap() {
98 eprintln!(
99 "test_virtual_memory_map_config_struct_size: Test skipped due to missing capability: CAP_SYS_RESOURCE."
100 );
101 return;
102 }
103
104 if !linux_kernel_config_item_is_enabled("CONFIG_CHECKPOINT_RESTORE").unwrap_or(false) {
105 eprintln!("test_virtual_memory_map_config_struct_size: Test skipped due to missing kernel feature: CONFIG_CHECKPOINT_RESTORE.");
106 return;
107 }
108
109 dbg!(virtual_memory_map_config_struct_size().unwrap());
110 }
111
112 #[test]
113 #[ignore = "Only on ia64"]
test_floating_point_emulation_control()114 fn test_floating_point_emulation_control() {
115 dbg!(floating_point_emulation_control().unwrap());
116 }
117
118 /*
119 * Helper functions.
120 */
121
122 #[cfg(feature = "thread")]
thread_has_capability(capability: Capability) -> io::Result<bool>123 pub(crate) fn thread_has_capability(capability: Capability) -> io::Result<bool> {
124 const _LINUX_CAPABILITY_VERSION_3: u32 = 0x20080522;
125
126 #[repr(C)]
127 struct cap_user_header_t {
128 version: u32,
129 pid: c_int,
130 }
131
132 #[repr(C)]
133 struct cap_user_data_t {
134 effective: u32,
135 permitted: u32,
136 inheritable: u32,
137 }
138
139 let header = cap_user_header_t {
140 version: _LINUX_CAPABILITY_VERSION_3,
141 pid: 0,
142 };
143
144 let mut data: [cap_user_data_t; 2] = [
145 cap_user_data_t {
146 effective: 0,
147 permitted: 0,
148 inheritable: 0,
149 },
150 cap_user_data_t {
151 effective: 0,
152 permitted: 0,
153 inheritable: 0,
154 },
155 ];
156
157 let r = unsafe {
158 libc::syscall(
159 libc::SYS_capget,
160 &header as *const cap_user_header_t,
161 data.as_mut_ptr() as *mut cap_user_data_t,
162 )
163 };
164
165 if r == -1 {
166 return Err(io::Error::last_os_error());
167 }
168
169 let cap_index = capability as u32;
170 let (data_index, cap_index) = if cap_index < 32 {
171 (0, cap_index)
172 } else {
173 (1, cap_index - 32)
174 };
175 let flag = 1_u32 << cap_index;
176 Ok((flag & data[data_index].effective) != 0)
177 }
178
load_linux_kernel_config() -> io::Result<Vec<u8>>179 fn load_linux_kernel_config() -> io::Result<Vec<u8>> {
180 if let Ok(compressed_bytes) = fs::read("/proc/config.gz") {
181 let mut decoder = flate2::bufread::GzDecoder::new(compressed_bytes.as_slice());
182 let mut bytes = Vec::default();
183 decoder.read_to_end(&mut bytes)?;
184 return Ok(bytes);
185 }
186
187 let info = rustix::process::uname();
188 let release = info
189 .release()
190 .to_str()
191 .map_err(|_r| io::Error::from(io::ErrorKind::InvalidData))?;
192
193 fs::read(format!("/boot/config-{}", release))
194 }
195
is_linux_kernel_config_item_enabled(config: &[u8], name: &str) -> io::Result<bool>196 fn is_linux_kernel_config_item_enabled(config: &[u8], name: &str) -> io::Result<bool> {
197 for line in io::Cursor::new(config).lines() {
198 let line = line?;
199 let line = line.trim();
200 if line.is_empty() || line.starts_with('#') {
201 continue;
202 }
203
204 let mut iter = line.splitn(2, '=');
205 if let Some(current_name) = iter.next().map(str::trim) {
206 if current_name == name {
207 if let Some(mut value) = iter.next().map(str::trim) {
208 if value.starts_with('"') && value.ends_with('"') {
209 // Just remove the quotes, but don't bother unescaping the inner string
210 // because we are only trying to find out if the option is an true boolean.
211 value = &value[1..(value.len() - 2)];
212 }
213
214 return Ok(value == "y" || value == "m");
215 }
216 }
217 }
218 }
219 Ok(false)
220 }
221
linux_kernel_config_item_is_enabled(name: &str) -> io::Result<bool>222 pub(crate) fn linux_kernel_config_item_is_enabled(name: &str) -> io::Result<bool> {
223 let config = load_linux_kernel_config()?;
224 is_linux_kernel_config_item_enabled(&config, name)
225 }
226