• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::io::{BufRead, Read};
2 use std::{fs, io};
3 
4 use rustix::thread::*;
5 
6 #[test]
test_get_keep_capabilities()7 fn test_get_keep_capabilities() {
8     dbg!(get_keep_capabilities().unwrap());
9 }
10 
11 #[test]
test_name()12 fn test_name() {
13     dbg!(name().unwrap());
14 }
15 
16 #[test]
test_is_in_capability_bounding_set()17 fn test_is_in_capability_bounding_set() {
18     dbg!(is_in_capability_bounding_set(Capability::ChangeOwnership).unwrap());
19 }
20 
21 #[test]
test_capabilities_secure_bits()22 fn test_capabilities_secure_bits() {
23     dbg!(capabilities_secure_bits().unwrap());
24 }
25 
26 #[test]
test_current_timer_slack()27 fn test_current_timer_slack() {
28     dbg!(current_timer_slack().unwrap());
29 }
30 
31 #[test]
test_no_new_privs()32 fn test_no_new_privs() {
33     dbg!(no_new_privs().unwrap());
34 }
35 
36 #[test]
test_capability_is_in_ambient_capability_set()37 fn test_capability_is_in_ambient_capability_set() {
38     dbg!(capability_is_in_ambient_capability_set(Capability::ChangeOwnership).unwrap());
39 }
40 
41 #[cfg(target_arch = "aarch64")]
42 #[test]
test_sve_vector_length_configuration()43 fn test_sve_vector_length_configuration() {
44     dbg!(sve_vector_length_configuration().unwrap());
45 }
46 
47 #[cfg(target_arch = "aarch64")]
48 #[test]
test_current_tagged_address_mode()49 fn test_current_tagged_address_mode() {
50     dbg!(current_tagged_address_mode().unwrap());
51 }
52 
53 #[test]
54 #[ignore = "?"]
test_transparent_huge_pages_are_disabled()55 fn test_transparent_huge_pages_are_disabled() {
56     dbg!(transparent_huge_pages_are_disabled().unwrap());
57 }
58 
59 /*
60 #[test]
61 #[ignore = "Might result in SIGKILL"]
62 fn test_secure_computing_mode() {
63     if !linux_kernel_config_item_is_enabled("CONFIG_SECCOMP").unwrap_or(false) {
64         eprintln!("test_secure_computing_mode: Test skipped due to missing kernel feature: CONFIG_SECCOMP.");
65         return;
66     }
67 
68     dbg!(secure_computing_mode().unwrap());
69 }
70 */
71 
72 #[test]
test_get_clear_child_tid_address()73 fn test_get_clear_child_tid_address() {
74     if !linux_kernel_config_item_is_enabled("CONFIG_CHECKPOINT_RESTORE").unwrap_or(false) {
75         eprintln!("test_get_clear_child_tid_address: Test skipped due to missing kernel feature: CONFIG_CHECKPOINT_RESTORE.");
76         return;
77     }
78 
79     match get_clear_child_tid_address() {
80         Ok(address) => println!("get_clear_child_tid_address = {:?}", address),
81 
82         Err(r) => {
83             let errno = r.raw_os_error();
84             assert!(errno == libc::ENODEV || errno == libc::EINVAL);
85             eprintln!("test_get_clear_child_tid_address: Test unsupported: {}", r);
86         }
87     }
88 }
89 
90 #[test]
test_core_scheduling_cookie()91 fn test_core_scheduling_cookie() {
92     if !linux_kernel_config_item_is_enabled("CONFIG_SCHED_CORE").unwrap_or(false) {
93         eprintln!("test_core_scheduling_cookie: Test skipped due to missing kernel feature: CONFIG_SCHED_CORE.");
94         return;
95     }
96 
97     match core_scheduling_cookie(rustix::thread::gettid(), CoreSchedulingScope::Thread) {
98         Ok(cookie) => println!("core_scheduling_cookie = {:?}", cookie),
99 
100         Err(r) => {
101             let errno = r.raw_os_error();
102             assert!(errno == libc::ENODEV || errno == libc::EINVAL);
103             eprintln!("test_core_scheduling_cookie: Test unsupported: {}", r);
104         }
105     }
106 }
107 
108 /*
109  * Helper functions.
110  */
111 
load_linux_kernel_config() -> io::Result<Vec<u8>>112 fn load_linux_kernel_config() -> io::Result<Vec<u8>> {
113     if let Ok(compressed_bytes) = fs::read("/proc/config.gz") {
114         let mut decoder = flate2::bufread::GzDecoder::new(compressed_bytes.as_slice());
115         let mut bytes = Vec::default();
116         decoder.read_to_end(&mut bytes)?;
117         return Ok(bytes);
118     }
119 
120     let info = rustix::process::uname();
121     let release = info
122         .release()
123         .to_str()
124         .map_err(|_r| io::Error::from(io::ErrorKind::InvalidData))?;
125 
126     fs::read(format!("/boot/config-{}", release))
127 }
128 
is_linux_kernel_config_item_enabled(config: &[u8], name: &str) -> io::Result<bool>129 fn is_linux_kernel_config_item_enabled(config: &[u8], name: &str) -> io::Result<bool> {
130     for line in io::Cursor::new(config).lines() {
131         let line = line?;
132         let line = line.trim();
133         if line.is_empty() || line.starts_with('#') {
134             continue;
135         }
136 
137         let mut iter = line.splitn(2, '=');
138         if let Some(current_name) = iter.next().map(str::trim) {
139             if current_name == name {
140                 if let Some(mut value) = iter.next().map(str::trim) {
141                     if value.starts_with('"') && value.ends_with('"') {
142                         // Just remove the quotes, but don't bother unescaping the inner string
143                         // because we are only trying to find out if the option is an true boolean.
144                         value = &value[1..(value.len() - 2)];
145                     }
146 
147                     return Ok(value == "y" || value == "m");
148                 }
149             }
150         }
151     }
152     Ok(false)
153 }
154 
linux_kernel_config_item_is_enabled(name: &str) -> io::Result<bool>155 pub(crate) fn linux_kernel_config_item_is_enabled(name: &str) -> io::Result<bool> {
156     let config = load_linux_kernel_config()?;
157     is_linux_kernel_config_item_enabled(&config, name)
158 }
159