1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 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 //! Small system utility modules for usage by other modules. 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_os = "android")] 8*bb4ee6a4SAndroid Build Coastguard Worker mod android; 9*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_os = "android")] 10*bb4ee6a4SAndroid Build Coastguard Worker use android as target_os; 11*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_os = "linux")] 12*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::module_inception)] 13*bb4ee6a4SAndroid Build Coastguard Worker mod linux; 14*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_os = "linux")] 15*bb4ee6a4SAndroid Build Coastguard Worker use linux as target_os; 16*bb4ee6a4SAndroid Build Coastguard Worker use log::warn; 17*bb4ee6a4SAndroid Build Coastguard Worker #[macro_use] 18*bb4ee6a4SAndroid Build Coastguard Worker pub mod ioctl; 19*bb4ee6a4SAndroid Build Coastguard Worker #[macro_use] 20*bb4ee6a4SAndroid Build Coastguard Worker pub mod syslog; 21*bb4ee6a4SAndroid Build Coastguard Worker mod acpi_event; 22*bb4ee6a4SAndroid Build Coastguard Worker mod capabilities; 23*bb4ee6a4SAndroid Build Coastguard Worker mod descriptor; 24*bb4ee6a4SAndroid Build Coastguard Worker mod event; 25*bb4ee6a4SAndroid Build Coastguard Worker mod file; 26*bb4ee6a4SAndroid Build Coastguard Worker mod file_traits; 27*bb4ee6a4SAndroid Build Coastguard Worker mod mmap; 28*bb4ee6a4SAndroid Build Coastguard Worker mod net; 29*bb4ee6a4SAndroid Build Coastguard Worker mod netlink; 30*bb4ee6a4SAndroid Build Coastguard Worker mod notifiers; 31*bb4ee6a4SAndroid Build Coastguard Worker pub mod platform_timer_resolution; 32*bb4ee6a4SAndroid Build Coastguard Worker mod poll; 33*bb4ee6a4SAndroid Build Coastguard Worker mod priority; 34*bb4ee6a4SAndroid Build Coastguard Worker mod sched; 35*bb4ee6a4SAndroid Build Coastguard Worker mod shm; 36*bb4ee6a4SAndroid Build Coastguard Worker pub mod signal; 37*bb4ee6a4SAndroid Build Coastguard Worker mod signalfd; 38*bb4ee6a4SAndroid Build Coastguard Worker mod terminal; 39*bb4ee6a4SAndroid Build Coastguard Worker mod timer; 40*bb4ee6a4SAndroid Build Coastguard Worker pub mod vsock; 41*bb4ee6a4SAndroid Build Coastguard Worker mod write_zeroes; 42*bb4ee6a4SAndroid Build Coastguard Worker 43*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CString; 44*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::remove_file; 45*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File; 46*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions; 47*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 48*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::MaybeUninit; 49*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref; 50*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::FromRawFd; 51*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::RawFd; 52*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixDatagram; 53*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixListener; 54*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::process::ExitStatusExt; 55*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path; 56*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf; 57*bb4ee6a4SAndroid Build Coastguard Worker use std::process::ExitStatus; 58*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr; 59*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration; 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker pub use acpi_event::*; 62*bb4ee6a4SAndroid Build Coastguard Worker pub use capabilities::drop_capabilities; 63*bb4ee6a4SAndroid Build Coastguard Worker pub use event::EventExt; 64*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use event::PlatformEvent; 65*bb4ee6a4SAndroid Build Coastguard Worker pub use file::find_next_data; 66*bb4ee6a4SAndroid Build Coastguard Worker pub use file::FileDataIterator; 67*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use file_traits::lib::*; 68*bb4ee6a4SAndroid Build Coastguard Worker pub use ioctl::*; 69*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int; 70*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_long; 71*bb4ee6a4SAndroid Build Coastguard Worker use libc::fcntl; 72*bb4ee6a4SAndroid Build Coastguard Worker use libc::pipe2; 73*bb4ee6a4SAndroid Build Coastguard Worker use libc::prctl; 74*bb4ee6a4SAndroid Build Coastguard Worker use libc::syscall; 75*bb4ee6a4SAndroid Build Coastguard Worker use libc::waitpid; 76*bb4ee6a4SAndroid Build Coastguard Worker use libc::SYS_getpid; 77*bb4ee6a4SAndroid Build Coastguard Worker use libc::SYS_getppid; 78*bb4ee6a4SAndroid Build Coastguard Worker use libc::SYS_gettid; 79*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL; 80*bb4ee6a4SAndroid Build Coastguard Worker use libc::O_CLOEXEC; 81*bb4ee6a4SAndroid Build Coastguard Worker use libc::PR_SET_NAME; 82*bb4ee6a4SAndroid Build Coastguard Worker use libc::SIGKILL; 83*bb4ee6a4SAndroid Build Coastguard Worker use libc::WNOHANG; 84*bb4ee6a4SAndroid Build Coastguard Worker pub use mmap::*; 85*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) use net::sendmsg_nosignal as sendmsg; 86*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) use net::sockaddr_un; 87*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) use net::sockaddrv4_to_lib_c; 88*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) use net::sockaddrv6_to_lib_c; 89*bb4ee6a4SAndroid Build Coastguard Worker pub use netlink::*; 90*bb4ee6a4SAndroid Build Coastguard Worker use once_cell::sync::OnceCell; 91*bb4ee6a4SAndroid Build Coastguard Worker pub use poll::EventContext; 92*bb4ee6a4SAndroid Build Coastguard Worker pub use priority::*; 93*bb4ee6a4SAndroid Build Coastguard Worker pub use sched::*; 94*bb4ee6a4SAndroid Build Coastguard Worker pub use shm::MemfdSeals; 95*bb4ee6a4SAndroid Build Coastguard Worker pub use shm::SharedMemoryLinux; 96*bb4ee6a4SAndroid Build Coastguard Worker pub use signal::*; 97*bb4ee6a4SAndroid Build Coastguard Worker pub use signalfd::Error as SignalFdError; 98*bb4ee6a4SAndroid Build Coastguard Worker pub use signalfd::*; 99*bb4ee6a4SAndroid Build Coastguard Worker pub use terminal::*; 100*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use write_zeroes::file_punch_hole; 101*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use write_zeroes::file_write_zeroes_at; 102*bb4ee6a4SAndroid Build Coastguard Worker 103*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor; 104*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor; 105*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::errno::Error; 106*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::errno::Result; 107*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::errno::*; 108*bb4ee6a4SAndroid Build Coastguard Worker use crate::number_of_logical_cores; 109*bb4ee6a4SAndroid Build Coastguard Worker use crate::round_up_to_page_size; 110*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::sys::unix::descriptor::*; 111*bb4ee6a4SAndroid Build Coastguard Worker use crate::syscall; 112*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor; 113*bb4ee6a4SAndroid Build Coastguard Worker use crate::Pid; 114*bb4ee6a4SAndroid Build Coastguard Worker 115*bb4ee6a4SAndroid Build Coastguard Worker /// Re-export libc types that are part of the API. 116*bb4ee6a4SAndroid Build Coastguard Worker pub type Uid = libc::uid_t; 117*bb4ee6a4SAndroid Build Coastguard Worker pub type Gid = libc::gid_t; 118*bb4ee6a4SAndroid Build Coastguard Worker pub type Mode = libc::mode_t; 119*bb4ee6a4SAndroid Build Coastguard Worker 120*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for PR_SET_NAME(2const) 121*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 122*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_thread_name(name: &str) -> Result<()> { 123*bb4ee6a4SAndroid Build Coastguard Worker let name = CString::new(name).or(Err(Error::new(EINVAL)))?; 124*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: prctl copies name and doesn't expect it to outlive this function. 125*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { prctl(PR_SET_NAME, name.as_c_str()) }; 126*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 { 127*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 128*bb4ee6a4SAndroid Build Coastguard Worker } else { 129*bb4ee6a4SAndroid Build Coastguard Worker errno_result() 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker 133*bb4ee6a4SAndroid Build Coastguard Worker /// This bypasses `libc`'s caching `getpid(2)` wrapper which can be invalid if a raw clone was used 134*bb4ee6a4SAndroid Build Coastguard Worker /// elsewhere. 135*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 136*bb4ee6a4SAndroid Build Coastguard Worker pub fn getpid() -> Pid { 137*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 138*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this syscall can never fail and we give it a valid syscall number. 139*bb4ee6a4SAndroid Build Coastguard Worker unsafe { syscall(SYS_getpid as c_long) as Pid } 140*bb4ee6a4SAndroid Build Coastguard Worker } 141*bb4ee6a4SAndroid Build Coastguard Worker 142*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for the geppid Linux systemcall. 143*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 144*bb4ee6a4SAndroid Build Coastguard Worker pub fn getppid() -> Pid { 145*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 146*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this syscall can never fail and we give it a valid syscall number. 147*bb4ee6a4SAndroid Build Coastguard Worker unsafe { syscall(SYS_getppid as c_long) as Pid } 148*bb4ee6a4SAndroid Build Coastguard Worker } 149*bb4ee6a4SAndroid Build Coastguard Worker 150*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for the gettid Linux systemcall. 151*bb4ee6a4SAndroid Build Coastguard Worker pub fn gettid() -> Pid { 152*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 153*bb4ee6a4SAndroid Build Coastguard Worker // Calling the gettid() sycall is always safe. 154*bb4ee6a4SAndroid Build Coastguard Worker unsafe { syscall(SYS_gettid as c_long) as Pid } 155*bb4ee6a4SAndroid Build Coastguard Worker } 156*bb4ee6a4SAndroid Build Coastguard Worker 157*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for `geteuid(2)`. 158*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 159*bb4ee6a4SAndroid Build Coastguard Worker pub fn geteuid() -> Uid { 160*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 161*bb4ee6a4SAndroid Build Coastguard Worker // trivially safe 162*bb4ee6a4SAndroid Build Coastguard Worker unsafe { libc::geteuid() } 163*bb4ee6a4SAndroid Build Coastguard Worker } 164*bb4ee6a4SAndroid Build Coastguard Worker 165*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for `getegid(2)`. 166*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 167*bb4ee6a4SAndroid Build Coastguard Worker pub fn getegid() -> Gid { 168*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 169*bb4ee6a4SAndroid Build Coastguard Worker // trivially safe 170*bb4ee6a4SAndroid Build Coastguard Worker unsafe { libc::getegid() } 171*bb4ee6a4SAndroid Build Coastguard Worker } 172*bb4ee6a4SAndroid Build Coastguard Worker 173*bb4ee6a4SAndroid Build Coastguard Worker /// The operation to perform with `flock`. 174*bb4ee6a4SAndroid Build Coastguard Worker pub enum FlockOperation { 175*bb4ee6a4SAndroid Build Coastguard Worker LockShared, 176*bb4ee6a4SAndroid Build Coastguard Worker LockExclusive, 177*bb4ee6a4SAndroid Build Coastguard Worker Unlock, 178*bb4ee6a4SAndroid Build Coastguard Worker } 179*bb4ee6a4SAndroid Build Coastguard Worker 180*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for flock(2) with the operation `op` and optionally `nonblocking`. The lock will be 181*bb4ee6a4SAndroid Build Coastguard Worker /// dropped automatically when `file` is dropped. 182*bb4ee6a4SAndroid Build Coastguard Worker #[inline(always)] 183*bb4ee6a4SAndroid Build Coastguard Worker pub fn flock<F: AsRawDescriptor>(file: &F, op: FlockOperation, nonblocking: bool) -> Result<()> { 184*bb4ee6a4SAndroid Build Coastguard Worker let mut operation = match op { 185*bb4ee6a4SAndroid Build Coastguard Worker FlockOperation::LockShared => libc::LOCK_SH, 186*bb4ee6a4SAndroid Build Coastguard Worker FlockOperation::LockExclusive => libc::LOCK_EX, 187*bb4ee6a4SAndroid Build Coastguard Worker FlockOperation::Unlock => libc::LOCK_UN, 188*bb4ee6a4SAndroid Build Coastguard Worker }; 189*bb4ee6a4SAndroid Build Coastguard Worker 190*bb4ee6a4SAndroid Build Coastguard Worker if nonblocking { 191*bb4ee6a4SAndroid Build Coastguard Worker operation |= libc::LOCK_NB; 192*bb4ee6a4SAndroid Build Coastguard Worker } 193*bb4ee6a4SAndroid Build Coastguard Worker 194*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 195*bb4ee6a4SAndroid Build Coastguard Worker // Safe since we pass in a valid fd and flock operation, and check the return value. 196*bb4ee6a4SAndroid Build Coastguard Worker syscall!(unsafe { libc::flock(file.as_raw_descriptor(), operation) }).map(|_| ()) 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker 199*bb4ee6a4SAndroid Build Coastguard Worker /// The operation to perform with `fallocate`. 200*bb4ee6a4SAndroid Build Coastguard Worker pub enum FallocateMode { 201*bb4ee6a4SAndroid Build Coastguard Worker PunchHole, 202*bb4ee6a4SAndroid Build Coastguard Worker ZeroRange, 203*bb4ee6a4SAndroid Build Coastguard Worker Allocate, 204*bb4ee6a4SAndroid Build Coastguard Worker } 205*bb4ee6a4SAndroid Build Coastguard Worker 206*bb4ee6a4SAndroid Build Coastguard Worker impl From<FallocateMode> for i32 { 207*bb4ee6a4SAndroid Build Coastguard Worker fn from(value: FallocateMode) -> Self { 208*bb4ee6a4SAndroid Build Coastguard Worker match value { 209*bb4ee6a4SAndroid Build Coastguard Worker FallocateMode::Allocate => libc::FALLOC_FL_KEEP_SIZE, 210*bb4ee6a4SAndroid Build Coastguard Worker FallocateMode::PunchHole => libc::FALLOC_FL_PUNCH_HOLE | libc::FALLOC_FL_KEEP_SIZE, 211*bb4ee6a4SAndroid Build Coastguard Worker FallocateMode::ZeroRange => libc::FALLOC_FL_ZERO_RANGE | libc::FALLOC_FL_KEEP_SIZE, 212*bb4ee6a4SAndroid Build Coastguard Worker } 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker } 215*bb4ee6a4SAndroid Build Coastguard Worker 216*bb4ee6a4SAndroid Build Coastguard Worker impl From<FallocateMode> for u32 { 217*bb4ee6a4SAndroid Build Coastguard Worker fn from(value: FallocateMode) -> Self { 218*bb4ee6a4SAndroid Build Coastguard Worker Into::<i32>::into(value) as u32 219*bb4ee6a4SAndroid Build Coastguard Worker } 220*bb4ee6a4SAndroid Build Coastguard Worker } 221*bb4ee6a4SAndroid Build Coastguard Worker 222*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for `fallocate()`. 223*bb4ee6a4SAndroid Build Coastguard Worker pub fn fallocate<F: AsRawDescriptor>( 224*bb4ee6a4SAndroid Build Coastguard Worker file: &F, 225*bb4ee6a4SAndroid Build Coastguard Worker mode: FallocateMode, 226*bb4ee6a4SAndroid Build Coastguard Worker offset: u64, 227*bb4ee6a4SAndroid Build Coastguard Worker len: u64, 228*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 229*bb4ee6a4SAndroid Build Coastguard Worker let offset = if offset > libc::off64_t::MAX as u64 { 230*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EINVAL)); 231*bb4ee6a4SAndroid Build Coastguard Worker } else { 232*bb4ee6a4SAndroid Build Coastguard Worker offset as libc::off64_t 233*bb4ee6a4SAndroid Build Coastguard Worker }; 234*bb4ee6a4SAndroid Build Coastguard Worker 235*bb4ee6a4SAndroid Build Coastguard Worker let len = if len > libc::off64_t::MAX as u64 { 236*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EINVAL)); 237*bb4ee6a4SAndroid Build Coastguard Worker } else { 238*bb4ee6a4SAndroid Build Coastguard Worker len as libc::off64_t 239*bb4ee6a4SAndroid Build Coastguard Worker }; 240*bb4ee6a4SAndroid Build Coastguard Worker 241*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 242*bb4ee6a4SAndroid Build Coastguard Worker // Safe since we pass in a valid fd and fallocate mode, validate offset and len, 243*bb4ee6a4SAndroid Build Coastguard Worker // and check the return value. 244*bb4ee6a4SAndroid Build Coastguard Worker syscall!(unsafe { libc::fallocate64(file.as_raw_descriptor(), mode.into(), offset, len) }) 245*bb4ee6a4SAndroid Build Coastguard Worker .map(|_| ()) 246*bb4ee6a4SAndroid Build Coastguard Worker } 247*bb4ee6a4SAndroid Build Coastguard Worker 248*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper for `fstat()`. 249*bb4ee6a4SAndroid Build Coastguard Worker pub fn fstat<F: AsRawDescriptor>(f: &F) -> Result<libc::stat64> { 250*bb4ee6a4SAndroid Build Coastguard Worker let mut st = MaybeUninit::<libc::stat64>::zeroed(); 251*bb4ee6a4SAndroid Build Coastguard Worker 252*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 253*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the kernel will only write data in `st` and we check the return 254*bb4ee6a4SAndroid Build Coastguard Worker // value. 255*bb4ee6a4SAndroid Build Coastguard Worker syscall!(unsafe { libc::fstat64(f.as_raw_descriptor(), st.as_mut_ptr()) })?; 256*bb4ee6a4SAndroid Build Coastguard Worker 257*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 258*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the kernel guarantees that the struct is now fully initialized. 259*bb4ee6a4SAndroid Build Coastguard Worker Ok(unsafe { st.assume_init() }) 260*bb4ee6a4SAndroid Build Coastguard Worker } 261*bb4ee6a4SAndroid Build Coastguard Worker 262*bb4ee6a4SAndroid Build Coastguard Worker /// Checks whether a file is a block device fie or not. 263*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_block_file<F: AsRawDescriptor>(file: &F) -> Result<bool> { 264*bb4ee6a4SAndroid Build Coastguard Worker let stat = fstat(file)?; 265*bb4ee6a4SAndroid Build Coastguard Worker Ok((stat.st_mode & libc::S_IFMT) == libc::S_IFBLK) 266*bb4ee6a4SAndroid Build Coastguard Worker } 267*bb4ee6a4SAndroid Build Coastguard Worker 268*bb4ee6a4SAndroid Build Coastguard Worker const BLOCK_IO_TYPE: u32 = 0x12; 269*bb4ee6a4SAndroid Build Coastguard Worker ioctl_io_nr!(BLKDISCARD, BLOCK_IO_TYPE, 119); 270*bb4ee6a4SAndroid Build Coastguard Worker 271*bb4ee6a4SAndroid Build Coastguard Worker /// Discards the given range of a block file. 272*bb4ee6a4SAndroid Build Coastguard Worker pub fn discard_block<F: AsRawDescriptor>(file: &F, offset: u64, len: u64) -> Result<()> { 273*bb4ee6a4SAndroid Build Coastguard Worker let range: [u64; 2] = [offset, len]; 274*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 275*bb4ee6a4SAndroid Build Coastguard Worker // Safe because 276*bb4ee6a4SAndroid Build Coastguard Worker // - we check the return value. 277*bb4ee6a4SAndroid Build Coastguard Worker // - ioctl(BLKDISCARD) does not hold the descriptor after the call. 278*bb4ee6a4SAndroid Build Coastguard Worker // - ioctl(BLKDISCARD) does not break the file descriptor. 279*bb4ee6a4SAndroid Build Coastguard Worker // - ioctl(BLKDISCARD) does not modify the given range. 280*bb4ee6a4SAndroid Build Coastguard Worker syscall!(unsafe { libc::ioctl(file.as_raw_descriptor(), BLKDISCARD, &range) }).map(|_| ()) 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker 283*bb4ee6a4SAndroid Build Coastguard Worker /// A trait used to abstract types that provide a process id that can be operated on. 284*bb4ee6a4SAndroid Build Coastguard Worker pub trait AsRawPid { 285*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_pid(&self) -> Pid; 286*bb4ee6a4SAndroid Build Coastguard Worker } 287*bb4ee6a4SAndroid Build Coastguard Worker 288*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawPid for Pid { 289*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_pid(&self) -> Pid { 290*bb4ee6a4SAndroid Build Coastguard Worker *self 291*bb4ee6a4SAndroid Build Coastguard Worker } 292*bb4ee6a4SAndroid Build Coastguard Worker } 293*bb4ee6a4SAndroid Build Coastguard Worker 294*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawPid for std::process::Child { 295*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_pid(&self) -> Pid { 296*bb4ee6a4SAndroid Build Coastguard Worker self.id() as Pid 297*bb4ee6a4SAndroid Build Coastguard Worker } 298*bb4ee6a4SAndroid Build Coastguard Worker } 299*bb4ee6a4SAndroid Build Coastguard Worker 300*bb4ee6a4SAndroid Build Coastguard Worker /// A safe wrapper around waitpid. 301*bb4ee6a4SAndroid Build Coastguard Worker /// 302*bb4ee6a4SAndroid Build Coastguard Worker /// On success if a process was reaped, it will be returned as the first value. 303*bb4ee6a4SAndroid Build Coastguard Worker /// The second returned value is the ExitStatus from the libc::waitpid() call. 304*bb4ee6a4SAndroid Build Coastguard Worker /// 305*bb4ee6a4SAndroid Build Coastguard Worker /// Note: this can block if libc::WNOHANG is not set and EINTR is not handled internally. 306*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_for_pid<A: AsRawPid>(pid: A, options: c_int) -> Result<(Option<Pid>, ExitStatus)> { 307*bb4ee6a4SAndroid Build Coastguard Worker let pid = pid.as_raw_pid(); 308*bb4ee6a4SAndroid Build Coastguard Worker let mut status: c_int = 1; 309*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 310*bb4ee6a4SAndroid Build Coastguard Worker // Safe because status is owned and the error is checked. 311*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::waitpid(pid, &mut status, options) }; 312*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 { 313*bb4ee6a4SAndroid Build Coastguard Worker return errno_result(); 314*bb4ee6a4SAndroid Build Coastguard Worker } 315*bb4ee6a4SAndroid Build Coastguard Worker Ok(( 316*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 { None } else { Some(ret) }, 317*bb4ee6a4SAndroid Build Coastguard Worker ExitStatus::from_raw(status), 318*bb4ee6a4SAndroid Build Coastguard Worker )) 319*bb4ee6a4SAndroid Build Coastguard Worker } 320*bb4ee6a4SAndroid Build Coastguard Worker 321*bb4ee6a4SAndroid Build Coastguard Worker /// Reaps a child process that has terminated. 322*bb4ee6a4SAndroid Build Coastguard Worker /// 323*bb4ee6a4SAndroid Build Coastguard Worker /// Returns `Ok(pid)` where `pid` is the process that was reaped or `Ok(0)` if none of the children 324*bb4ee6a4SAndroid Build Coastguard Worker /// have terminated. An `Error` is with `errno == ECHILD` if there are no children left to reap. 325*bb4ee6a4SAndroid Build Coastguard Worker /// 326*bb4ee6a4SAndroid Build Coastguard Worker /// # Examples 327*bb4ee6a4SAndroid Build Coastguard Worker /// 328*bb4ee6a4SAndroid Build Coastguard Worker /// Reaps all child processes until there are no terminated children to reap. 329*bb4ee6a4SAndroid Build Coastguard Worker /// 330*bb4ee6a4SAndroid Build Coastguard Worker /// ``` 331*bb4ee6a4SAndroid Build Coastguard Worker /// fn reap_children() { 332*bb4ee6a4SAndroid Build Coastguard Worker /// loop { 333*bb4ee6a4SAndroid Build Coastguard Worker /// match base::linux::reap_child() { 334*bb4ee6a4SAndroid Build Coastguard Worker /// Ok(0) => println!("no children ready to reap"), 335*bb4ee6a4SAndroid Build Coastguard Worker /// Ok(pid) => { 336*bb4ee6a4SAndroid Build Coastguard Worker /// println!("reaped {}", pid); 337*bb4ee6a4SAndroid Build Coastguard Worker /// continue 338*bb4ee6a4SAndroid Build Coastguard Worker /// }, 339*bb4ee6a4SAndroid Build Coastguard Worker /// Err(e) if e.errno() == libc::ECHILD => println!("no children left"), 340*bb4ee6a4SAndroid Build Coastguard Worker /// Err(e) => println!("error reaping children: {}", e), 341*bb4ee6a4SAndroid Build Coastguard Worker /// } 342*bb4ee6a4SAndroid Build Coastguard Worker /// break 343*bb4ee6a4SAndroid Build Coastguard Worker /// } 344*bb4ee6a4SAndroid Build Coastguard Worker /// } 345*bb4ee6a4SAndroid Build Coastguard Worker /// ``` 346*bb4ee6a4SAndroid Build Coastguard Worker pub fn reap_child() -> Result<Pid> { 347*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 348*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we pass in no memory, prevent blocking with WNOHANG, and check for error. 349*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { waitpid(-1, ptr::null_mut(), WNOHANG) }; 350*bb4ee6a4SAndroid Build Coastguard Worker if ret == -1 { 351*bb4ee6a4SAndroid Build Coastguard Worker errno_result() 352*bb4ee6a4SAndroid Build Coastguard Worker } else { 353*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret) 354*bb4ee6a4SAndroid Build Coastguard Worker } 355*bb4ee6a4SAndroid Build Coastguard Worker } 356*bb4ee6a4SAndroid Build Coastguard Worker 357*bb4ee6a4SAndroid Build Coastguard Worker /// Kill all processes in the current process group. 358*bb4ee6a4SAndroid Build Coastguard Worker /// 359*bb4ee6a4SAndroid Build Coastguard Worker /// On success, this kills all processes in the current process group, including the current 360*bb4ee6a4SAndroid Build Coastguard Worker /// process, meaning this will not return. This is equivalent to a call to `kill(0, SIGKILL)`. 361*bb4ee6a4SAndroid Build Coastguard Worker pub fn kill_process_group() -> Result<()> { 362*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because pid is 'self group' and return value doesn't matter. 363*bb4ee6a4SAndroid Build Coastguard Worker unsafe { kill(0, SIGKILL) }?; 364*bb4ee6a4SAndroid Build Coastguard Worker // Kill succeeded, so this process never reaches here. 365*bb4ee6a4SAndroid Build Coastguard Worker unreachable!(); 366*bb4ee6a4SAndroid Build Coastguard Worker } 367*bb4ee6a4SAndroid Build Coastguard Worker 368*bb4ee6a4SAndroid Build Coastguard Worker /// Spawns a pipe pair where the first pipe is the read end and the second pipe is the write end. 369*bb4ee6a4SAndroid Build Coastguard Worker /// 370*bb4ee6a4SAndroid Build Coastguard Worker /// The `O_CLOEXEC` flag will be set during pipe creation. 371*bb4ee6a4SAndroid Build Coastguard Worker pub fn pipe() -> Result<(File, File)> { 372*bb4ee6a4SAndroid Build Coastguard Worker let mut pipe_fds = [-1; 2]; 373*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 374*bb4ee6a4SAndroid Build Coastguard Worker // Safe because pipe2 will only write 2 element array of i32 to the given pointer, and we check 375*bb4ee6a4SAndroid Build Coastguard Worker // for error. 376*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { pipe2(&mut pipe_fds[0], O_CLOEXEC) }; 377*bb4ee6a4SAndroid Build Coastguard Worker if ret == -1 { 378*bb4ee6a4SAndroid Build Coastguard Worker errno_result() 379*bb4ee6a4SAndroid Build Coastguard Worker } else { 380*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 381*bb4ee6a4SAndroid Build Coastguard Worker // Safe because both fds must be valid for pipe2 to have returned sucessfully and we have 382*bb4ee6a4SAndroid Build Coastguard Worker // exclusive ownership of them. 383*bb4ee6a4SAndroid Build Coastguard Worker Ok(unsafe { 384*bb4ee6a4SAndroid Build Coastguard Worker ( 385*bb4ee6a4SAndroid Build Coastguard Worker File::from_raw_fd(pipe_fds[0]), 386*bb4ee6a4SAndroid Build Coastguard Worker File::from_raw_fd(pipe_fds[1]), 387*bb4ee6a4SAndroid Build Coastguard Worker ) 388*bb4ee6a4SAndroid Build Coastguard Worker }) 389*bb4ee6a4SAndroid Build Coastguard Worker } 390*bb4ee6a4SAndroid Build Coastguard Worker } 391*bb4ee6a4SAndroid Build Coastguard Worker 392*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the pipe signified with fd to `size`. 393*bb4ee6a4SAndroid Build Coastguard Worker /// 394*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the new size of the pipe or an error if the OS fails to set the pipe size. 395*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_pipe_size(fd: RawFd, size: usize) -> Result<usize> { 396*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 397*bb4ee6a4SAndroid Build Coastguard Worker // Safe because fcntl with the `F_SETPIPE_SZ` arg doesn't touch memory. 398*bb4ee6a4SAndroid Build Coastguard Worker syscall!(unsafe { fcntl(fd, libc::F_SETPIPE_SZ, size as c_int) }).map(|ret| ret as usize) 399*bb4ee6a4SAndroid Build Coastguard Worker } 400*bb4ee6a4SAndroid Build Coastguard Worker 401*bb4ee6a4SAndroid Build Coastguard Worker /// Test-only function used to create a pipe that is full. The pipe is created, has its size set to 402*bb4ee6a4SAndroid Build Coastguard Worker /// the minimum and then has that much data written to it. Use `new_pipe_full` to test handling of 403*bb4ee6a4SAndroid Build Coastguard Worker /// blocking `write` calls in unit tests. 404*bb4ee6a4SAndroid Build Coastguard Worker pub fn new_pipe_full() -> Result<(File, File)> { 405*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 406*bb4ee6a4SAndroid Build Coastguard Worker 407*bb4ee6a4SAndroid Build Coastguard Worker let (rx, mut tx) = pipe()?; 408*bb4ee6a4SAndroid Build Coastguard Worker // The smallest allowed size of a pipe is the system page size on linux. 409*bb4ee6a4SAndroid Build Coastguard Worker let page_size = set_pipe_size(tx.as_raw_descriptor(), round_up_to_page_size(1))?; 410*bb4ee6a4SAndroid Build Coastguard Worker 411*bb4ee6a4SAndroid Build Coastguard Worker // Fill the pipe with page_size zeros so the next write call will block. 412*bb4ee6a4SAndroid Build Coastguard Worker let buf = vec![0u8; page_size]; 413*bb4ee6a4SAndroid Build Coastguard Worker tx.write_all(&buf)?; 414*bb4ee6a4SAndroid Build Coastguard Worker 415*bb4ee6a4SAndroid Build Coastguard Worker Ok((rx, tx)) 416*bb4ee6a4SAndroid Build Coastguard Worker } 417*bb4ee6a4SAndroid Build Coastguard Worker 418*bb4ee6a4SAndroid Build Coastguard Worker /// Used to attempt to clean up a named pipe after it is no longer used. 419*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnlinkUnixDatagram(pub UnixDatagram); 420*bb4ee6a4SAndroid Build Coastguard Worker impl AsRef<UnixDatagram> for UnlinkUnixDatagram { 421*bb4ee6a4SAndroid Build Coastguard Worker fn as_ref(&self) -> &UnixDatagram { 422*bb4ee6a4SAndroid Build Coastguard Worker &self.0 423*bb4ee6a4SAndroid Build Coastguard Worker } 424*bb4ee6a4SAndroid Build Coastguard Worker } 425*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for UnlinkUnixDatagram { 426*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) { 427*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(addr) = self.0.local_addr() { 428*bb4ee6a4SAndroid Build Coastguard Worker if let Some(path) = addr.as_pathname() { 429*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = remove_file(path) { 430*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to remove control socket file: {}", e); 431*bb4ee6a4SAndroid Build Coastguard Worker } 432*bb4ee6a4SAndroid Build Coastguard Worker } 433*bb4ee6a4SAndroid Build Coastguard Worker } 434*bb4ee6a4SAndroid Build Coastguard Worker } 435*bb4ee6a4SAndroid Build Coastguard Worker } 436*bb4ee6a4SAndroid Build Coastguard Worker 437*bb4ee6a4SAndroid Build Coastguard Worker /// Used to attempt to clean up a named pipe after it is no longer used. 438*bb4ee6a4SAndroid Build Coastguard Worker pub struct UnlinkUnixListener(pub UnixListener); 439*bb4ee6a4SAndroid Build Coastguard Worker 440*bb4ee6a4SAndroid Build Coastguard Worker impl AsRef<UnixListener> for UnlinkUnixListener { 441*bb4ee6a4SAndroid Build Coastguard Worker fn as_ref(&self) -> &UnixListener { 442*bb4ee6a4SAndroid Build Coastguard Worker &self.0 443*bb4ee6a4SAndroid Build Coastguard Worker } 444*bb4ee6a4SAndroid Build Coastguard Worker } 445*bb4ee6a4SAndroid Build Coastguard Worker 446*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for UnlinkUnixListener { 447*bb4ee6a4SAndroid Build Coastguard Worker type Target = UnixListener; 448*bb4ee6a4SAndroid Build Coastguard Worker 449*bb4ee6a4SAndroid Build Coastguard Worker fn deref(&self) -> &UnixListener { 450*bb4ee6a4SAndroid Build Coastguard Worker &self.0 451*bb4ee6a4SAndroid Build Coastguard Worker } 452*bb4ee6a4SAndroid Build Coastguard Worker } 453*bb4ee6a4SAndroid Build Coastguard Worker 454*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for UnlinkUnixListener { 455*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) { 456*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(addr) = self.0.local_addr() { 457*bb4ee6a4SAndroid Build Coastguard Worker if let Some(path) = addr.as_pathname() { 458*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = remove_file(path) { 459*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to remove control socket file: {}", e); 460*bb4ee6a4SAndroid Build Coastguard Worker } 461*bb4ee6a4SAndroid Build Coastguard Worker } 462*bb4ee6a4SAndroid Build Coastguard Worker } 463*bb4ee6a4SAndroid Build Coastguard Worker } 464*bb4ee6a4SAndroid Build Coastguard Worker } 465*bb4ee6a4SAndroid Build Coastguard Worker 466*bb4ee6a4SAndroid Build Coastguard Worker /// Verifies that |raw_descriptor| is actually owned by this process and duplicates it 467*bb4ee6a4SAndroid Build Coastguard Worker /// to ensure that we have a unique handle to it. 468*bb4ee6a4SAndroid Build Coastguard Worker pub fn validate_raw_descriptor(raw_descriptor: RawDescriptor) -> Result<RawDescriptor> { 469*bb4ee6a4SAndroid Build Coastguard Worker validate_raw_fd(&raw_descriptor) 470*bb4ee6a4SAndroid Build Coastguard Worker } 471*bb4ee6a4SAndroid Build Coastguard Worker 472*bb4ee6a4SAndroid Build Coastguard Worker /// Verifies that |raw_fd| is actually owned by this process and duplicates it to ensure that 473*bb4ee6a4SAndroid Build Coastguard Worker /// we have a unique handle to it. 474*bb4ee6a4SAndroid Build Coastguard Worker pub fn validate_raw_fd(raw_fd: &RawFd) -> Result<RawFd> { 475*bb4ee6a4SAndroid Build Coastguard Worker // Checking that close-on-exec isn't set helps filter out FDs that were opened by 476*bb4ee6a4SAndroid Build Coastguard Worker // crosvm as all crosvm FDs are close on exec. 477*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 478*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value. 479*bb4ee6a4SAndroid Build Coastguard Worker let flags = unsafe { libc::fcntl(*raw_fd, libc::F_GETFD) }; 480*bb4ee6a4SAndroid Build Coastguard Worker if flags < 0 || (flags & libc::FD_CLOEXEC) != 0 { 481*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::new(libc::EBADF)); 482*bb4ee6a4SAndroid Build Coastguard Worker } 483*bb4ee6a4SAndroid Build Coastguard Worker 484*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 485*bb4ee6a4SAndroid Build Coastguard Worker // Duplicate the fd to ensure that we don't accidentally close an fd previously 486*bb4ee6a4SAndroid Build Coastguard Worker // opened by another subsystem. Safe because this doesn't modify any memory and 487*bb4ee6a4SAndroid Build Coastguard Worker // we check the return value. 488*bb4ee6a4SAndroid Build Coastguard Worker let dup_fd = unsafe { libc::fcntl(*raw_fd, libc::F_DUPFD_CLOEXEC, 0) }; 489*bb4ee6a4SAndroid Build Coastguard Worker if dup_fd < 0 { 490*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::last()); 491*bb4ee6a4SAndroid Build Coastguard Worker } 492*bb4ee6a4SAndroid Build Coastguard Worker Ok(dup_fd as RawFd) 493*bb4ee6a4SAndroid Build Coastguard Worker } 494*bb4ee6a4SAndroid Build Coastguard Worker 495*bb4ee6a4SAndroid Build Coastguard Worker /// Utility function that returns true if the given FD is readable without blocking. 496*bb4ee6a4SAndroid Build Coastguard Worker /// 497*bb4ee6a4SAndroid Build Coastguard Worker /// On an error, such as an invalid or incompatible FD, this will return false, which can not be 498*bb4ee6a4SAndroid Build Coastguard Worker /// distinguished from a non-ready to read FD. 499*bb4ee6a4SAndroid Build Coastguard Worker pub fn poll_in<F: AsRawDescriptor>(fd: &F) -> bool { 500*bb4ee6a4SAndroid Build Coastguard Worker let mut fds = libc::pollfd { 501*bb4ee6a4SAndroid Build Coastguard Worker fd: fd.as_raw_descriptor(), 502*bb4ee6a4SAndroid Build Coastguard Worker events: libc::POLLIN, 503*bb4ee6a4SAndroid Build Coastguard Worker revents: 0, 504*bb4ee6a4SAndroid Build Coastguard Worker }; 505*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 506*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we give a valid pointer to a list (of 1) FD and check the return value. 507*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { libc::poll(&mut fds, 1, 0) }; 508*bb4ee6a4SAndroid Build Coastguard Worker // An error probably indicates an invalid FD, or an FD that can't be polled. Returning false in 509*bb4ee6a4SAndroid Build Coastguard Worker // that case is probably correct as such an FD is unlikely to be readable, although there are 510*bb4ee6a4SAndroid Build Coastguard Worker // probably corner cases in which that is wrong. 511*bb4ee6a4SAndroid Build Coastguard Worker if ret == -1 { 512*bb4ee6a4SAndroid Build Coastguard Worker return false; 513*bb4ee6a4SAndroid Build Coastguard Worker } 514*bb4ee6a4SAndroid Build Coastguard Worker fds.revents & libc::POLLIN != 0 515*bb4ee6a4SAndroid Build Coastguard Worker } 516*bb4ee6a4SAndroid Build Coastguard Worker 517*bb4ee6a4SAndroid Build Coastguard Worker /// Return the maximum Duration that can be used with libc::timespec. 518*bb4ee6a4SAndroid Build Coastguard Worker pub fn max_timeout() -> Duration { 519*bb4ee6a4SAndroid Build Coastguard Worker Duration::new(libc::time_t::MAX as u64, 999999999) 520*bb4ee6a4SAndroid Build Coastguard Worker } 521*bb4ee6a4SAndroid Build Coastguard Worker 522*bb4ee6a4SAndroid Build Coastguard Worker /// If the given path is of the form /proc/self/fd/N for some N, returns `Ok(Some(N))`. Otherwise 523*bb4ee6a4SAndroid Build Coastguard Worker /// returns `Ok(None)`. 524*bb4ee6a4SAndroid Build Coastguard Worker pub fn safe_descriptor_from_path<P: AsRef<Path>>(path: P) -> Result<Option<SafeDescriptor>> { 525*bb4ee6a4SAndroid Build Coastguard Worker let path = path.as_ref(); 526*bb4ee6a4SAndroid Build Coastguard Worker if path.parent() == Some(Path::new("/proc/self/fd")) { 527*bb4ee6a4SAndroid Build Coastguard Worker let raw_descriptor = path 528*bb4ee6a4SAndroid Build Coastguard Worker .file_name() 529*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|fd_osstr| fd_osstr.to_str()) 530*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|fd_str| fd_str.parse::<RawFd>().ok()) 531*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| Error::new(EINVAL))?; 532*bb4ee6a4SAndroid Build Coastguard Worker let validated_fd = validate_raw_fd(&raw_descriptor)?; 533*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some( 534*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 535*bb4ee6a4SAndroid Build Coastguard Worker // Safe because nothing else has access to validated_fd after this call. 536*bb4ee6a4SAndroid Build Coastguard Worker unsafe { SafeDescriptor::from_raw_descriptor(validated_fd) }, 537*bb4ee6a4SAndroid Build Coastguard Worker )) 538*bb4ee6a4SAndroid Build Coastguard Worker } else { 539*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 540*bb4ee6a4SAndroid Build Coastguard Worker } 541*bb4ee6a4SAndroid Build Coastguard Worker } 542*bb4ee6a4SAndroid Build Coastguard Worker 543*bb4ee6a4SAndroid Build Coastguard Worker /// Check FD is not opened by crosvm and returns a FD that is freshly DUPFD_CLOEXEC's. 544*bb4ee6a4SAndroid Build Coastguard Worker /// A SafeDescriptor is created from the duplicated fd. It does not take ownership of 545*bb4ee6a4SAndroid Build Coastguard Worker /// fd passed by argument. 546*bb4ee6a4SAndroid Build Coastguard Worker pub fn safe_descriptor_from_cmdline_fd(fd: &RawFd) -> Result<SafeDescriptor> { 547*bb4ee6a4SAndroid Build Coastguard Worker let validated_fd = validate_raw_fd(fd)?; 548*bb4ee6a4SAndroid Build Coastguard Worker Ok( 549*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 550*bb4ee6a4SAndroid Build Coastguard Worker // Safe because nothing else has access to validated_fd after this call. 551*bb4ee6a4SAndroid Build Coastguard Worker unsafe { SafeDescriptor::from_raw_descriptor(validated_fd) }, 552*bb4ee6a4SAndroid Build Coastguard Worker ) 553*bb4ee6a4SAndroid Build Coastguard Worker } 554*bb4ee6a4SAndroid Build Coastguard Worker 555*bb4ee6a4SAndroid Build Coastguard Worker /// Open the file with the given path, or if it is of the form `/proc/self/fd/N` then just use the 556*bb4ee6a4SAndroid Build Coastguard Worker /// file descriptor. 557*bb4ee6a4SAndroid Build Coastguard Worker /// 558*bb4ee6a4SAndroid Build Coastguard Worker /// Note that this will not work properly if the same `/proc/self/fd/N` path is used twice in 559*bb4ee6a4SAndroid Build Coastguard Worker /// different places, as the metadata (including the offset) will be shared between both file 560*bb4ee6a4SAndroid Build Coastguard Worker /// descriptors. 561*bb4ee6a4SAndroid Build Coastguard Worker pub fn open_file_or_duplicate<P: AsRef<Path>>(path: P, options: &OpenOptions) -> Result<File> { 562*bb4ee6a4SAndroid Build Coastguard Worker let path = path.as_ref(); 563*bb4ee6a4SAndroid Build Coastguard Worker // Special case '/proc/self/fd/*' paths. The FD is already open, just use it. 564*bb4ee6a4SAndroid Build Coastguard Worker Ok(if let Some(fd) = safe_descriptor_from_path(path)? { 565*bb4ee6a4SAndroid Build Coastguard Worker fd.into() 566*bb4ee6a4SAndroid Build Coastguard Worker } else { 567*bb4ee6a4SAndroid Build Coastguard Worker options.open(path)? 568*bb4ee6a4SAndroid Build Coastguard Worker }) 569*bb4ee6a4SAndroid Build Coastguard Worker } 570*bb4ee6a4SAndroid Build Coastguard Worker 571*bb4ee6a4SAndroid Build Coastguard Worker /// Get the soft and hard limits of max number of open files allowed by the environment. 572*bb4ee6a4SAndroid Build Coastguard Worker pub fn max_open_files() -> Result<libc::rlimit64> { 573*bb4ee6a4SAndroid Build Coastguard Worker let mut buf = mem::MaybeUninit::<libc::rlimit64>::zeroed(); 574*bb4ee6a4SAndroid Build Coastguard Worker 575*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 576*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this will only modify `buf` and we check the return value. 577*bb4ee6a4SAndroid Build Coastguard Worker let res = unsafe { libc::prlimit64(0, libc::RLIMIT_NOFILE, ptr::null(), buf.as_mut_ptr()) }; 578*bb4ee6a4SAndroid Build Coastguard Worker if res == 0 { 579*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 580*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the kernel guarantees that the struct is fully initialized. 581*bb4ee6a4SAndroid Build Coastguard Worker let limit = unsafe { buf.assume_init() }; 582*bb4ee6a4SAndroid Build Coastguard Worker Ok(limit) 583*bb4ee6a4SAndroid Build Coastguard Worker } else { 584*bb4ee6a4SAndroid Build Coastguard Worker errno_result() 585*bb4ee6a4SAndroid Build Coastguard Worker } 586*bb4ee6a4SAndroid Build Coastguard Worker } 587*bb4ee6a4SAndroid Build Coastguard Worker 588*bb4ee6a4SAndroid Build Coastguard Worker /// Executes the given callback with extended soft limit of max number of open files. After the 589*bb4ee6a4SAndroid Build Coastguard Worker /// callback executed, restore the limit. 590*bb4ee6a4SAndroid Build Coastguard Worker pub fn call_with_extended_max_files<T, E>( 591*bb4ee6a4SAndroid Build Coastguard Worker callback: impl FnOnce() -> std::result::Result<T, E>, 592*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<std::result::Result<T, E>> { 593*bb4ee6a4SAndroid Build Coastguard Worker let cur_limit = max_open_files()?; 594*bb4ee6a4SAndroid Build Coastguard Worker let new_limit = libc::rlimit64 { 595*bb4ee6a4SAndroid Build Coastguard Worker rlim_cur: cur_limit.rlim_max, 596*bb4ee6a4SAndroid Build Coastguard Worker ..cur_limit 597*bb4ee6a4SAndroid Build Coastguard Worker }; 598*bb4ee6a4SAndroid Build Coastguard Worker let needs_extension = cur_limit.rlim_cur < new_limit.rlim_cur; 599*bb4ee6a4SAndroid Build Coastguard Worker if needs_extension { 600*bb4ee6a4SAndroid Build Coastguard Worker set_max_open_files(new_limit)?; 601*bb4ee6a4SAndroid Build Coastguard Worker } 602*bb4ee6a4SAndroid Build Coastguard Worker 603*bb4ee6a4SAndroid Build Coastguard Worker let r = callback(); 604*bb4ee6a4SAndroid Build Coastguard Worker 605*bb4ee6a4SAndroid Build Coastguard Worker // Restore the soft limit. 606*bb4ee6a4SAndroid Build Coastguard Worker if needs_extension { 607*bb4ee6a4SAndroid Build Coastguard Worker set_max_open_files(cur_limit)?; 608*bb4ee6a4SAndroid Build Coastguard Worker } 609*bb4ee6a4SAndroid Build Coastguard Worker 610*bb4ee6a4SAndroid Build Coastguard Worker Ok(r) 611*bb4ee6a4SAndroid Build Coastguard Worker } 612*bb4ee6a4SAndroid Build Coastguard Worker 613*bb4ee6a4SAndroid Build Coastguard Worker /// Set the soft and hard limits of max number of open files to the given value. 614*bb4ee6a4SAndroid Build Coastguard Worker fn set_max_open_files(limit: libc::rlimit64) -> Result<()> { 615*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: RLIMIT_NOFILE is known only to read a buffer of size rlimit64, and we have always 616*bb4ee6a4SAndroid Build Coastguard Worker // rlimit64 allocated. 617*bb4ee6a4SAndroid Build Coastguard Worker let res = unsafe { libc::setrlimit64(libc::RLIMIT_NOFILE, &limit) }; 618*bb4ee6a4SAndroid Build Coastguard Worker if res == 0 { 619*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 620*bb4ee6a4SAndroid Build Coastguard Worker } else { 621*bb4ee6a4SAndroid Build Coastguard Worker errno_result() 622*bb4ee6a4SAndroid Build Coastguard Worker } 623*bb4ee6a4SAndroid Build Coastguard Worker } 624*bb4ee6a4SAndroid Build Coastguard Worker 625*bb4ee6a4SAndroid Build Coastguard Worker /// Moves the requested PID/TID to a particular cgroup 626*bb4ee6a4SAndroid Build Coastguard Worker pub fn move_to_cgroup(cgroup_path: PathBuf, id_to_write: Pid, cgroup_file: &str) -> Result<()> { 627*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 628*bb4ee6a4SAndroid Build Coastguard Worker 629*bb4ee6a4SAndroid Build Coastguard Worker let gpu_cgroup_file = cgroup_path.join(cgroup_file); 630*bb4ee6a4SAndroid Build Coastguard Worker let mut f = File::create(gpu_cgroup_file)?; 631*bb4ee6a4SAndroid Build Coastguard Worker f.write_all(id_to_write.to_string().as_bytes())?; 632*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 633*bb4ee6a4SAndroid Build Coastguard Worker } 634*bb4ee6a4SAndroid Build Coastguard Worker 635*bb4ee6a4SAndroid Build Coastguard Worker pub fn move_task_to_cgroup(cgroup_path: PathBuf, thread_id: Pid) -> Result<()> { 636*bb4ee6a4SAndroid Build Coastguard Worker move_to_cgroup(cgroup_path, thread_id, "tasks") 637*bb4ee6a4SAndroid Build Coastguard Worker } 638*bb4ee6a4SAndroid Build Coastguard Worker 639*bb4ee6a4SAndroid Build Coastguard Worker pub fn move_proc_to_cgroup(cgroup_path: PathBuf, process_id: Pid) -> Result<()> { 640*bb4ee6a4SAndroid Build Coastguard Worker move_to_cgroup(cgroup_path, process_id, "cgroup.procs") 641*bb4ee6a4SAndroid Build Coastguard Worker } 642*bb4ee6a4SAndroid Build Coastguard Worker 643*bb4ee6a4SAndroid Build Coastguard Worker /// Queries the property of a specified CPU sysfs node. 644*bb4ee6a4SAndroid Build Coastguard Worker fn parse_sysfs_cpu_info_vec(cpu_id: usize, property: &str) -> Result<Vec<u32>> { 645*bb4ee6a4SAndroid Build Coastguard Worker let path = format!("/sys/devices/system/cpu/cpu{cpu_id}/{property}"); 646*bb4ee6a4SAndroid Build Coastguard Worker let res: Result<Vec<_>> = std::fs::read_to_string(path)? 647*bb4ee6a4SAndroid Build Coastguard Worker .split_whitespace() 648*bb4ee6a4SAndroid Build Coastguard Worker .map(|x| x.parse().map_err(|_| Error::new(libc::EINVAL))) 649*bb4ee6a4SAndroid Build Coastguard Worker .collect(); 650*bb4ee6a4SAndroid Build Coastguard Worker res 651*bb4ee6a4SAndroid Build Coastguard Worker } 652*bb4ee6a4SAndroid Build Coastguard Worker 653*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a list of supported frequencies in kHz for a given logical core. 654*bb4ee6a4SAndroid Build Coastguard Worker pub fn logical_core_frequencies_khz(cpu_id: usize) -> Result<Vec<u32>> { 655*bb4ee6a4SAndroid Build Coastguard Worker parse_sysfs_cpu_info_vec(cpu_id, "cpufreq/scaling_available_frequencies") 656*bb4ee6a4SAndroid Build Coastguard Worker } 657*bb4ee6a4SAndroid Build Coastguard Worker 658*bb4ee6a4SAndroid Build Coastguard Worker fn parse_sysfs_cpu_info(cpu_id: usize, property: &str) -> Result<u32> { 659*bb4ee6a4SAndroid Build Coastguard Worker let path = format!("/sys/devices/system/cpu/cpu{cpu_id}/{property}"); 660*bb4ee6a4SAndroid Build Coastguard Worker std::fs::read_to_string(path)? 661*bb4ee6a4SAndroid Build Coastguard Worker .trim() 662*bb4ee6a4SAndroid Build Coastguard Worker .parse() 663*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::new(libc::EINVAL)) 664*bb4ee6a4SAndroid Build Coastguard Worker } 665*bb4ee6a4SAndroid Build Coastguard Worker 666*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the capacity (measure of performance) of a given logical core. 667*bb4ee6a4SAndroid Build Coastguard Worker pub fn logical_core_capacity(cpu_id: usize) -> Result<u32> { 668*bb4ee6a4SAndroid Build Coastguard Worker static CPU_MAX_FREQS: OnceCell<Vec<u32>> = OnceCell::new(); 669*bb4ee6a4SAndroid Build Coastguard Worker 670*bb4ee6a4SAndroid Build Coastguard Worker let cpu_capacity = parse_sysfs_cpu_info(cpu_id, "cpu_capacity")?; 671*bb4ee6a4SAndroid Build Coastguard Worker 672*bb4ee6a4SAndroid Build Coastguard Worker // Collect and cache the maximum frequencies of all cores. We need to know 673*bb4ee6a4SAndroid Build Coastguard Worker // the largest maximum frequency between all cores to reverse normalization, 674*bb4ee6a4SAndroid Build Coastguard Worker // so collect all the values once on the first call to this function. 675*bb4ee6a4SAndroid Build Coastguard Worker let cpu_max_freqs = CPU_MAX_FREQS.get_or_try_init(|| { 676*bb4ee6a4SAndroid Build Coastguard Worker (0..number_of_logical_cores()?) 677*bb4ee6a4SAndroid Build Coastguard Worker .map(logical_core_max_freq_khz) 678*bb4ee6a4SAndroid Build Coastguard Worker .collect() 679*bb4ee6a4SAndroid Build Coastguard Worker }); 680*bb4ee6a4SAndroid Build Coastguard Worker 681*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(cpu_max_freqs) = cpu_max_freqs { 682*bb4ee6a4SAndroid Build Coastguard Worker let largest_max_freq = *cpu_max_freqs.iter().max().ok_or(Error::new(EINVAL))?; 683*bb4ee6a4SAndroid Build Coastguard Worker let cpu_max_freq = *cpu_max_freqs.get(cpu_id).ok_or(Error::new(EINVAL))?; 684*bb4ee6a4SAndroid Build Coastguard Worker let normalized_cpu_capacity = (u64::from(cpu_capacity) * u64::from(largest_max_freq)) 685*bb4ee6a4SAndroid Build Coastguard Worker .checked_div(u64::from(cpu_max_freq)) 686*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::new(EINVAL))?; 687*bb4ee6a4SAndroid Build Coastguard Worker normalized_cpu_capacity 688*bb4ee6a4SAndroid Build Coastguard Worker .try_into() 689*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::new(EINVAL)) 690*bb4ee6a4SAndroid Build Coastguard Worker } else { 691*bb4ee6a4SAndroid Build Coastguard Worker // cpu-freq is not enabled. Fall back to using the normalized capacity. 692*bb4ee6a4SAndroid Build Coastguard Worker Ok(cpu_capacity) 693*bb4ee6a4SAndroid Build Coastguard Worker } 694*bb4ee6a4SAndroid Build Coastguard Worker } 695*bb4ee6a4SAndroid Build Coastguard Worker 696*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the cluster ID of a given logical core. 697*bb4ee6a4SAndroid Build Coastguard Worker pub fn logical_core_cluster_id(cpu_id: usize) -> Result<u32> { 698*bb4ee6a4SAndroid Build Coastguard Worker parse_sysfs_cpu_info(cpu_id, "topology/physical_package_id") 699*bb4ee6a4SAndroid Build Coastguard Worker } 700*bb4ee6a4SAndroid Build Coastguard Worker 701*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the maximum frequency (in kHz) of a given logical core. 702*bb4ee6a4SAndroid Build Coastguard Worker pub fn logical_core_max_freq_khz(cpu_id: usize) -> Result<u32> { 703*bb4ee6a4SAndroid Build Coastguard Worker parse_sysfs_cpu_info(cpu_id, "cpufreq/cpuinfo_max_freq") 704*bb4ee6a4SAndroid Build Coastguard Worker } 705*bb4ee6a4SAndroid Build Coastguard Worker 706*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)] 707*bb4ee6a4SAndroid Build Coastguard Worker pub struct sched_attr { 708*bb4ee6a4SAndroid Build Coastguard Worker pub size: u32, 709*bb4ee6a4SAndroid Build Coastguard Worker 710*bb4ee6a4SAndroid Build Coastguard Worker pub sched_policy: u32, 711*bb4ee6a4SAndroid Build Coastguard Worker pub sched_flags: u64, 712*bb4ee6a4SAndroid Build Coastguard Worker pub sched_nice: i32, 713*bb4ee6a4SAndroid Build Coastguard Worker 714*bb4ee6a4SAndroid Build Coastguard Worker pub sched_priority: u32, 715*bb4ee6a4SAndroid Build Coastguard Worker 716*bb4ee6a4SAndroid Build Coastguard Worker pub sched_runtime: u64, 717*bb4ee6a4SAndroid Build Coastguard Worker pub sched_deadline: u64, 718*bb4ee6a4SAndroid Build Coastguard Worker pub sched_period: u64, 719*bb4ee6a4SAndroid Build Coastguard Worker 720*bb4ee6a4SAndroid Build Coastguard Worker pub sched_util_min: u32, 721*bb4ee6a4SAndroid Build Coastguard Worker pub sched_util_max: u32, 722*bb4ee6a4SAndroid Build Coastguard Worker } 723*bb4ee6a4SAndroid Build Coastguard Worker 724*bb4ee6a4SAndroid Build Coastguard Worker impl sched_attr { 725*bb4ee6a4SAndroid Build Coastguard Worker pub fn default() -> Self { 726*bb4ee6a4SAndroid Build Coastguard Worker Self { 727*bb4ee6a4SAndroid Build Coastguard Worker size: std::mem::size_of::<sched_attr>() as u32, 728*bb4ee6a4SAndroid Build Coastguard Worker sched_policy: 0, 729*bb4ee6a4SAndroid Build Coastguard Worker sched_flags: 0, 730*bb4ee6a4SAndroid Build Coastguard Worker sched_nice: 0, 731*bb4ee6a4SAndroid Build Coastguard Worker sched_priority: 0, 732*bb4ee6a4SAndroid Build Coastguard Worker sched_runtime: 0, 733*bb4ee6a4SAndroid Build Coastguard Worker sched_deadline: 0, 734*bb4ee6a4SAndroid Build Coastguard Worker sched_period: 0, 735*bb4ee6a4SAndroid Build Coastguard Worker sched_util_min: 0, 736*bb4ee6a4SAndroid Build Coastguard Worker sched_util_max: 0, 737*bb4ee6a4SAndroid Build Coastguard Worker } 738*bb4ee6a4SAndroid Build Coastguard Worker } 739*bb4ee6a4SAndroid Build Coastguard Worker } 740*bb4ee6a4SAndroid Build Coastguard Worker 741*bb4ee6a4SAndroid Build Coastguard Worker pub fn sched_setattr(pid: Pid, attr: &mut sched_attr, flags: u32) -> Result<()> { 742*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe becuase all the args are valid and the return valud is checked. 743*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { 744*bb4ee6a4SAndroid Build Coastguard Worker libc::syscall( 745*bb4ee6a4SAndroid Build Coastguard Worker libc::SYS_sched_setattr, 746*bb4ee6a4SAndroid Build Coastguard Worker pid as usize, 747*bb4ee6a4SAndroid Build Coastguard Worker attr as *mut sched_attr as usize, 748*bb4ee6a4SAndroid Build Coastguard Worker flags as usize, 749*bb4ee6a4SAndroid Build Coastguard Worker ) 750*bb4ee6a4SAndroid Build Coastguard Worker }; 751*bb4ee6a4SAndroid Build Coastguard Worker 752*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 { 753*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::last()); 754*bb4ee6a4SAndroid Build Coastguard Worker } 755*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 756*bb4ee6a4SAndroid Build Coastguard Worker } 757*bb4ee6a4SAndroid Build Coastguard Worker 758*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 759*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 760*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 761*bb4ee6a4SAndroid Build Coastguard Worker use std::os::fd::AsRawFd; 762*bb4ee6a4SAndroid Build Coastguard Worker 763*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 764*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::add_fd_flags; 765*bb4ee6a4SAndroid Build Coastguard Worker 766*bb4ee6a4SAndroid Build Coastguard Worker #[test] 767*bb4ee6a4SAndroid Build Coastguard Worker fn pipe_size_and_fill() { 768*bb4ee6a4SAndroid Build Coastguard Worker let (_rx, mut tx) = new_pipe_full().expect("Failed to pipe"); 769*bb4ee6a4SAndroid Build Coastguard Worker 770*bb4ee6a4SAndroid Build Coastguard Worker // To check that setting the size worked, set the descriptor to non blocking and check that 771*bb4ee6a4SAndroid Build Coastguard Worker // write returns an error. 772*bb4ee6a4SAndroid Build Coastguard Worker add_fd_flags(tx.as_raw_fd(), libc::O_NONBLOCK).expect("Failed to set tx non blocking"); 773*bb4ee6a4SAndroid Build Coastguard Worker tx.write(&[0u8; 8]) 774*bb4ee6a4SAndroid Build Coastguard Worker .expect_err("Write after fill didn't fail"); 775*bb4ee6a4SAndroid Build Coastguard Worker } 776*bb4ee6a4SAndroid Build Coastguard Worker } 777