1use linux_syscall::{Result as LinuxSyscallResult, Result64};
2use num_enum::{IntoPrimitive, TryFromPrimitive};
3
4use crate::errno::Errno;
5use crate::ldt::linux_user_desc;
6use crate::posix_types::{Pid, kernel_pid_t};
7use crate::signal::Signal;
8use crate::{bindings, const_conversions};
9
10#[allow(non_camel_case_types)]
11#[repr(i32)]
12#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
13pub enum Sched {
14 SCHED_NORMAL = const_conversions::i32_from_u32(bindings::LINUX_SCHED_NORMAL),
15 SCHED_FIFO = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FIFO),
16 SCHED_RR = const_conversions::i32_from_u32(bindings::LINUX_SCHED_RR),
17 SCHED_BATCH = const_conversions::i32_from_u32(bindings::LINUX_SCHED_BATCH),
18 SCHED_IDLE = const_conversions::i32_from_u32(bindings::LINUX_SCHED_IDLE),
19 SCHED_DEADLINE = const_conversions::i32_from_u32(bindings::LINUX_SCHED_DEADLINE),
20 SCHED_EXT = const_conversions::i32_from_u32(bindings::LINUX_SCHED_EXT),
21}
22
23pub const SCHED_RESET_ON_FORK: i32 =
24 const_conversions::i32_from_u32(bindings::LINUX_SCHED_RESET_ON_FORK);
25
26bitflags::bitflags! {
27 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
28 pub struct SchedFlags: i32 {
29 const SCHED_FLAG_RESET_ON_FORK = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_RESET_ON_FORK);
30 const SCHED_FLAG_RECLAIM = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_RECLAIM);
31 const SCHED_FLAG_DL_OVERRUN = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_DL_OVERRUN);
32 const SCHED_FLAG_KEEP_POLICY = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_KEEP_POLICY);
33 const SCHED_FLAG_KEEP_PARAMS = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_KEEP_PARAMS);
34 const SCHED_FLAG_UTIL_CLAMP_MIN = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_UTIL_CLAMP_MIN);
35 const SCHED_FLAG_UTIL_CLAMP_MAX = const_conversions::i32_from_u32(bindings::LINUX_SCHED_FLAG_UTIL_CLAMP_MAX);
36 }
37}
38
39#[allow(non_camel_case_types)]
42pub type sched_attr = bindings::linux_sched_attr;
43
44bitflags::bitflags! {
45 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
49 pub struct CloneFlags: u64 {
50 const CLONE_CLEAR_SIGHAND = bindings::LINUX_CLONE_CLEAR_SIGHAND;
51 const CLONE_INTO_CGROUP = bindings::LINUX_CLONE_INTO_CGROUP;
52 const CLONE_NEWTIME = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWTIME);
53 const CLONE_VM = const_conversions::u64_from_u32(bindings::LINUX_CLONE_VM);
54 const CLONE_FS = const_conversions::u64_from_u32(bindings::LINUX_CLONE_FS);
55 const CLONE_FILES = const_conversions::u64_from_u32(bindings::LINUX_CLONE_FILES);
56 const CLONE_SIGHAND = const_conversions::u64_from_u32(bindings::LINUX_CLONE_SIGHAND);
57 const CLONE_PIDFD = const_conversions::u64_from_u32(bindings::LINUX_CLONE_PIDFD);
58 const CLONE_PTRACE = const_conversions::u64_from_u32(bindings::LINUX_CLONE_PTRACE);
59 const CLONE_VFORK = const_conversions::u64_from_u32(bindings::LINUX_CLONE_VFORK);
60 const CLONE_PARENT = const_conversions::u64_from_u32(bindings::LINUX_CLONE_PARENT);
61 const CLONE_THREAD = const_conversions::u64_from_u32(bindings::LINUX_CLONE_THREAD);
62 const CLONE_NEWNS = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWNS);
63 const CLONE_SYSVSEM = const_conversions::u64_from_u32(bindings::LINUX_CLONE_SYSVSEM);
64 const CLONE_SETTLS = const_conversions::u64_from_u32(bindings::LINUX_CLONE_SETTLS);
65 const CLONE_PARENT_SETTID = const_conversions::u64_from_u32(bindings::LINUX_CLONE_PARENT_SETTID);
66 const CLONE_CHILD_CLEARTID = const_conversions::u64_from_u32(bindings::LINUX_CLONE_CHILD_CLEARTID);
67 const CLONE_DETACHED = const_conversions::u64_from_u32(bindings::LINUX_CLONE_DETACHED);
68 const CLONE_UNTRACED = const_conversions::u64_from_u32(bindings::LINUX_CLONE_UNTRACED);
69 const CLONE_CHILD_SETTID = const_conversions::u64_from_u32(bindings::LINUX_CLONE_CHILD_SETTID);
70 const CLONE_NEWCGROUP = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWCGROUP);
71 const CLONE_NEWUTS = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWUTS);
72 const CLONE_NEWIPC = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWIPC);
73 const CLONE_NEWUSER = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWUSER);
74 const CLONE_NEWPID = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWPID);
75 const CLONE_NEWNET = const_conversions::u64_from_u32(bindings::LINUX_CLONE_NEWNET);
76 const CLONE_IO = const_conversions::u64_from_u32(bindings::LINUX_CLONE_IO);
77 }
78}
79
80pub use bindings::linux_clone_args;
81#[allow(non_camel_case_types)]
82pub type clone_args = linux_clone_args;
83
84#[allow(clippy::derivable_impls)]
85impl Default for clone_args {
86 fn default() -> Self {
87 Self {
88 flags: Default::default(),
89 pidfd: Default::default(),
90 child_tid: Default::default(),
91 parent_tid: Default::default(),
92 exit_signal: Default::default(),
93 stack: Default::default(),
94 stack_size: Default::default(),
95 tls: Default::default(),
96 set_tid: Default::default(),
97 set_tid_size: Default::default(),
98 cgroup: Default::default(),
99 }
100 }
101}
102
103impl clone_args {
104 #[inline]
105 pub fn with_flags(mut self, flags: CloneFlags) -> Self {
106 self.flags = flags.bits();
107 self
108 }
109
110 #[inline]
111 pub fn with_exit_signal(mut self, exit_signal: Option<Signal>) -> Self {
112 self.exit_signal = u64::try_from(Signal::as_raw(exit_signal)).unwrap();
113 self
114 }
115}
116
117unsafe impl shadow_pod::Pod for clone_args {}
118unsafe impl shadow_pod::Pod for sched_attr {}
119
120#[derive(Copy, Clone, PartialEq, Eq)]
123pub struct SuidDump(i32);
124
125impl SuidDump {
126 pub const SUID_DUMP_DISABLE: Self = Self(const_conversions::i32_from_u32(
127 bindings::LINUX_SUID_DUMP_DISABLE,
128 ));
129 pub const SUID_DUMP_USER: Self = Self(const_conversions::i32_from_u32(
130 bindings::LINUX_SUID_DUMP_USER,
131 ));
132 pub const SUID_DUMP_ROOT: Self = Self(const_conversions::i32_from_u32(
133 bindings::LINUX_SUID_DUMP_ROOT,
134 ));
135 pub const fn new(val: i32) -> Self {
138 Self(val)
139 }
140
141 pub const fn val(&self) -> i32 {
142 self.0
143 }
144
145 pub const fn to_str(&self) -> Option<&'static str> {
146 match *self {
147 Self::SUID_DUMP_DISABLE => Some("SUID_DUMP_DISABLE"),
148 Self::SUID_DUMP_USER => Some("SUID_DUMP_USER"),
149 Self::SUID_DUMP_ROOT => Some("SUID_DUMP_ROOT"),
150 _ => None,
151 }
152 }
153}
154
155impl core::fmt::Display for SuidDump {
156 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
157 match self.to_str() {
158 Some(s) => formatter.write_str(s),
159 None => write!(formatter, "(unknown dumpable option {})", self.0),
160 }
161 }
162}
163
164impl core::fmt::Debug for SuidDump {
165 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
166 match self.to_str() {
167 Some(s) => write!(formatter, "SuidDump::{s}"),
168 None => write!(formatter, "SuidDump::<{}>", self.0),
169 }
170 }
171}
172
173pub fn sched_yield() -> Result<(), Errno> {
174 unsafe { linux_syscall::syscall!(linux_syscall::SYS_sched_yield) }
175 .check()
176 .map_err(Errno::from)
177}
178
179pub unsafe fn clone_raw(
183 flags: core::ffi::c_ulong,
184 stack: core::ffi::c_ulong,
185 parent_tid: *mut core::ffi::c_int,
186 child_tid: *mut core::ffi::c_int,
187 tls: core::ffi::c_ulong,
188) -> Result<core::ffi::c_long, Errno> {
189 unsafe {
190 linux_syscall::syscall!(
191 linux_syscall::SYS_clone,
192 flags,
193 stack,
194 parent_tid,
195 child_tid,
196 tls
197 )
198 }
199 .try_i64()
200 .map_err(Errno::from)
201}
202
203pub unsafe fn clone3_raw(args: *const clone_args, size: usize) -> Result<core::ffi::c_long, Errno> {
207 unsafe { linux_syscall::syscall!(linux_syscall::SYS_clone3, args, size,) }
208 .try_i64()
209 .map_err(Errno::from)
210}
211
212pub enum CloneResult {
213 CallerIsChild,
214 CallerIsParent(Pid),
216}
217
218pub unsafe fn clone(
222 flags: CloneFlags,
223 exit_signal: Option<Signal>,
224 stack: *mut core::ffi::c_void,
225 parent_tid: *mut kernel_pid_t,
226 child_tid: *mut kernel_pid_t,
227 tls: *mut linux_user_desc,
228) -> Result<CloneResult, Errno> {
229 unsafe {
230 clone_raw(
231 flags.bits() | u64::try_from(Signal::as_raw(exit_signal)).unwrap(),
232 stack as core::ffi::c_ulong,
233 parent_tid,
234 child_tid,
235 tls as core::ffi::c_ulong,
236 )
237 }
238 .map(|res| match res.cmp(&0) {
239 core::cmp::Ordering::Equal => CloneResult::CallerIsChild,
240 core::cmp::Ordering::Greater => {
241 CloneResult::CallerIsParent(Pid::from_raw(res.try_into().unwrap()).unwrap())
242 }
243 core::cmp::Ordering::Less => unreachable!(),
244 })
245}
246
247pub unsafe fn clone3(args: &clone_args) -> Result<CloneResult, Errno> {
251 unsafe { clone3_raw(args, core::mem::size_of::<clone_args>()) }.map(|res| match res.cmp(&0) {
252 core::cmp::Ordering::Equal => CloneResult::CallerIsChild,
253 core::cmp::Ordering::Greater => {
254 CloneResult::CallerIsParent(Pid::from_raw(res.try_into().unwrap()).unwrap())
255 }
256 core::cmp::Ordering::Less => unreachable!(),
257 })
258}
259
260pub unsafe fn fork_raw() -> Result<core::ffi::c_long, Errno> {
275 unsafe { linux_syscall::syscall!(linux_syscall::SYS_fork) }
276 .try_i64()
277 .map_err(Errno::from)
278}
279
280pub unsafe fn fork() -> Result<CloneResult, Errno> {
284 unsafe { fork_raw() }.map(|res| match res.cmp(&0) {
285 core::cmp::Ordering::Equal => CloneResult::CallerIsChild,
286 core::cmp::Ordering::Greater => {
287 CloneResult::CallerIsParent(Pid::from_raw(res.try_into().unwrap()).unwrap())
288 }
289 core::cmp::Ordering::Less => unreachable!(),
290 })
291}