Files
third_party_rust_rustix/tests/process/prctl.rs
T
2022-11-28 08:58:36 -08:00

226 lines
5.8 KiB
Rust

use std::io::{BufRead, Read};
use std::os::raw::c_int;
use std::{fs, io};
use rustix::process::*;
#[cfg(feature = "thread")]
use rustix::thread::Capability;
#[test]
fn test_parent_process_death_signal() {
dbg!(parent_process_death_signal().unwrap());
}
#[test]
fn test_dumpable_behavior() {
dbg!(dumpable_behavior().unwrap());
}
#[test]
fn test_timing_method() {
dbg!(timing_method().unwrap());
}
#[test]
fn test_machine_check_memory_corruption_kill_policy() {
dbg!(machine_check_memory_corruption_kill_policy().unwrap());
}
#[cfg(target_arch = "x86")]
#[test]
fn test_time_stamp_counter_readability() {
dbg!(time_stamp_counter_readability().unwrap());
}
#[cfg(target_arch = "powerpc")]
#[test]
fn test_unaligned_access_control() {
dbg!(unaligned_access_control().unwrap());
}
#[cfg(target_arch = "powerpc")]
#[test]
fn test_floating_point_exception_mode() {
dbg!(floating_point_exception_mode().unwrap());
}
#[cfg(target_arch = "powerpc")]
#[test]
fn test_endian_mode() {
dbg!(endian_mode().unwrap());
}
#[cfg(target_arch = "mips")]
#[test]
fn test_floating_point_mode() {
dbg!(floating_point_mode().unwrap());
}
#[cfg(target_arch = "aarch64")]
#[test]
#[ignore = "Only on ARMv8.3 and later"]
fn test_enabled_pointer_authentication_keys() {
dbg!(enabled_pointer_authentication_keys().unwrap());
}
#[test]
#[ignore = "?"]
fn test_child_subreaper() {
dbg!(child_subreaper().unwrap());
}
#[test]
#[ignore = "?"]
fn test_speculative_feature_state() {
dbg!(speculative_feature_state(SpeculationFeature::SpeculativeStoreBypass).unwrap());
dbg!(speculative_feature_state(SpeculationFeature::IndirectBranchSpeculation).unwrap());
dbg!(
speculative_feature_state(SpeculationFeature::FlushL1DCacheOnContextSwitchOutOfTask)
.unwrap()
);
}
#[cfg(feature = "thread")]
#[test]
fn test_is_io_flusher() {
if !thread_has_capability(Capability::SystemResource).unwrap() {
eprintln!("test_is_io_flusher: Test skipped due to missing capability: CAP_SYS_RESOURCE.");
return;
}
dbg!(is_io_flusher().unwrap());
}
#[cfg(feature = "thread")]
#[test]
fn test_virtual_memory_map_config_struct_size() {
if !thread_has_capability(Capability::SystemResource).unwrap() {
eprintln!(
"test_virtual_memory_map_config_struct_size: Test skipped due to missing capability: CAP_SYS_RESOURCE."
);
return;
}
if !linux_kernel_config_item_is_enabled("CONFIG_CHECKPOINT_RESTORE").unwrap_or(false) {
eprintln!("test_virtual_memory_map_config_struct_size: Test skipped due to missing kernel feature: CONFIG_CHECKPOINT_RESTORE.");
return;
}
dbg!(virtual_memory_map_config_struct_size().unwrap());
}
#[test]
#[ignore = "Only on ia64"]
fn test_floating_point_emulation_control() {
dbg!(floating_point_emulation_control().unwrap());
}
/*
* Helper functions.
*/
#[cfg(feature = "thread")]
pub(crate) fn thread_has_capability(capability: Capability) -> io::Result<bool> {
const _LINUX_CAPABILITY_VERSION_3: u32 = 0x20080522;
#[repr(C)]
struct cap_user_header_t {
version: u32,
pid: c_int,
}
#[repr(C)]
struct cap_user_data_t {
effective: u32,
permitted: u32,
inheritable: u32,
}
let header = cap_user_header_t {
version: _LINUX_CAPABILITY_VERSION_3,
pid: 0,
};
let mut data: [cap_user_data_t; 2] = [
cap_user_data_t {
effective: 0,
permitted: 0,
inheritable: 0,
},
cap_user_data_t {
effective: 0,
permitted: 0,
inheritable: 0,
},
];
let r = unsafe {
libc::syscall(
libc::SYS_capget,
&header as *const cap_user_header_t,
data.as_mut_ptr() as *mut cap_user_data_t,
)
};
if r == -1 {
return Err(io::Error::last_os_error());
}
let cap_index = capability as u32;
let (data_index, cap_index) = if cap_index < 32 {
(0, cap_index)
} else {
(1, cap_index - 32)
};
let flag = 1_u32 << cap_index;
Ok((flag & data[data_index].effective) != 0)
}
fn load_linux_kernel_config() -> io::Result<Vec<u8>> {
if let Ok(compressed_bytes) = fs::read("/proc/config.gz") {
let mut decoder = flate2::bufread::GzDecoder::new(compressed_bytes.as_slice());
let mut bytes = Vec::default();
decoder.read_to_end(&mut bytes)?;
return Ok(bytes);
}
let info = rustix::process::uname();
let release = info
.release()
.to_str()
.map_err(|_r| io::Error::from(io::ErrorKind::InvalidData))?;
fs::read(format!("/boot/config-{}", release))
}
fn is_linux_kernel_config_item_enabled(config: &[u8], name: &str) -> io::Result<bool> {
for line in io::Cursor::new(config).lines() {
let line = line?;
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let mut iter = line.splitn(2, '=');
if let Some(current_name) = iter.next().map(str::trim) {
if current_name == name {
if let Some(mut value) = iter.next().map(str::trim) {
if value.starts_with('"') && value.ends_with('"') {
// Just remove the quotes, but don't bother unescaping the inner string
// because we are only trying to find out if the option is an true boolean.
value = &value[1..(value.len() - 2)];
}
return Ok(value == "y" || value == "m");
}
}
}
}
Ok(false)
}
pub(crate) fn linux_kernel_config_item_is_enabled(name: &str) -> io::Result<bool> {
let config = load_linux_kernel_config()?;
is_linux_kernel_config_item_enabled(&config, name)
}