]> git.proxmox.com Git - rustc.git/blob - vendor/rustix/src/backend/linux_raw/runtime/syscalls.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / vendor / rustix / src / backend / linux_raw / runtime / syscalls.rs
1 //! linux_raw syscalls supporting `rustix::runtime`.
2 //!
3 //! # Safety
4 //!
5 //! See the `rustix::backend` module documentation for details.
6 #![allow(unsafe_code)]
7 #![allow(clippy::undocumented_unsafe_blocks)]
8
9 use super::super::c;
10 #[cfg(target_arch = "x86")]
11 use super::super::conv::by_mut;
12 use super::super::conv::{
13 by_ref, c_int, c_uint, ret, ret_c_int, ret_c_uint, ret_error, ret_usize_infallible, size_of,
14 zero,
15 };
16 #[cfg(feature = "fs")]
17 use crate::fd::BorrowedFd;
18 use crate::ffi::CStr;
19 #[cfg(feature = "fs")]
20 use crate::fs::AtFlags;
21 use crate::io;
22 use crate::process::{Pid, RawNonZeroPid, Signal};
23 use crate::runtime::{How, Sigaction, Siginfo, Sigset, Stack, Timespec};
24 use crate::utils::optional_as_ptr;
25 #[cfg(target_pointer_width = "32")]
26 use core::convert::TryInto;
27 use core::mem::MaybeUninit;
28 #[cfg(target_pointer_width = "32")]
29 use linux_raw_sys::general::__kernel_old_timespec;
30 use linux_raw_sys::general::{__kernel_pid_t, kernel_sigset_t, PR_SET_NAME, SIGCHLD};
31 #[cfg(target_arch = "x86_64")]
32 use {super::super::conv::ret_infallible, linux_raw_sys::general::ARCH_SET_FS};
33
34 #[inline]
35 pub(crate) unsafe fn fork() -> io::Result<Option<Pid>> {
36 let pid = ret_c_uint(syscall_readonly!(
37 __NR_clone,
38 c_uint(SIGCHLD),
39 zero(),
40 zero(),
41 zero(),
42 zero()
43 ))?;
44 Ok(Pid::from_raw(pid))
45 }
46
47 #[cfg(feature = "fs")]
48 pub(crate) unsafe fn execveat(
49 dirfd: BorrowedFd<'_>,
50 path: &CStr,
51 args: *const *const u8,
52 env_vars: *const *const u8,
53 flags: AtFlags,
54 ) -> io::Errno {
55 ret_error(syscall_readonly!(
56 __NR_execveat,
57 dirfd,
58 path,
59 args,
60 env_vars,
61 flags
62 ))
63 }
64
65 pub(crate) unsafe fn execve(
66 path: &CStr,
67 args: *const *const u8,
68 env_vars: *const *const u8,
69 ) -> io::Errno {
70 ret_error(syscall_readonly!(__NR_execve, path, args, env_vars))
71 }
72
73 pub(crate) mod tls {
74 #[cfg(target_arch = "x86")]
75 use super::super::tls::UserDesc;
76 use super::*;
77
78 #[cfg(target_arch = "x86")]
79 #[inline]
80 pub(crate) unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> {
81 ret(syscall!(__NR_set_thread_area, by_mut(u_info)))
82 }
83
84 #[cfg(target_arch = "arm")]
85 #[inline]
86 pub(crate) unsafe fn arm_set_tls(data: *mut c::c_void) -> io::Result<()> {
87 ret(syscall_readonly!(__ARM_NR_set_tls, data))
88 }
89
90 #[cfg(target_arch = "x86_64")]
91 #[inline]
92 pub(crate) unsafe fn set_fs(data: *mut c::c_void) {
93 ret_infallible(syscall_readonly!(
94 __NR_arch_prctl,
95 c_uint(ARCH_SET_FS),
96 data
97 ))
98 }
99
100 #[inline]
101 pub(crate) unsafe fn set_tid_address(data: *mut c::c_void) -> Pid {
102 let tid: i32 =
103 ret_usize_infallible(syscall_readonly!(__NR_set_tid_address, data)) as __kernel_pid_t;
104 debug_assert_ne!(tid, 0);
105 Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid as u32))
106 }
107
108 #[inline]
109 pub(crate) unsafe fn set_thread_name(name: &CStr) -> io::Result<()> {
110 ret(syscall_readonly!(__NR_prctl, c_uint(PR_SET_NAME), name))
111 }
112
113 #[inline]
114 pub(crate) fn exit_thread(code: c::c_int) -> ! {
115 unsafe { syscall_noreturn!(__NR_exit, c_int(code)) }
116 }
117 }
118
119 #[inline]
120 pub(crate) unsafe fn sigaction(signal: Signal, new: Option<Sigaction>) -> io::Result<Sigaction> {
121 let mut old = MaybeUninit::<Sigaction>::uninit();
122 let new = optional_as_ptr(new.as_ref());
123 ret(syscall!(
124 __NR_rt_sigaction,
125 signal,
126 new,
127 &mut old,
128 size_of::<kernel_sigset_t, _>()
129 ))?;
130 Ok(old.assume_init())
131 }
132
133 #[inline]
134 pub(crate) unsafe fn sigaltstack(new: Option<Stack>) -> io::Result<Stack> {
135 let mut old = MaybeUninit::<Stack>::uninit();
136 let new = optional_as_ptr(new.as_ref());
137 ret(syscall!(__NR_sigaltstack, new, &mut old))?;
138 Ok(old.assume_init())
139 }
140
141 #[inline]
142 pub(crate) unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> {
143 ret(syscall_readonly!(__NR_tkill, tid, sig))
144 }
145
146 #[inline]
147 pub(crate) unsafe fn sigprocmask(how: How, set: &Sigset) -> io::Result<Sigset> {
148 let mut old = MaybeUninit::<Sigset>::uninit();
149 ret(syscall!(
150 __NR_rt_sigprocmask,
151 how,
152 by_ref(set),
153 &mut old,
154 size_of::<kernel_sigset_t, _>()
155 ))?;
156 Ok(old.assume_init())
157 }
158
159 #[inline]
160 pub(crate) fn sigwait(set: &Sigset) -> io::Result<Signal> {
161 unsafe {
162 match Signal::from_raw(ret_c_int(syscall_readonly!(
163 __NR_rt_sigtimedwait,
164 by_ref(set),
165 zero(),
166 zero(),
167 size_of::<kernel_sigset_t, _>()
168 ))?) {
169 Some(signum) => Ok(signum),
170 None => Err(io::Errno::NOTSUP),
171 }
172 }
173 }
174
175 #[inline]
176 pub(crate) fn sigwaitinfo(set: &Sigset) -> io::Result<Siginfo> {
177 let mut info = MaybeUninit::<Siginfo>::uninit();
178 unsafe {
179 let _signum = ret_c_int(syscall!(
180 __NR_rt_sigtimedwait,
181 by_ref(set),
182 &mut info,
183 zero(),
184 size_of::<kernel_sigset_t, _>()
185 ))?;
186 Ok(info.assume_init())
187 }
188 }
189
190 #[inline]
191 pub(crate) fn sigtimedwait(set: &Sigset, timeout: Option<Timespec>) -> io::Result<Siginfo> {
192 let mut info = MaybeUninit::<Siginfo>::uninit();
193 let timeout_ptr = optional_as_ptr(timeout.as_ref());
194
195 #[cfg(target_pointer_width = "32")]
196 unsafe {
197 match ret_c_int(syscall!(
198 __NR_rt_sigtimedwait_time64,
199 by_ref(set),
200 &mut info,
201 timeout_ptr,
202 size_of::<kernel_sigset_t, _>()
203 )) {
204 Ok(_signum) => (),
205 Err(io::Errno::NOSYS) => sigtimedwait_old(set, timeout, &mut info)?,
206 Err(err) => return Err(err),
207 }
208 Ok(info.assume_init())
209 }
210
211 #[cfg(target_pointer_width = "64")]
212 unsafe {
213 let _signum = ret_c_int(syscall!(
214 __NR_rt_sigtimedwait,
215 by_ref(set),
216 &mut info,
217 timeout_ptr,
218 size_of::<kernel_sigset_t, _>()
219 ))?;
220 Ok(info.assume_init())
221 }
222 }
223
224 #[cfg(target_pointer_width = "32")]
225 unsafe fn sigtimedwait_old(
226 set: &Sigset,
227 timeout: Option<Timespec>,
228 info: &mut MaybeUninit<Siginfo>,
229 ) -> io::Result<()> {
230 let old_timeout = match timeout {
231 Some(timeout) => Some(__kernel_old_timespec {
232 tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?,
233 tv_nsec: timeout.tv_nsec as _,
234 }),
235 None => None,
236 };
237
238 let old_timeout_ptr = optional_as_ptr(old_timeout.as_ref());
239
240 let _signum = ret_c_int(syscall!(
241 __NR_rt_sigtimedwait,
242 by_ref(set),
243 info,
244 old_timeout_ptr,
245 size_of::<kernel_sigset_t, _>()
246 ))?;
247
248 Ok(())
249 }