rustix/thread/
setns.rs

1//! Thread-specific namespace functions.
2//!
3//! # Safety
4//!
5//! The `unshare` function can cause threads to use different file descriptor tables.
6#![allow(unsafe_code)]
7
8use bitflags::bitflags;
9use linux_raw_sys::general::{
10    CLONE_FILES, CLONE_FS, CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID,
11    CLONE_NEWTIME, CLONE_NEWUSER, CLONE_NEWUTS, CLONE_SYSVSEM,
12};
13
14use crate::backend::c::c_int;
15use crate::backend::thread::syscalls;
16use crate::fd::BorrowedFd;
17use crate::io;
18
19bitflags! {
20    /// Thread name space type.
21    #[repr(transparent)]
22    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
23    pub struct ThreadNameSpaceType: u32 {
24        /// Time name space.
25        const TIME = CLONE_NEWTIME;
26        /// Mount name space.
27        const MOUNT = CLONE_NEWNS;
28        /// Control group (CGroup) name space.
29        const CONTROL_GROUP = CLONE_NEWCGROUP;
30        /// `Host name` and `NIS domain name` (UTS) name space.
31        const HOST_NAME_AND_NIS_DOMAIN_NAME = CLONE_NEWUTS;
32        /// Inter-process communication (IPC) name space.
33        const INTER_PROCESS_COMMUNICATION = CLONE_NEWIPC;
34        /// User name space.
35        const USER = CLONE_NEWUSER;
36        /// Process ID name space.
37        const PROCESS_ID = CLONE_NEWPID;
38        /// Network name space.
39        const NETWORK = CLONE_NEWNET;
40
41        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
42        const _ = !0;
43    }
44}
45
46/// Type of name space referred to by a link.
47#[derive(Copy, Clone, Debug, Eq, PartialEq)]
48#[repr(u32)]
49pub enum LinkNameSpaceType {
50    /// Time name space.
51    Time = CLONE_NEWTIME,
52    /// Mount name space.
53    Mount = CLONE_NEWNS,
54    /// Control group (CGroup) name space.
55    ControlGroup = CLONE_NEWCGROUP,
56    /// `Host name` and `NIS domain name` (UTS) name space.
57    HostNameAndNISDomainName = CLONE_NEWUTS,
58    /// Inter-process communication (IPC) name space.
59    InterProcessCommunication = CLONE_NEWIPC,
60    /// User name space.
61    User = CLONE_NEWUSER,
62    /// Process ID name space.
63    ProcessID = CLONE_NEWPID,
64    /// Network name space.
65    Network = CLONE_NEWNET,
66}
67
68bitflags! {
69    /// `CLONE_*` for use with [`unshare`].
70    #[repr(transparent)]
71    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
72    pub struct UnshareFlags: u32 {
73        /// `CLONE_FILES`
74        const FILES = CLONE_FILES;
75        /// `CLONE_FS`
76        const FS = CLONE_FS;
77        /// `CLONE_NEWCGROUP`
78        const NEWCGROUP = CLONE_NEWCGROUP;
79        /// `CLONE_NEWIPC`
80        const NEWIPC = CLONE_NEWIPC;
81        /// `CLONE_NEWNET`
82        const NEWNET = CLONE_NEWNET;
83        /// `CLONE_NEWNS`
84        const NEWNS = CLONE_NEWNS;
85        /// `CLONE_NEWPID`
86        const NEWPID = CLONE_NEWPID;
87        /// `CLONE_NEWTIME`
88        const NEWTIME = CLONE_NEWTIME;
89        /// `CLONE_NEWUSER`
90        const NEWUSER = CLONE_NEWUSER;
91        /// `CLONE_NEWUTS`
92        const NEWUTS = CLONE_NEWUTS;
93        /// `CLONE_SYSVSEM`
94        const SYSVSEM = CLONE_SYSVSEM;
95
96        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
97        const _ = !0;
98    }
99}
100
101/// Reassociate the calling thread with the namespace associated with link
102/// referred to by `fd`.
103///
104/// `fd` must refer to one of the magic links in a `/proc/[pid]/ns/` directory,
105/// or a bind mount to such a link.
106///
107/// # References
108///  - [Linux]
109///
110/// [Linux]: https://man7.org/linux/man-pages/man2/setns.2.html
111#[doc(alias = "setns")]
112pub fn move_into_link_name_space(
113    fd: BorrowedFd<'_>,
114    allowed_type: Option<LinkNameSpaceType>,
115) -> io::Result<()> {
116    let allowed_type = allowed_type.map_or(0, |t| t as c_int);
117    syscalls::setns(fd, allowed_type).map(|_r| ())
118}
119
120/// Atomically move the calling thread into one or more of the same namespaces
121/// as the thread referred to by `fd`.
122///
123/// `fd` must refer to a thread ID. See: `pidfd_open` and `clone`.
124///
125/// # References
126///  - [Linux]
127///
128/// [Linux]: https://man7.org/linux/man-pages/man2/setns.2.html
129#[doc(alias = "setns")]
130pub fn move_into_thread_name_spaces(
131    fd: BorrowedFd<'_>,
132    allowed_types: ThreadNameSpaceType,
133) -> io::Result<()> {
134    syscalls::setns(fd, allowed_types.bits() as c_int).map(|_r| ())
135}
136
137/// `unshare(flags)`—Deprecated in favor of [`unshare_unsafe`].
138///
139/// This function should be unsafe; see the safety comment on `unshare_unsafe`.
140#[deprecated(since = "1.1.0", note = "Use `unshare_unsafe`")]
141pub fn unshare(flags: UnshareFlags) -> io::Result<()> {
142    // SAFETY: This is not actually safe. This function is deprecated and users
143    // should use `unshare_unsafe` instead.
144    unsafe { syscalls::unshare(flags) }
145}
146
147/// `unshare(flags)`—Disassociate parts of the current thread's execution
148/// context with other threads.
149///
150/// # Safety
151///
152/// When using `UnshareFlags::FILES`, this function can cause one thread to be
153/// unable to use file descriptors created on a different thread. Callers must
154/// ensure that threads never observe file descriptors from unshared tables.
155///
156/// # References
157///  - [Linux]
158///
159/// [Linux]: https://man7.org/linux/man-pages/man2/unshare.2.html
160pub unsafe fn unshare_unsafe(flags: UnshareFlags) -> io::Result<()> {
161    syscalls::unshare(flags)
162}