• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Low-level implementation details for libc-like runtime libraries such as
2 //! [origin].
3 //!
4 //! These functions are for implementing thread-local storage (TLS), managing
5 //! threads, loaded libraries, and other process-wide resources. Most of
6 //! `rustix` doesn't care about what other libraries are linked into the
7 //! program or what they're doing, but the features in this module generally
8 //! can only be used by one entity within a process.
9 //!
10 //! The API for these functions is not stable, and this module is
11 //! `doc(hidden)`.
12 //!
13 //! [origin]: https://github.com/sunfishcode/mustang/tree/main/origin
14 //!
15 //! # Safety
16 //!
17 //! This module is intended to be used for implementing a runtime library such
18 //! as libc. Use of these features for any other purpose is likely to create
19 //! serious problems.
20 #![allow(unsafe_code)]
21 
22 use crate::backend;
23 #[cfg(linux_raw)]
24 use crate::ffi::CStr;
25 #[cfg(linux_raw)]
26 #[cfg(feature = "fs")]
27 use crate::fs::AtFlags;
28 #[cfg(linux_raw)]
29 use crate::io;
30 #[cfg(linux_raw)]
31 use crate::process::Pid;
32 #[cfg(linux_raw)]
33 #[cfg(feature = "fs")]
34 use backend::fd::AsFd;
35 #[cfg(linux_raw)]
36 use core::ffi::c_void;
37 
38 #[cfg(linux_raw)]
39 #[cfg(target_arch = "x86")]
40 #[inline]
set_thread_area(u_info: &mut UserDesc) -> io::Result<()>41 pub unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> {
42     backend::runtime::syscalls::tls::set_thread_area(u_info)
43 }
44 
45 #[cfg(linux_raw)]
46 #[cfg(target_arch = "arm")]
47 #[inline]
arm_set_tls(data: *mut c_void) -> io::Result<()>48 pub unsafe fn arm_set_tls(data: *mut c_void) -> io::Result<()> {
49     backend::runtime::syscalls::tls::arm_set_tls(data)
50 }
51 
52 #[cfg(linux_raw)]
53 #[cfg(target_arch = "x86_64")]
54 #[inline]
set_fs(data: *mut c_void)55 pub unsafe fn set_fs(data: *mut c_void) {
56     backend::runtime::syscalls::tls::set_fs(data)
57 }
58 
59 #[cfg(linux_raw)]
60 #[inline]
set_tid_address(data: *mut c_void) -> Pid61 pub unsafe fn set_tid_address(data: *mut c_void) -> Pid {
62     backend::runtime::syscalls::tls::set_tid_address(data)
63 }
64 
65 /// `prctl(PR_SET_NAME, name)`
66 ///
67 /// # References
68 ///  - [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
69 ///
70 /// # Safety
71 ///
72 /// This is a very low-level feature for implementing threading libraries.
73 /// See the references links above.
74 ///
75 /// [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
76 #[cfg(linux_raw)]
77 #[inline]
set_thread_name(name: &CStr) -> io::Result<()>78 pub unsafe fn set_thread_name(name: &CStr) -> io::Result<()> {
79     backend::runtime::syscalls::tls::set_thread_name(name)
80 }
81 
82 #[cfg(linux_raw)]
83 #[cfg(target_arch = "x86")]
84 pub use backend::runtime::tls::UserDesc;
85 
86 /// `syscall(SYS_exit, status)`—Exit the current thread.
87 ///
88 /// # Safety
89 ///
90 /// This is a very low-level feature for implementing threading libraries.
91 #[cfg(linux_raw)]
92 #[inline]
exit_thread(status: i32) -> !93 pub unsafe fn exit_thread(status: i32) -> ! {
94     backend::runtime::syscalls::tls::exit_thread(status)
95 }
96 
97 /// Exit all the threads in the current process' thread group.
98 ///
99 /// This is equivalent to `_exit` and `_Exit` in libc.
100 ///
101 /// This does not all any `__cxa_atexit`, `atexit`, or any other destructors.
102 /// Most programs should use [`std::process::exit`] instead of calling this
103 /// directly.
104 ///
105 /// # References
106 ///  - [POSIX `_Exit`]
107 ///  - [Linux `exit_group`]
108 ///  - [Linux `_Exit`]
109 ///
110 /// [POSIX `_Exit`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
111 /// [Linux `exit_group`]: https://man7.org/linux/man-pages/man2/exit_group.2.html
112 /// [Linux `_Exit`]: https://man7.org/linux/man-pages/man2/exit.2.html
113 #[doc(alias = "_exit")]
114 #[doc(alias = "_Exit")]
115 #[inline]
exit_group(status: i32) -> !116 pub fn exit_group(status: i32) -> ! {
117     backend::process::syscalls::exit_group(status)
118 }
119 
120 /// Return fields from the main executable segment headers ("phdrs") relevant
121 /// to initializing TLS provided to the program at startup.
122 #[cfg(linux_raw)]
123 #[inline]
startup_tls_info() -> StartupTlsInfo124 pub fn startup_tls_info() -> StartupTlsInfo {
125     backend::runtime::tls::startup_tls_info()
126 }
127 
128 /// `(getauxval(AT_PHDR), getauxval(AT_PHNUM))`—Returns the address and
129 /// number of ELF segment headers for the main executable.
130 ///
131 /// # References
132 ///  - [Linux]
133 ///
134 /// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
135 #[cfg(linux_raw)]
136 #[cfg(any(target_os = "android", target_os = "linux"))]
137 #[inline]
exe_phdrs() -> (*const c_void, usize)138 pub fn exe_phdrs() -> (*const c_void, usize) {
139     backend::param::auxv::exe_phdrs()
140 }
141 
142 #[cfg(linux_raw)]
143 pub use backend::runtime::tls::StartupTlsInfo;
144 
145 /// `fork()`—Creates a new process by duplicating the calling process.
146 ///
147 /// On success, the pid of the child process is returned in the parent, and
148 /// `None` is returned in the child.
149 ///
150 /// Unlike its POSIX and libc counterparts, this `fork` does not invoke any
151 /// handlers (such as those registered with `pthread_atfork`).
152 ///
153 /// The program environment in the child after a `fork` and before an `execve`
154 /// is very special. All code that executes in this environment must avoid:
155 ///
156 ///  - Acquiring any other locks that are held in other threads on the parent
157 ///    at the time of the `fork`, as the child only contains one thread, and
158 ///    attempting to acquire such locks will deadlock (though this is [not
159 ///    considered unsafe]).
160 ///
161 ///  - Performing any dynamic allocation using the global allocator, since
162 ///    global allocators may use locks to ensure thread safety, and their locks
163 ///    may not be released in the child process, so attempts to allocate may
164 ///    deadlock (as described in the previous point).
165 ///
166 ///  - Accessing any external state which the parent assumes it has exclusive
167 ///    access to, such as a file protected by a file lock, as this could
168 ///    corrupt the external state.
169 ///
170 ///  - Accessing any random-number-generator state inherited from the parent,
171 ///    as the parent may have the same state and generate the same random
172 ///    numbers, which may violate security invariants.
173 ///
174 ///  - Accessing any thread runtime state, since this function does not update
175 ///    the thread id in the thread runtime, so thread runtime functions could
176 ///    cause undefined behavior.
177 ///
178 ///  - Accessing any memory shared with the parent, such as a [`MAP_SHARED`]
179 ///    mapping, even with anonymous or [`memfd_create`] mappings, as this could
180 ///    cause undefined behavior.
181 ///
182 ///  - Calling any C function which isn't known to be [async-signal-safe], as
183 ///    that could cause undefined behavior. The extent to which this also
184 ///    applies to Rust functions is unclear at this time.
185 ///
186 /// # Safety
187 ///
188 /// The child must avoid accessing any memory shared with the parent in a
189 /// way that invokes undefined behavior. It must avoid accessing any threading
190 /// runtime functions in a way that invokes undefined behavior. And it must
191 /// avoid invoking any undefined behavior through any function that is not
192 /// guaranteed to be async-signal-safe.
193 ///
194 /// # References
195 ///  - [POSIX]
196 ///  - [Linux]
197 ///
198 /// # Literary interlude
199 ///
200 /// > Do not jump on ancient uncles.
201 /// > Do not yell at average mice.
202 /// > Do not wear a broom to breakfast.
203 /// > Do not ask a snake’s advice.
204 /// > Do not bathe in chocolate pudding.
205 /// > Do not talk to bearded bears.
206 /// > Do not smoke cigars on sofas.
207 /// > Do not dance on velvet chairs.
208 /// > Do not take a whale to visit
209 /// > Russell’s mother’s cousin’s yacht.
210 /// > And whatever else you do do
211 /// > It is better you
212 /// > Do not.
213 ///
214 /// - "Rules", by Karla Kuskin
215 ///
216 /// [`MAP_SHARED`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
217 /// [not considered unsafe]: https://doc.rust-lang.org/reference/behavior-not-considered-unsafe.html#deadlocks
218 /// [`memfd_create`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
219 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
220 /// [Linux]: https://man7.org/linux/man-pages/man2/fork.2.html
221 /// [async-signal-safe]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
222 #[cfg(linux_raw)]
fork() -> io::Result<Option<Pid>>223 pub unsafe fn fork() -> io::Result<Option<Pid>> {
224     backend::runtime::syscalls::fork()
225 }
226 
227 /// `execveat(dirfd, path.as_c_str(), argv, envp, flags)`—Execute a new
228 /// command using the current process.
229 ///
230 /// # Safety
231 ///
232 /// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
233 /// their contents must be pointers to NUL-terminated byte arrays.
234 ///
235 /// # References
236 ///  - [Linux]
237 ///
238 /// [Linux]: https://man7.org/linux/man-pages/man2/execveat.2.html
239 #[cfg(linux_raw)]
240 #[inline]
241 #[cfg(feature = "fs")]
242 #[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
execveat<Fd: AsFd>( dirfd: Fd, path: &CStr, argv: *const *const u8, envp: *const *const u8, flags: AtFlags, ) -> io::Errno243 pub unsafe fn execveat<Fd: AsFd>(
244     dirfd: Fd,
245     path: &CStr,
246     argv: *const *const u8,
247     envp: *const *const u8,
248     flags: AtFlags,
249 ) -> io::Errno {
250     backend::runtime::syscalls::execveat(dirfd.as_fd(), path, argv, envp, flags)
251 }
252 
253 /// `execve(path.as_c_str(), argv, envp)`—Execute a new command using the
254 /// current process.
255 ///
256 /// # Safety
257 ///
258 /// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
259 /// their contents must be pointers to NUL-terminated byte arrays.
260 ///
261 /// # References
262 ///  - [Linux]
263 ///
264 /// [Linux]: https://man7.org/linux/man-pages/man2/execve.2.html
265 #[cfg(linux_raw)]
266 #[inline]
execve(path: &CStr, argv: *const *const u8, envp: *const *const u8) -> io::Errno267 pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8) -> io::Errno {
268     backend::runtime::syscalls::execve(path, argv, envp)
269 }
270