1use crate::components;
3use crate::error::Result;
4
5pub struct Config {
9 anti_tracing: bool,
10 fs: Fs,
11 unstable: Unstable,
12 win_dacl: WinDacl,
13}
14
15impl Default for Config {
16 fn default() -> Self {
17 Self::DEFAULT
18 }
19}
20
21impl Config {
22 pub const DEFAULT: Self = Self {
24 anti_tracing: true,
25 fs: Fs::DEFAULT,
26 unstable: Unstable::DEFAULT,
27 win_dacl: WinDacl::DEFAULT,
28 };
29
30 #[must_use]
33 pub const fn new_with_anti_tracing(anti_tracing: bool) -> Self {
34 Self {
35 anti_tracing,
36 fs: Fs::DEFAULT,
37 unstable: Unstable::DEFAULT,
38 win_dacl: WinDacl::DEFAULT,
39 }
40 }
41
42 pub fn set_anti_tracing(&mut self, b: bool) {
44 self.anti_tracing = b;
45 }
46
47 pub fn set_fs(&mut self, b: bool) {
49 self.fs = match b {
50 true => Fs::TRUE,
51 false => Fs::FALSE,
52 };
53 }
54
55 pub fn fs_mut(&mut self) -> &mut Fs {
58 &mut self.fs
59 }
60
61 pub fn set_fs_procfs(&mut self, b: bool) {
63 self.fs.set_procfs(b);
64 }
65
66 pub fn set_unstable(&mut self, b: bool) {
73 self.unstable = match b {
74 true => Unstable::TRUE,
75 false => Unstable::FALSE,
76 };
77 }
78
79 pub fn unstable_mut(&mut self) -> &mut Unstable {
82 &mut self.unstable
83 }
84
85 pub fn set_unstable_win_ntapi(&mut self, b: bool) {
92 self.unstable.set_win_ntapi(b);
93 }
94
95 pub fn set_unstable_win_kernelmem(&mut self, b: bool) {
103 self.unstable.set_win_kernelmem(b);
104 }
105
106 pub fn set_win_dacl(&mut self, dacl: WinDacl) {
108 self.win_dacl = dacl;
109 }
110
111 pub fn set_win_dacl_default(&mut self) {
113 self.set_win_dacl(WinDacl::Default);
114 }
115
116 pub fn set_win_dacl_empty(&mut self) {
120 self.set_win_dacl(WinDacl::Empty);
121 }
122
123 pub fn set_win_dacl_custom_user_perm(&mut self, access: WinDaclProcessAccess) {
127 self.set_win_dacl(WinDacl::CustomUserPerm(access));
128 }
129
130 pub fn set_win_dacl_custom_fn(&mut self, fnptr: fn() -> Result) {
135 self.set_win_dacl(WinDacl::CustomFn(fnptr));
136 }
137
138 pub fn harden_process(self) -> Result {
140 {
142 if self.unstable.has_win_ntapi() {
143 #[cfg(all(windows, feature = "unstable"))]
144 components::hide_thread_from_debugger_ntapi()?;
145 }
146 }
147
148 {
150 #[cfg(windows)]
151 self.win_dacl.call()?;
152
153 #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
154 components::disable_tracing_prctl()?;
155
156 #[cfg(unix)]
157 components::disable_core_dumps_rlimit()?;
158 }
159
160 if self.anti_tracing {
162 #[cfg(windows)]
163 components::check_tracer_winapi()?;
164
165 if self.unstable.has_win_kernelmem() {
166 #[cfg(all(windows, feature = "unstable"))]
167 components::check_tracer_unstable()?;
168 }
169
170 if self.fs.has_procfs() {
171 #[cfg(all(target_os = "linux", feature = "std"))]
172 components::check_tracer_procfs()?;
173 }
174
175 #[cfg(target_os = "freebsd")]
176 components::check_tracer_prctl()?;
177 }
178
179 Ok(())
180 }
181}
182
183#[derive(Clone, Debug, PartialEq)]
185pub struct Fs {
186 procfs: bool,
187}
188
189impl Default for Fs {
190 fn default() -> Self {
191 Self::DEFAULT
192 }
193}
194
195impl Fs {
196 pub const DEFAULT: Self = Self::TRUE;
198 pub const FALSE: Self = Self { procfs: false };
200 pub const TRUE: Self = Self { procfs: true };
202
203 pub fn set_procfs(&mut self, b: bool) {
205 self.procfs = b;
206 }
207
208 const fn has_procfs(&self) -> bool {
210 self.procfs
211 }
212}
213
214#[derive(Clone, Debug, PartialEq)]
221pub struct Unstable {
222 win_ntapi: bool,
224 win_kernelmem: bool,
226}
227
228impl Default for Unstable {
229 fn default() -> Self {
230 Self::DEFAULT
231 }
232}
233
234impl Unstable {
235 pub const DEFAULT: Self = Self::FALSE;
237 pub const FALSE: Self = Self {
239 win_ntapi: false,
240 win_kernelmem: false,
241 };
242 pub const TRUE: Self = Self {
244 win_ntapi: true,
245 win_kernelmem: true,
246 };
247
248 pub fn set_win_ntapi(&mut self, b: bool) {
251 self.win_ntapi = b;
252 }
253
254 pub fn set_win_kernelmem(&mut self, b: bool) {
257 self.win_kernelmem = b;
258 }
259
260 const fn has_win_ntapi(&self) -> bool {
262 self.win_ntapi
263 }
264
265 const fn has_win_kernelmem(&self) -> bool {
267 self.win_kernelmem
268 }
269}
270
271pub enum WinDacl {
273 Empty,
276 Default,
278 CustomUserPerm(WinDaclProcessAccess),
281 False,
283 CustomFn(fn() -> Result),
287}
288
289#[derive(Debug, Clone, Copy)]
297pub struct WinDaclProcessAccess(u32);
298
299impl core::ops::BitOr for WinDaclProcessAccess {
300 type Output = Self;
301
302 fn bitor(self, rhs: Self) -> Self::Output {
303 Self(self.0 | rhs.0)
304 }
305}
306
307impl core::ops::BitAnd for WinDaclProcessAccess {
308 type Output = Self;
309
310 fn bitand(self, rhs: Self) -> Self::Output {
311 Self(self.0 & rhs.0)
312 }
313}
314
315impl core::ops::BitOrAssign for WinDaclProcessAccess {
316 fn bitor_assign(&mut self, rhs: Self) {
317 self.0 |= rhs.0;
318 }
319}
320
321impl core::ops::BitAndAssign for WinDaclProcessAccess {
322 fn bitand_assign(&mut self, rhs: Self) {
323 self.0 &= rhs.0;
324 }
325}
326
327#[cfg(windows)]
328impl From<WinDaclProcessAccess> for windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS {
329 fn from(access: WinDaclProcessAccess) -> Self {
330 Self(access.0)
331 }
332}
333
334#[cfg(windows)]
335impl From<&WinDaclProcessAccess> for windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS {
336 fn from(access: &WinDaclProcessAccess) -> Self {
337 Self(access.0)
338 }
339}
340
341#[cfg(windows)]
342impl WinDaclProcessAccess {
343 pub const ALL_ACCESS: Self = Self::new(windows::Win32::System::Threading::PROCESS_ALL_ACCESS);
344 pub const CREATE_PROCESS: Self =
345 Self::new(windows::Win32::System::Threading::PROCESS_CREATE_PROCESS);
346 pub const CREATE_THREAD: Self =
347 Self::new(windows::Win32::System::Threading::PROCESS_CREATE_THREAD);
348 pub const DELETE: Self = Self::new(windows::Win32::System::Threading::PROCESS_DELETE);
349 pub const DUP_HANDLE: Self = Self::new(windows::Win32::System::Threading::PROCESS_DUP_HANDLE);
350 pub const QUERY_INFORMATION: Self =
351 Self::new(windows::Win32::System::Threading::PROCESS_QUERY_INFORMATION);
352 pub const QUERY_LIMITED_INFORMATION: Self =
353 Self::new(windows::Win32::System::Threading::PROCESS_QUERY_LIMITED_INFORMATION);
354 pub const READ_CONTROL: Self =
355 Self::new(windows::Win32::System::Threading::PROCESS_READ_CONTROL);
356 pub const SET_INFORMATION: Self =
357 Self::new(windows::Win32::System::Threading::PROCESS_SET_INFORMATION);
358 pub const SET_QUOTA: Self = Self::new(windows::Win32::System::Threading::PROCESS_SET_QUOTA);
359 pub const SUSPEND_RESUME: Self =
360 Self::new(windows::Win32::System::Threading::PROCESS_SUSPEND_RESUME);
361 pub const SYNCHRONIZE: Self = Self::new(windows::Win32::System::Threading::PROCESS_SYNCHRONIZE);
362 pub const TERMINATE: Self = Self::new(windows::Win32::System::Threading::PROCESS_TERMINATE);
363 pub const VM_OPERATION: Self =
364 Self::new(windows::Win32::System::Threading::PROCESS_VM_OPERATION);
365 pub const VM_READ: Self = Self::new(windows::Win32::System::Threading::PROCESS_VM_READ);
366 pub const VM_WRITE: Self = Self::new(windows::Win32::System::Threading::PROCESS_VM_WRITE);
367 pub const WRITE_DAC: Self = Self::new(windows::Win32::System::Threading::PROCESS_WRITE_DAC);
368 pub const WRITE_OWNER: Self = Self::new(windows::Win32::System::Threading::PROCESS_WRITE_OWNER);
369
370 const fn new(access: windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS) -> Self {
371 Self(access.0)
372 }
373}
374
375#[cfg(not(windows))]
377impl WinDaclProcessAccess {
378 pub const ALL_ACCESS: Self = Self(0);
379 pub const CREATE_PROCESS: Self = Self(0);
380 pub const CREATE_THREAD: Self = Self(0);
381 pub const DELETE: Self = Self(0);
382 pub const DUP_HANDLE: Self = Self(0);
383 pub const QUERY_INFORMATION: Self = Self(0);
384 pub const QUERY_LIMITED_INFORMATION: Self = Self(0);
385 pub const READ_CONTROL: Self = Self(0);
386 pub const SET_INFORMATION: Self = Self(0);
387 pub const SET_QUOTA: Self = Self(0);
388 pub const SUSPEND_RESUME: Self = Self(0);
389 pub const SYNCHRONIZE: Self = Self(0);
390 pub const TERMINATE: Self = Self(0);
391 pub const VM_OPERATION: Self = Self(0);
392 pub const VM_READ: Self = Self(0);
393 pub const VM_WRITE: Self = Self(0);
394 pub const WRITE_DAC: Self = Self(0);
395 pub const WRITE_OWNER: Self = Self(0);
396}
397
398impl Default for WinDacl {
399 fn default() -> Self {
400 Self::DEFAULT
401 }
402}
403
404impl WinDacl {
405 pub const DEFAULT: Self = Self::Default;
407
408 pub fn call(&self) -> Result {
413 #[cfg(windows)]
414 return match self {
415 Self::Empty => components::set_empty_dacl_winapi(),
416 Self::Default => components::set_default_dacl_winapi(),
417 Self::CustomUserPerm(access) => components::set_custom_dacl_winapi(access.into()),
418 Self::False => Ok(()),
419 Self::CustomFn(f) => f(),
420 };
421 #[cfg(not(windows))]
422 Ok(())
423 }
424}