1b8a62b91Sopenharmony_ci#![allow(unsafe_code)]
2b8a62b91Sopenharmony_ci
3b8a62b91Sopenharmony_ciuse bitflags::bitflags;
4b8a62b91Sopenharmony_ciuse linux_raw_sys::general::{
5b8a62b91Sopenharmony_ci    CLONE_FILES, CLONE_FS, CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID,
6b8a62b91Sopenharmony_ci    CLONE_NEWTIME, CLONE_NEWUSER, CLONE_NEWUTS, CLONE_SYSVSEM,
7b8a62b91Sopenharmony_ci};
8b8a62b91Sopenharmony_ci
9b8a62b91Sopenharmony_ciuse crate::backend::c::c_int;
10b8a62b91Sopenharmony_ciuse crate::backend::thread::syscalls;
11b8a62b91Sopenharmony_ciuse crate::fd::BorrowedFd;
12b8a62b91Sopenharmony_ciuse crate::io;
13b8a62b91Sopenharmony_ci
14b8a62b91Sopenharmony_cibitflags! {
15b8a62b91Sopenharmony_ci    /// Thread name space type.
16b8a62b91Sopenharmony_ci    pub struct ThreadNameSpaceType: u32 {
17b8a62b91Sopenharmony_ci        /// Time name space.
18b8a62b91Sopenharmony_ci        const TIME = CLONE_NEWTIME;
19b8a62b91Sopenharmony_ci        /// Mount name space.
20b8a62b91Sopenharmony_ci        const MOUNT = CLONE_NEWNS;
21b8a62b91Sopenharmony_ci        /// Control group (CGroup) name space.
22b8a62b91Sopenharmony_ci        const CONTROL_GROUP = CLONE_NEWCGROUP;
23b8a62b91Sopenharmony_ci        /// `Host name` and `NIS domain name` (UTS) name space.
24b8a62b91Sopenharmony_ci        const HOST_NAME_AND_NIS_DOMAIN_NAME = CLONE_NEWUTS;
25b8a62b91Sopenharmony_ci        /// Inter-process communication (IPC) name space.
26b8a62b91Sopenharmony_ci        const INTER_PROCESS_COMMUNICATION = CLONE_NEWIPC;
27b8a62b91Sopenharmony_ci        /// User name space.
28b8a62b91Sopenharmony_ci        const USER = CLONE_NEWUSER;
29b8a62b91Sopenharmony_ci        /// Process ID name space.
30b8a62b91Sopenharmony_ci        const PROCESS_ID = CLONE_NEWPID;
31b8a62b91Sopenharmony_ci        /// Network name space.
32b8a62b91Sopenharmony_ci        const NETWORK = CLONE_NEWNET;
33b8a62b91Sopenharmony_ci    }
34b8a62b91Sopenharmony_ci}
35b8a62b91Sopenharmony_ci
36b8a62b91Sopenharmony_ci/// Type of name space referred to by a link.
37b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)]
38b8a62b91Sopenharmony_ci#[repr(u32)]
39b8a62b91Sopenharmony_cipub enum LinkNameSpaceType {
40b8a62b91Sopenharmony_ci    /// Time name space.
41b8a62b91Sopenharmony_ci    Time = CLONE_NEWTIME,
42b8a62b91Sopenharmony_ci    /// Mount name space.
43b8a62b91Sopenharmony_ci    Mount = CLONE_NEWNS,
44b8a62b91Sopenharmony_ci    /// Control group (CGroup) name space.
45b8a62b91Sopenharmony_ci    ControlGroup = CLONE_NEWCGROUP,
46b8a62b91Sopenharmony_ci    /// `Host name` and `NIS domain name` (UTS) name space.
47b8a62b91Sopenharmony_ci    HostNameAndNISDomainName = CLONE_NEWUTS,
48b8a62b91Sopenharmony_ci    /// Inter-process communication (IPC) name space.
49b8a62b91Sopenharmony_ci    InterProcessCommunication = CLONE_NEWIPC,
50b8a62b91Sopenharmony_ci    /// User name space.
51b8a62b91Sopenharmony_ci    User = CLONE_NEWUSER,
52b8a62b91Sopenharmony_ci    /// Process ID name space.
53b8a62b91Sopenharmony_ci    ProcessID = CLONE_NEWPID,
54b8a62b91Sopenharmony_ci    /// Network name space.
55b8a62b91Sopenharmony_ci    Network = CLONE_NEWNET,
56b8a62b91Sopenharmony_ci}
57b8a62b91Sopenharmony_ci
58b8a62b91Sopenharmony_cibitflags! {
59b8a62b91Sopenharmony_ci    /// `CLONE_*` for use with [`unshare`].
60b8a62b91Sopenharmony_ci    pub struct UnshareFlags: u32 {
61b8a62b91Sopenharmony_ci        /// `CLONE_FILES`.
62b8a62b91Sopenharmony_ci        const FILES = CLONE_FILES;
63b8a62b91Sopenharmony_ci        /// `CLONE_FS`.
64b8a62b91Sopenharmony_ci        const FS = CLONE_FS;
65b8a62b91Sopenharmony_ci        /// `CLONE_NEWCGROUP`.
66b8a62b91Sopenharmony_ci        const NWCGROUP = CLONE_NEWCGROUP;
67b8a62b91Sopenharmony_ci        /// `CLONE_NEWIPC`.
68b8a62b91Sopenharmony_ci        const NEWIPC = CLONE_NEWIPC;
69b8a62b91Sopenharmony_ci        /// `CLONE_NEWNET`.
70b8a62b91Sopenharmony_ci        const NEWNET = CLONE_NEWNET;
71b8a62b91Sopenharmony_ci        /// `CLONE_NEWNS`.
72b8a62b91Sopenharmony_ci        const NEWNS = CLONE_NEWNS;
73b8a62b91Sopenharmony_ci        /// `CLONE_NEWPID`.
74b8a62b91Sopenharmony_ci        const NEWPID = CLONE_NEWPID;
75b8a62b91Sopenharmony_ci        /// `CLONE_NEWTIME`.
76b8a62b91Sopenharmony_ci        const NEWTIME = CLONE_NEWTIME;
77b8a62b91Sopenharmony_ci        /// `CLONE_NEWUSER`.
78b8a62b91Sopenharmony_ci        const NEWUSER = CLONE_NEWUSER;
79b8a62b91Sopenharmony_ci        /// `CLONE_SYSVSEM`.
80b8a62b91Sopenharmony_ci        const SYSVSEM = CLONE_SYSVSEM;
81b8a62b91Sopenharmony_ci    }
82b8a62b91Sopenharmony_ci}
83b8a62b91Sopenharmony_ci
84b8a62b91Sopenharmony_ci/// Reassociate the calling thread with the namespace associated with link referred to by `fd`.
85b8a62b91Sopenharmony_ci///
86b8a62b91Sopenharmony_ci/// `fd` must refer to one of the magic links in a `/proc/[pid]/ns/` directory, or a bind mount
87b8a62b91Sopenharmony_ci/// to such a link.
88b8a62b91Sopenharmony_ci///
89b8a62b91Sopenharmony_ci/// # References
90b8a62b91Sopenharmony_ci/// - [`setns`]
91b8a62b91Sopenharmony_ci///
92b8a62b91Sopenharmony_ci/// [`setns`]: https://man7.org/linux/man-pages/man2/setns.2.html
93b8a62b91Sopenharmony_cipub fn move_into_link_name_space(
94b8a62b91Sopenharmony_ci    fd: BorrowedFd,
95b8a62b91Sopenharmony_ci    allowed_type: Option<LinkNameSpaceType>,
96b8a62b91Sopenharmony_ci) -> io::Result<()> {
97b8a62b91Sopenharmony_ci    let allowed_type = allowed_type.map_or(0, |t| t as c_int);
98b8a62b91Sopenharmony_ci    syscalls::setns(fd, allowed_type).map(|_r| ())
99b8a62b91Sopenharmony_ci}
100b8a62b91Sopenharmony_ci
101b8a62b91Sopenharmony_ci/// Atomically move the calling thread into one or more of the same namespaces as the thread
102b8a62b91Sopenharmony_ci/// referred to by `fd`.
103b8a62b91Sopenharmony_ci///
104b8a62b91Sopenharmony_ci/// `fd` must refer to a thread ID. See: `pidfd_open` and `clone`.
105b8a62b91Sopenharmony_ci///
106b8a62b91Sopenharmony_ci/// # References
107b8a62b91Sopenharmony_ci/// - [`setns`]
108b8a62b91Sopenharmony_ci///
109b8a62b91Sopenharmony_ci/// [`setns`]: https://man7.org/linux/man-pages/man2/setns.2.html
110b8a62b91Sopenharmony_cipub fn move_into_thread_name_spaces(
111b8a62b91Sopenharmony_ci    fd: BorrowedFd,
112b8a62b91Sopenharmony_ci    allowed_types: ThreadNameSpaceType,
113b8a62b91Sopenharmony_ci) -> io::Result<()> {
114b8a62b91Sopenharmony_ci    syscalls::setns(fd, allowed_types.bits() as c_int).map(|_r| ())
115b8a62b91Sopenharmony_ci}
116b8a62b91Sopenharmony_ci
117b8a62b91Sopenharmony_ci/// `unshare(flags)`—Disassociate parts of the current thread's execution
118b8a62b91Sopenharmony_ci/// context with other threads.
119b8a62b91Sopenharmony_ci///
120b8a62b91Sopenharmony_ci/// # References
121b8a62b91Sopenharmony_ci/// - [`unshare`]
122b8a62b91Sopenharmony_ci///
123b8a62b91Sopenharmony_ci/// [`unshare`]: https://man7.org/linux/man-pages/man2/unshare.2.html
124b8a62b91Sopenharmony_cipub fn unshare(flags: UnshareFlags) -> io::Result<()> {
125b8a62b91Sopenharmony_ci    syscalls::unshare(flags)
126b8a62b91Sopenharmony_ci}
127