rustix/thread/id.rs
1//! CPU and thread identifiers.
2//!
3//! # Safety
4//!
5//! The `Cpuid`, type can be constructed from raw integers, which is marked
6//! unsafe because actual OS's assign special meaning to some integer values.
7
8#![allow(unsafe_code)]
9use crate::{backend, io};
10#[cfg(linux_kernel)]
11use backend::thread::types::RawCpuid;
12
13pub use crate::pid::{Pid, RawPid};
14pub use crate::ugid::{Gid, RawGid, RawUid, Uid};
15
16/// A Linux CPU ID.
17#[cfg(linux_kernel)]
18#[repr(transparent)]
19#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
20pub struct Cpuid(RawCpuid);
21
22#[cfg(linux_kernel)]
23impl Cpuid {
24 /// Converts a `RawCpuid` into a `Cpuid`.
25 ///
26 /// # Safety
27 ///
28 /// `raw` must be the value of a valid Linux CPU ID.
29 #[inline]
30 pub const unsafe fn from_raw(raw: RawCpuid) -> Self {
31 Self(raw)
32 }
33
34 /// Converts a `Cpuid` into a `RawCpuid`.
35 #[inline]
36 pub const fn as_raw(self) -> RawCpuid {
37 self.0
38 }
39}
40
41/// `gettid()`—Returns the thread ID.
42///
43/// This returns the OS thread ID, which is not necessarily the same as the
44/// Rust's `std::thread::Thread::id` or the pthread ID.
45///
46/// This function always does a system call. To avoid this overhead, ask the
47/// thread runtime for the ID instead, for example using [`libc::gettid`] or
48/// [`origin::thread::current_id`].
49///
50/// [`libc::gettid`]: https://docs.rs/libc/*/libc/fn.gettid.html
51/// [`origin::thread::current_id`]: https://docs.rs/origin/*/origin/thread/fn.current_id.html
52///
53/// # References
54/// - [Linux]
55///
56/// [Linux]: https://man7.org/linux/man-pages/man2/gettid.2.html
57#[inline]
58#[must_use]
59pub fn gettid() -> Pid {
60 backend::thread::syscalls::gettid()
61}
62
63/// `setuid(uid)`—Sets the effective user ID of the calling thread.
64///
65/// # Warning
66///
67/// This is not the `setuid` you are looking for… POSIX requires uids to be
68/// process granular, but on Linux they are per-thread. Thus, this call only
69/// changes the uid for the current *thread*, not the entire process even
70/// though that is in violation of the POSIX standard.
71///
72/// For details on this distinction, see the C library vs. kernel differences
73/// in the [manual page][linux_notes]. This call implements the kernel
74/// behavior.
75///
76/// # References
77/// - [POSIX]
78/// - [Linux]
79///
80/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/setuid.html
81/// [Linux]: https://man7.org/linux/man-pages/man2/setuid.2.html
82/// [linux_notes]: https://man7.org/linux/man-pages/man2/setuid.2.html#NOTES
83#[inline]
84pub fn set_thread_uid(uid: Uid) -> io::Result<()> {
85 backend::thread::syscalls::setuid_thread(uid)
86}
87
88/// `setresuid(ruid, euid, suid)`—Sets the real, effective, and saved user ID
89/// of the calling thread.
90///
91/// # Warning
92///
93/// This is not the `setresuid` you are looking for… POSIX requires uids to be
94/// process granular, but on Linux they are per-thread. Thus, this call only
95/// changes the uid for the current *thread*, not the entire process even
96/// though that is in violation of the POSIX standard.
97///
98/// For details on this distinction, see the C library vs. kernel differences
99/// in the [manual page][linux_notes] and the notes in [`set_thread_uid`]. This
100/// call implements the kernel behavior.
101///
102/// # References
103/// - [Linux]
104///
105/// [Linux]: https://man7.org/linux/man-pages/man2/setresuid.2.html
106/// [linux_notes]: https://man7.org/linux/man-pages/man2/setresuid.2.html#NOTES
107#[inline]
108pub fn set_thread_res_uid<R, E, S>(ruid: R, euid: E, suid: S) -> io::Result<()>
109where
110 R: Into<Option<Uid>>,
111 E: Into<Option<Uid>>,
112 S: Into<Option<Uid>>,
113{
114 backend::thread::syscalls::setresuid_thread(ruid.into(), euid.into(), suid.into())
115}
116
117/// `setgid(gid)`—Sets the effective group ID of the current thread.
118///
119/// # Warning
120///
121/// This is not the `setgid` you are looking for… POSIX requires gids to be
122/// process granular, but on Linux they are per-thread. Thus, this call only
123/// changes the gid for the current *thread*, not the entire process even
124/// though that is in violation of the POSIX standard.
125///
126/// For details on this distinction, see the C library vs. kernel differences
127/// in the [manual page][linux_notes]. This call implements the kernel
128/// behavior.
129///
130/// # References
131/// - [POSIX]
132/// - [Linux]
133///
134/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/setgid.html
135/// [Linux]: https://man7.org/linux/man-pages/man2/setgid.2.html
136/// [linux_notes]: https://man7.org/linux/man-pages/man2/setgid.2.html#NOTES
137#[inline]
138pub fn set_thread_gid(gid: Gid) -> io::Result<()> {
139 backend::thread::syscalls::setgid_thread(gid)
140}
141
142/// `setresgid(rgid, egid, sgid)`—Sets the real, effective, and saved group
143/// ID of the current thread.
144///
145/// # Warning
146///
147/// This is not the `setresgid` you are looking for… POSIX requires gids to be
148/// process granular, but on Linux they are per-thread. Thus, this call only
149/// changes the gid for the current *thread*, not the entire process even
150/// though that is in violation of the POSIX standard.
151///
152/// For details on this distinction, see the C library vs. kernel differences
153/// in the [manual page][linux_notes] and the notes in [`set_thread_gid`]. This
154/// call implements the kernel behavior.
155///
156/// # References
157/// - [Linux]
158///
159/// [Linux]: https://man7.org/linux/man-pages/man2/setresgid.2.html
160/// [linux_notes]: https://man7.org/linux/man-pages/man2/setresgid.2.html#NOTES
161#[inline]
162pub fn set_thread_res_gid<R, E, S>(rgid: R, egid: E, sgid: S) -> io::Result<()>
163where
164 R: Into<Option<Gid>>,
165 E: Into<Option<Gid>>,
166 S: Into<Option<Gid>>,
167{
168 backend::thread::syscalls::setresgid_thread(rgid.into(), egid.into(), sgid.into())
169}
170
171/// `setgroups(groups)`—Sets the supplementary group IDs for the calling
172/// thread.
173///
174/// # Warning
175///
176/// This is not the `setgroups` you are looking for… POSIX requires gids to be
177/// process granular, but on Linux they are per-thread. Thus, this call only
178/// changes the gids for the current *thread*, not the entire process even
179/// though that is in violation of the POSIX standard.
180///
181/// For details on this distinction, see the C library vs. kernel differences
182/// in the [manual page][linux_notes]. This call implements the kernel
183/// behavior.
184///
185/// # References
186/// - [Linux]
187///
188/// [Linux]: https://man7.org/linux/man-pages/man2/setgroups.2.html
189/// [linux_notes]: https://man7.org/linux/man-pages/man2/setgroups.2.html#NOTES
190#[cfg(linux_kernel)]
191#[inline]
192pub fn set_thread_groups(groups: &[Gid]) -> io::Result<()> {
193 backend::thread::syscalls::setgroups_thread(groups)
194}