diff options
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/thread')
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/thread/futex.rs | 45 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/thread/mod.rs | 2 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/linux_raw/thread/syscalls.rs | 347 | 
3 files changed, 394 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/thread/futex.rs b/vendor/rustix/src/backend/linux_raw/thread/futex.rs new file mode 100644 index 0000000..263e980 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/thread/futex.rs @@ -0,0 +1,45 @@ +bitflags::bitflags! { +    /// `FUTEX_*` flags for use with [`futex`]. +    /// +    /// [`futex`]: crate::thread::futex +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct FutexFlags: u32 { +        /// `FUTEX_PRIVATE_FLAG` +        const PRIVATE = linux_raw_sys::general::FUTEX_PRIVATE_FLAG; +        /// `FUTEX_CLOCK_REALTIME` +        const CLOCK_REALTIME = linux_raw_sys::general::FUTEX_CLOCK_REALTIME; + +        // This deliberately lacks a `const _ = !0`, so that users can use +        // `from_bits_truncate` to extract the `SocketFlags` from a flags +        // value that also includes a `SocketType`. +    } +} + +/// `FUTEX_*` operations for use with [`futex`]. +/// +/// [`futex`]: crate::thread::futex +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[repr(u32)] +pub enum FutexOperation { +    /// `FUTEX_WAIT` +    Wait = linux_raw_sys::general::FUTEX_WAIT, +    /// `FUTEX_WAKE` +    Wake = linux_raw_sys::general::FUTEX_WAKE, +    /// `FUTEX_FD` +    Fd = linux_raw_sys::general::FUTEX_FD, +    /// `FUTEX_REQUEUE` +    Requeue = linux_raw_sys::general::FUTEX_REQUEUE, +    /// `FUTEX_CMP_REQUEUE` +    CmpRequeue = linux_raw_sys::general::FUTEX_CMP_REQUEUE, +    /// `FUTEX_WAKE_OP` +    WakeOp = linux_raw_sys::general::FUTEX_WAKE_OP, +    /// `FUTEX_LOCK_PI` +    LockPi = linux_raw_sys::general::FUTEX_LOCK_PI, +    /// `FUTEX_UNLOCK_PI` +    UnlockPi = linux_raw_sys::general::FUTEX_UNLOCK_PI, +    /// `FUTEX_TRYLOCK_PI` +    TrylockPi = linux_raw_sys::general::FUTEX_TRYLOCK_PI, +    /// `FUTEX_WAIT_BITSET` +    WaitBitset = linux_raw_sys::general::FUTEX_WAIT_BITSET, +} diff --git a/vendor/rustix/src/backend/linux_raw/thread/mod.rs b/vendor/rustix/src/backend/linux_raw/thread/mod.rs new file mode 100644 index 0000000..6a002c6 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/thread/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod futex; +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs new file mode 100644 index 0000000..0095eed --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs @@ -0,0 +1,347 @@ +//! linux_raw syscalls supporting `rustix::thread`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::{ +    by_mut, by_ref, c_int, c_uint, ret, ret_c_int, ret_c_int_infallible, ret_usize, +    slice_just_addr, slice_just_addr_mut, zero, +}; +use crate::fd::BorrowedFd; +use crate::io; +use crate::pid::Pid; +use crate::thread::{ClockId, FutexFlags, FutexOperation, NanosleepRelativeResult, Timespec}; +use core::mem::MaybeUninit; +#[cfg(target_pointer_width = "32")] +use linux_raw_sys::general::timespec as __kernel_old_timespec; +use linux_raw_sys::general::{__kernel_timespec, TIMER_ABSTIME}; + +#[inline] +pub(crate) fn clock_nanosleep_relative( +    id: ClockId, +    req: &__kernel_timespec, +) -> NanosleepRelativeResult { +    #[cfg(target_pointer_width = "32")] +    unsafe { +        let mut rem = MaybeUninit::<__kernel_timespec>::uninit(); +        match ret(syscall!( +            __NR_clock_nanosleep_time64, +            id, +            c_int(0), +            by_ref(req), +            &mut rem +        )) +        .or_else(|err| { +            // See the comments in `rustix_clock_gettime_via_syscall` about +            // emulation. +            if err == io::Errno::NOSYS { +                clock_nanosleep_relative_old(id, req, &mut rem) +            } else { +                Err(err) +            } +        }) { +            Ok(()) => NanosleepRelativeResult::Ok, +            Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()), +            Err(err) => NanosleepRelativeResult::Err(err), +        } +    } +    #[cfg(target_pointer_width = "64")] +    unsafe { +        let mut rem = MaybeUninit::<__kernel_timespec>::uninit(); +        match ret(syscall!( +            __NR_clock_nanosleep, +            id, +            c_int(0), +            by_ref(req), +            &mut rem +        )) { +            Ok(()) => NanosleepRelativeResult::Ok, +            Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()), +            Err(err) => NanosleepRelativeResult::Err(err), +        } +    } +} + +#[cfg(target_pointer_width = "32")] +unsafe fn clock_nanosleep_relative_old( +    id: ClockId, +    req: &__kernel_timespec, +    rem: &mut MaybeUninit<__kernel_timespec>, +) -> io::Result<()> { +    let old_req = __kernel_old_timespec { +        tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, +        tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?, +    }; +    let mut old_rem = MaybeUninit::<__kernel_old_timespec>::uninit(); +    ret(syscall!( +        __NR_clock_nanosleep, +        id, +        c_int(0), +        by_ref(&old_req), +        &mut old_rem +    ))?; +    let old_rem = old_rem.assume_init(); +    rem.write(__kernel_timespec { +        tv_sec: old_rem.tv_sec.into(), +        tv_nsec: old_rem.tv_nsec.into(), +    }); +    Ok(()) +} + +#[inline] +pub(crate) fn clock_nanosleep_absolute(id: ClockId, req: &__kernel_timespec) -> io::Result<()> { +    #[cfg(target_pointer_width = "32")] +    unsafe { +        ret(syscall_readonly!( +            __NR_clock_nanosleep_time64, +            id, +            c_uint(TIMER_ABSTIME), +            by_ref(req), +            zero() +        )) +        .or_else(|err| { +            // See the comments in `rustix_clock_gettime_via_syscall` about +            // emulation. +            if err == io::Errno::NOSYS { +                clock_nanosleep_absolute_old(id, req) +            } else { +                Err(err) +            } +        }) +    } +    #[cfg(target_pointer_width = "64")] +    unsafe { +        ret(syscall_readonly!( +            __NR_clock_nanosleep, +            id, +            c_uint(TIMER_ABSTIME), +            by_ref(req), +            zero() +        )) +    } +} + +#[cfg(target_pointer_width = "32")] +unsafe fn clock_nanosleep_absolute_old(id: ClockId, req: &__kernel_timespec) -> io::Result<()> { +    let old_req = __kernel_old_timespec { +        tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, +        tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?, +    }; +    ret(syscall_readonly!( +        __NR_clock_nanosleep, +        id, +        c_int(0), +        by_ref(&old_req), +        zero() +    )) +} + +#[inline] +pub(crate) fn nanosleep(req: &__kernel_timespec) -> NanosleepRelativeResult { +    #[cfg(target_pointer_width = "32")] +    unsafe { +        let mut rem = MaybeUninit::<__kernel_timespec>::uninit(); +        match ret(syscall!( +            __NR_clock_nanosleep_time64, +            ClockId::Realtime, +            c_int(0), +            by_ref(req), +            &mut rem +        )) +        .or_else(|err| { +            // See the comments in `rustix_clock_gettime_via_syscall` about +            // emulation. +            if err == io::Errno::NOSYS { +                nanosleep_old(req, &mut rem) +            } else { +                Err(err) +            } +        }) { +            Ok(()) => NanosleepRelativeResult::Ok, +            Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()), +            Err(err) => NanosleepRelativeResult::Err(err), +        } +    } +    #[cfg(target_pointer_width = "64")] +    unsafe { +        let mut rem = MaybeUninit::<__kernel_timespec>::uninit(); +        match ret(syscall!(__NR_nanosleep, by_ref(req), &mut rem)) { +            Ok(()) => NanosleepRelativeResult::Ok, +            Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(rem.assume_init()), +            Err(err) => NanosleepRelativeResult::Err(err), +        } +    } +} + +#[cfg(target_pointer_width = "32")] +unsafe fn nanosleep_old( +    req: &__kernel_timespec, +    rem: &mut MaybeUninit<__kernel_timespec>, +) -> io::Result<()> { +    let old_req = __kernel_old_timespec { +        tv_sec: req.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, +        tv_nsec: req.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?, +    }; +    let mut old_rem = MaybeUninit::<__kernel_old_timespec>::uninit(); +    ret(syscall!(__NR_nanosleep, by_ref(&old_req), &mut old_rem))?; +    let old_rem = old_rem.assume_init(); +    rem.write(__kernel_timespec { +        tv_sec: old_rem.tv_sec.into(), +        tv_nsec: old_rem.tv_nsec.into(), +    }); +    Ok(()) +} + +#[inline] +pub(crate) fn gettid() -> Pid { +    unsafe { +        let tid = ret_c_int_infallible(syscall_readonly!(__NR_gettid)); +        Pid::from_raw_unchecked(tid) +    } +} + +// TODO: This could be de-multiplexed. +#[inline] +pub(crate) unsafe fn futex( +    uaddr: *mut u32, +    op: FutexOperation, +    flags: FutexFlags, +    val: u32, +    utime: *const Timespec, +    uaddr2: *mut u32, +    val3: u32, +) -> io::Result<usize> { +    #[cfg(target_pointer_width = "32")] +    { +        ret_usize(syscall!( +            __NR_futex_time64, +            uaddr, +            (op, flags), +            c_uint(val), +            utime, +            uaddr2, +            c_uint(val3) +        )) +        .or_else(|err| { +            // See the comments in `rustix_clock_gettime_via_syscall` about +            // emulation. +            if err == io::Errno::NOSYS { +                futex_old(uaddr, op, flags, val, utime, uaddr2, val3) +            } else { +                Err(err) +            } +        }) +    } +    #[cfg(target_pointer_width = "64")] +    ret_usize(syscall!( +        __NR_futex, +        uaddr, +        (op, flags), +        c_uint(val), +        utime, +        uaddr2, +        c_uint(val3) +    )) +} + +#[cfg(target_pointer_width = "32")] +unsafe fn futex_old( +    uaddr: *mut u32, +    op: FutexOperation, +    flags: FutexFlags, +    val: u32, +    utime: *const Timespec, +    uaddr2: *mut u32, +    val3: u32, +) -> io::Result<usize> { +    let old_utime = __kernel_old_timespec { +        tv_sec: (*utime).tv_sec.try_into().map_err(|_| io::Errno::INVAL)?, +        tv_nsec: (*utime).tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?, +    }; +    ret_usize(syscall!( +        __NR_futex, +        uaddr, +        (op, flags), +        c_uint(val), +        by_ref(&old_utime), +        uaddr2, +        c_uint(val3) +    )) +} + +#[inline] +pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int> { +    unsafe { ret_c_int(syscall_readonly!(__NR_setns, fd, c_int(nstype))) } +} + +#[inline] +pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> { +    unsafe { ret(syscall_readonly!(__NR_unshare, flags)) } +} + +#[inline] +pub(crate) fn capget( +    header: &mut linux_raw_sys::general::__user_cap_header_struct, +    data: &mut [MaybeUninit<linux_raw_sys::general::__user_cap_data_struct>], +) -> io::Result<()> { +    unsafe { +        ret(syscall!( +            __NR_capget, +            by_mut(header), +            slice_just_addr_mut(data) +        )) +    } +} + +#[inline] +pub(crate) fn capset( +    header: &mut linux_raw_sys::general::__user_cap_header_struct, +    data: &[linux_raw_sys::general::__user_cap_data_struct], +) -> io::Result<()> { +    unsafe { ret(syscall!(__NR_capset, by_mut(header), slice_just_addr(data))) } +} + +#[inline] +pub(crate) fn setuid_thread(uid: crate::ugid::Uid) -> io::Result<()> { +    unsafe { ret(syscall_readonly!(__NR_setuid, uid)) } +} + +#[inline] +pub(crate) fn setresuid_thread( +    ruid: crate::ugid::Uid, +    euid: crate::ugid::Uid, +    suid: crate::ugid::Uid, +) -> io::Result<()> { +    #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] +    unsafe { +        ret(syscall_readonly!(__NR_setresuid32, ruid, euid, suid)) +    } +    #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))] +    unsafe { +        ret(syscall_readonly!(__NR_setresuid, ruid, euid, suid)) +    } +} + +#[inline] +pub(crate) fn setgid_thread(gid: crate::ugid::Gid) -> io::Result<()> { +    unsafe { ret(syscall_readonly!(__NR_setgid, gid)) } +} + +#[inline] +pub(crate) fn setresgid_thread( +    rgid: crate::ugid::Gid, +    egid: crate::ugid::Gid, +    sgid: crate::ugid::Gid, +) -> io::Result<()> { +    #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] +    unsafe { +        ret(syscall_readonly!(__NR_setresgid32, rgid, egid, sgid)) +    } +    #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))] +    unsafe { +        ret(syscall_readonly!(__NR_setresgid, rgid, egid, sgid)) +    } +}  | 
