diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/process/syscalls.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/process/syscalls.rs | 322 |
1 files changed, 120 insertions, 202 deletions
diff --git a/vendor/rustix/src/backend/libc/process/syscalls.rs b/vendor/rustix/src/backend/libc/process/syscalls.rs index d8f4fe3a4..0aa29b0b1 100644 --- a/vendor/rustix/src/backend/libc/process/syscalls.rs +++ b/vendor/rustix/src/backend/libc/process/syscalls.rs @@ -1,52 +1,43 @@ //! libc syscalls supporting `rustix::process`. -use super::super::c; -#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))] -use super::super::conv::borrowed_fd; -use super::super::conv::{c_str, ret, ret_c_int, ret_discarded_char_ptr}; -#[cfg(not(target_os = "wasi"))] -use super::super::conv::{ret_infallible, ret_pid_t, ret_usize}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::{syscall_ret, syscall_ret_u32}; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] use super::types::RawCpuSet; -#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))] +use crate::backend::c; +#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +use crate::backend::conv::ret_infallible; +#[cfg(linux_kernel)] +use crate::backend::conv::ret_u32; +#[cfg(not(target_os = "wasi"))] +use crate::backend::conv::{borrowed_fd, ret_pid_t, ret_usize}; +#[cfg(feature = "fs")] +use crate::backend::conv::{c_str, ret_discarded_char_ptr}; +use crate::backend::conv::{ret, ret_c_int}; +#[cfg(not(target_os = "wasi"))] use crate::fd::BorrowedFd; #[cfg(target_os = "linux")] -use crate::fd::{AsRawFd, OwnedFd}; +use crate::fd::{AsRawFd, OwnedFd, RawFd}; +#[cfg(feature = "fs")] use crate::ffi::CStr; #[cfg(feature = "fs")] use crate::fs::Mode; use crate::io; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::process::Sysinfo; -#[cfg(not(any(target_os = "wasi", target_os = "redox", target_os = "openbsd")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] +use crate::process::Uid; +#[cfg(linux_kernel)] +use crate::process::{Cpuid, MembarrierCommand, MembarrierQuery}; +#[cfg(not(target_os = "wasi"))] +use crate::process::{Gid, Pid, RawPid, Signal, WaitOptions, WaitStatus}; +#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +use crate::process::{Resource, Rlimit}; +#[cfg(not(any(target_os = "redox", target_os = "openbsd", target_os = "wasi")))] use crate::process::{WaitId, WaitidOptions, WaitidStatus}; use core::mem::MaybeUninit; #[cfg(target_os = "linux")] -use {super::super::conv::syscall_ret_owned_fd, crate::process::PidfdFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] use { - super::super::offset::libc_prlimit, - crate::process::{Cpuid, MembarrierCommand, MembarrierQuery}, -}; -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -use { - super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY}, - crate::process::{Resource, Rlimit}, -}; -#[cfg(not(target_os = "wasi"))] -use { - super::types::RawUname, - crate::process::{Gid, Pid, RawNonZeroPid, RawPid, Signal, Uid, WaitOptions, WaitStatus}, - core::convert::TryInto, + super::super::conv::ret_owned_fd, crate::process::PidfdFlags, crate::process::PidfdGetfdFlags, }; +#[cfg(feature = "fs")] #[cfg(not(target_os = "wasi"))] pub(crate) fn chdir(path: &CStr) -> io::Result<()> { unsafe { ret(c::chdir(c_str(path))) } @@ -57,17 +48,29 @@ pub(crate) fn fchdir(dirfd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ret(c::fchdir(borrowed_fd(dirfd))) } } +#[cfg(feature = "fs")] #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] pub(crate) fn chroot(path: &CStr) -> io::Result<()> { unsafe { ret(c::chroot(c_str(path))) } } +#[cfg(feature = "fs")] #[cfg(not(target_os = "wasi"))] -pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result<()> { +pub(crate) fn getcwd(buf: &mut [MaybeUninit<u8>]) -> io::Result<()> { unsafe { ret_discarded_char_ptr(c::getcwd(buf.as_mut_ptr().cast(), buf.len())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +// The `membarrier` syscall has a third argument, but it's only used when +// the `flags` argument is `MEMBARRIER_CMD_FLAG_CPU`. +#[cfg(linux_kernel)] +syscall! { + fn membarrier_all( + cmd: c::c_int, + flags: c::c_uint + ) via SYS_membarrier -> c::c_int +} + +#[cfg(linux_kernel)] pub(crate) fn membarrier_query() -> MembarrierQuery { // glibc does not have a wrapper for `membarrier`; [the documentation] // says to use `syscall`. @@ -75,79 +78,36 @@ pub(crate) fn membarrier_query() -> MembarrierQuery { // [the documentation]: https://man7.org/linux/man-pages/man2/membarrier.2.html#NOTES const MEMBARRIER_CMD_QUERY: u32 = 0; unsafe { - match syscall_ret_u32(c::syscall(c::SYS_membarrier, MEMBARRIER_CMD_QUERY, 0)) { - Ok(query) => MembarrierQuery::from_bits_unchecked(query), + match ret_u32(membarrier_all(MEMBARRIER_CMD_QUERY as i32, 0)) { + Ok(query) => MembarrierQuery::from_bits_retain(query), Err(_) => MembarrierQuery::empty(), } } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> { - unsafe { syscall_ret(c::syscall(c::SYS_membarrier, cmd as u32, 0)) } + unsafe { ret(membarrier_all(cmd as i32, 0)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> { const MEMBARRIER_CMD_FLAG_CPU: u32 = 1; - unsafe { - syscall_ret(c::syscall( - c::SYS_membarrier, - cmd as u32, - MEMBARRIER_CMD_FLAG_CPU, - cpu.as_raw(), - )) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getuid() -> Uid { - unsafe { - let uid = c::getuid(); - Uid::from_raw(uid) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn geteuid() -> Uid { - unsafe { - let uid = c::geteuid(); - Uid::from_raw(uid) - } -} -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getgid() -> Gid { - unsafe { - let gid = c::getgid(); - Gid::from_raw(gid) + syscall! { + fn membarrier_cpu( + cmd: c::c_int, + flags: c::c_uint, + cpu_id: c::c_int + ) via SYS_membarrier -> c::c_int } -} -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getegid() -> Gid { unsafe { - let gid = c::getegid(); - Gid::from_raw(gid) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getpid() -> Pid { - unsafe { - let pid = c::getpid(); - debug_assert_ne!(pid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)) + ret(membarrier_cpu( + cmd as i32, + MEMBARRIER_CMD_FLAG_CPU, + bitcast!(cpu.as_raw()), + )) } } @@ -166,8 +126,7 @@ pub(crate) fn getppid() -> Option<Pid> { pub(crate) fn getpgid(pid: Option<Pid>) -> io::Result<Pid> { unsafe { let pgid = ret_pid_t(c::getpgid(Pid::as_raw(pid) as _))?; - debug_assert_ne!(pgid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid))) + Ok(Pid::from_raw_unchecked(pgid)) } } @@ -183,17 +142,11 @@ pub(crate) fn setpgid(pid: Option<Pid>, pgid: Option<Pid>) -> io::Result<()> { pub(crate) fn getpgrp() -> Pid { unsafe { let pgid = c::getpgrp(); - debug_assert_ne!(pgid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid)) + Pid::from_raw_unchecked(pgid) } } -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] #[inline] pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io::Result<()> { unsafe { @@ -205,12 +158,7 @@ pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io: } } -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] #[inline] pub(crate) fn sched_setaffinity(pid: Option<Pid>, cpuset: &RawCpuSet) -> io::Result<()> { unsafe { @@ -230,21 +178,10 @@ pub(crate) fn sched_yield() { } #[cfg(not(target_os = "wasi"))] -#[inline] -pub(crate) fn uname() -> RawUname { - let mut uname = MaybeUninit::<RawUname>::uninit(); - unsafe { - ret_infallible(c::uname(uname.as_mut_ptr())); - uname.assume_init() - } -} - -#[cfg(not(target_os = "wasi"))] #[cfg(feature = "fs")] #[inline] pub(crate) fn umask(mask: Mode) -> Mode { - // TODO: Use `from_bits_retain` when we switch to bitflags 2.0. - unsafe { Mode::from_bits_truncate(c::umask(mask.bits() as _) as _) } + unsafe { Mode::from_bits_retain(c::umask(mask.bits() as c::mode_t).into()) } } #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] @@ -259,7 +196,7 @@ pub(crate) fn nice(inc: i32) -> io::Result<i32> { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_user(uid: Uid) -> io::Result<i32> { libc_errno::set_errno(libc_errno::Errno(0)); @@ -271,7 +208,7 @@ pub(crate) fn getpriority_user(uid: Uid) -> io::Result<i32> { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> { libc_errno::set_errno(libc_errno::Errno(0)); @@ -283,7 +220,7 @@ pub(crate) fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> { libc_errno::set_errno(libc_errno::Errno(0)); @@ -295,13 +232,13 @@ pub(crate) fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> { unsafe { ret(c::setpriority(c::PRIO_USER, uid.as_raw() as _, priority)) } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<()> { unsafe { @@ -313,7 +250,7 @@ pub(crate) fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<( } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result<()> { unsafe { @@ -328,9 +265,9 @@ pub(crate) fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] #[inline] pub(crate) fn getrlimit(limit: Resource) -> Rlimit { - let mut result = MaybeUninit::<libc_rlimit>::uninit(); + let mut result = MaybeUninit::<c::rlimit>::uninit(); unsafe { - ret_infallible(libc_getrlimit(limit as _, result.as_mut_ptr())); + ret_infallible(c::getrlimit(limit as _, result.as_mut_ptr())); rlimit_from_libc(result.assume_init()) } } @@ -339,16 +276,16 @@ pub(crate) fn getrlimit(limit: Resource) -> Rlimit { #[inline] pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> { let lim = rlimit_to_libc(new)?; - unsafe { ret(libc_setrlimit(limit as _, &lim)) } + unsafe { ret(c::setrlimit(limit as _, &lim)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Result<Rlimit> { let lim = rlimit_to_libc(new)?; - let mut result = MaybeUninit::<libc_rlimit>::uninit(); + let mut result = MaybeUninit::<c::rlimit>::uninit(); unsafe { - ret(libc_prlimit( + ret(c::prlimit( Pid::as_raw(pid), limit as _, &lim, @@ -358,15 +295,15 @@ pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Res } } -/// Convert a Rust [`Rlimit`] to a C `libc_rlimit`. +/// Convert a Rust [`Rlimit`] to a C `c::rlimit`. #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit { - let current = if lim.rlim_cur == LIBC_RLIM_INFINITY { +fn rlimit_from_libc(lim: c::rlimit) -> Rlimit { + let current = if lim.rlim_cur == c::RLIM_INFINITY { None } else { Some(lim.rlim_cur.try_into().unwrap()) }; - let maximum = if lim.rlim_max == LIBC_RLIM_INFINITY { + let maximum = if lim.rlim_max == c::RLIM_INFINITY { None } else { Some(lim.rlim_max.try_into().unwrap()) @@ -374,19 +311,19 @@ fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit { Rlimit { current, maximum } } -/// Convert a C `libc_rlimit` to a Rust `Rlimit`. +/// Convert a C `c::rlimit` to a Rust `Rlimit`. #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -fn rlimit_to_libc(lim: Rlimit) -> io::Result<libc_rlimit> { +fn rlimit_to_libc(lim: Rlimit) -> io::Result<c::rlimit> { let Rlimit { current, maximum } = lim; let rlim_cur = match current { Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?, - None => LIBC_RLIM_INFINITY as _, + None => c::RLIM_INFINITY as _, }; let rlim_max = match maximum { Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?, - None => LIBC_RLIM_INFINITY as _, + None => c::RLIM_INFINITY as _, }; - Ok(libc_rlimit { rlim_cur, rlim_max }) + Ok(c::rlimit { rlim_cur, rlim_max }) } #[cfg(not(target_os = "wasi"))] @@ -413,12 +350,7 @@ pub(crate) fn _waitpid( unsafe { let mut status: c::c_int = 0; let pid = ret_c_int(c::waitpid(pid as _, &mut status, waitopts.bits() as _))?; - Ok(RawNonZeroPid::new(pid).map(|non_zero| { - ( - Pid::from_raw_nonzero(non_zero), - WaitStatus::new(status as _), - ) - })) + Ok(Pid::from_raw(pid).map(|pid| (pid, WaitStatus::new(status as _)))) } } @@ -503,8 +435,8 @@ unsafe fn cvt_waitid_status(status: MaybeUninit<c::siginfo_t>) -> Option<WaitidS // `si_pid` is supposedly the better way to check that the struct has been // filled, e.g. the Linux manpage says about the `WNOHANG` case “zero out // the si_pid field before the call and check for a nonzero value”. - // But e.g. NetBSD/OpenBSD don't have it exposed in the libc crate for now, and - // some platforms don't have it at all. For simplicity, always check + // But e.g. NetBSD/OpenBSD don't have it exposed in the libc crate for now, + // and some platforms don't have it at all. For simplicity, always check // `si_signo`. We have zero-initialized the whole struct, and all kernels // should set `SIGCHLD` here. if status.si_signo == 0 { @@ -514,27 +446,12 @@ unsafe fn cvt_waitid_status(status: MaybeUninit<c::siginfo_t>) -> Option<WaitidS } } -#[inline] -pub(crate) fn exit_group(code: c::c_int) -> ! { - // `_exit` and `_Exit` are the same; it's just a matter of which ones - // the libc bindings expose. - #[cfg(any(target_os = "wasi", target_os = "solid"))] - unsafe { - c::_Exit(code) - } - #[cfg(unix)] - unsafe { - c::_exit(code) - } -} - #[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[inline] pub(crate) fn getsid(pid: Option<Pid>) -> io::Result<Pid> { unsafe { let pid = ret_pid_t(c::getsid(Pid::as_raw(pid) as _))?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -543,8 +460,7 @@ pub(crate) fn getsid(pid: Option<Pid>) -> io::Result<Pid> { pub(crate) fn setsid() -> io::Result<Pid> { unsafe { let pid = ret_c_int(c::setsid())?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -589,18 +505,6 @@ pub(crate) fn test_kill_current_process_group() -> io::Result<()> { unsafe { ret(c::kill(0, 0)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub(crate) unsafe fn prctl( - option: c::c_int, - arg2: *mut c::c_void, - arg3: *mut c::c_void, - arg4: *mut c::c_void, - arg5: *mut c::c_void, -) -> io::Result<c::c_int> { - ret_c_int(c::prctl(option, arg2, arg3, arg4, arg5)) -} - #[cfg(freebsdlike)] #[inline] pub(crate) unsafe fn procctl( @@ -614,11 +518,38 @@ pub(crate) unsafe fn procctl( #[cfg(target_os = "linux")] pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result<OwnedFd> { + syscall! { + fn pidfd_open( + pid: c::pid_t, + flags: c::c_uint + ) via SYS_pidfd_open -> c::c_int + } unsafe { - syscall_ret_owned_fd(c::syscall( - c::SYS_pidfd_open, + ret_owned_fd(pidfd_open( pid.as_raw_nonzero().get(), - flags.bits(), + bitflags_bits!(flags), + )) + } +} + +#[cfg(target_os = "linux")] +pub(crate) fn pidfd_getfd( + pidfd: BorrowedFd<'_>, + targetfd: RawFd, + flags: PidfdGetfdFlags, +) -> io::Result<OwnedFd> { + syscall! { + fn pidfd_getfd( + pidfd: c::c_int, + targetfd: c::c_int, + flags: c::c_uint + ) via SYS_pidfd_getfd -> c::c_int + } + unsafe { + ret_owned_fd(pidfd_getfd( + borrowed_fd(pidfd), + targetfd, + bitflags_bits!(flags), )) } } @@ -630,21 +561,8 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result<usize> { unsafe { ret_usize(c::getgroups(len, buf.as_mut_ptr().cast()) as isize) } } -#[cfg(any(target_os = "android", target_os = "linux"))] -pub(crate) fn sysinfo() -> Sysinfo { - let mut info = MaybeUninit::<Sysinfo>::uninit(); - unsafe { - ret_infallible(c::sysinfo(info.as_mut_ptr())); - info.assume_init() - } -} - -#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] -pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> { - unsafe { - ret(c::sethostname( - name.as_ptr().cast(), - name.len().try_into().map_err(|_| io::Errno::INVAL)?, - )) - } +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +#[inline] +pub(crate) fn ioctl_tiocsctty(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSCTTY as _, &0_u32)) } } |