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}