secmem_proc/
macros.rs

1//! This module contains a macro [`define_harden_function`] which allows to
2//! create a custom hardening function according to given configuration options.
3//! Under the hood this just uses the configuration API in [`crate::config`].
4//!
5//! # Examples
6//! The following code defines a hardening function `harden` with `pub(crate)`
7//! visibility using the default configuration. Calling `harden` is equivalent
8//! to [`crate::harden_process`].
9//!
10//! ```
11//! use secmem_proc::macros::define_harden_function;
12//! define_harden_function! {
13//!     pub(crate) fn harden {}
14//! }
15//!
16//! // in main:
17//! harden().expect("error during process hardening");
18//! ```
19//!
20//! The next example disables anti-tracing techniques and anything that requires
21//! file-system access:
22//!
23//! ```
24//! use secmem_proc::macros::define_harden_function;
25//! define_harden_function! {
26//!     fn harden {
27//!         anti_tracing = false,
28//!         fs = false,
29//!     }
30//! }
31//!
32//! // in main:
33//! harden().expect("error during process hardening");
34//! ```
35//!
36//! # Configuration keys
37//! * `anti_tracing` (bool)
38//! * `fs` (bool)
39//! * `fs.procfs` (bool)
40//! * `unstable` (bool)
41//! * `unstable.win.ntapi` (bool)
42//! * `unstable.win.kernelmem` (bool)
43//! * `unstable.assert_feature_enabled` (`true`): compile time assert that the
44//!   `unstable` crate feature is enabled
45//! * `win.dacl`: possible values:
46//!   - `default`
47//!   - `empty`
48//!   - `custom_user_perm(<something of type WinDaclProcessAccess>)`
49//!   - `custom_fnptr(<fn ptr of type fn() -> crate::Result>)`
50
51/// Define a custom hardening function. See the module level documentation
52/// [`crate::macros`] for details.
53#[macro_export]
54macro_rules! define_harden_function {
55    ($visibility:vis fn $name:ident {$($($path:tt).+ = $rhs:tt,)*}) => {
56        $visibility fn $name() -> $crate::error::Result {
57            #[allow(unused_mut)]
58            let mut config = $crate::config::Config::DEFAULT;
59            $(
60                define_harden_function!(@@ config, $($path).+ = $rhs);
61            )*
62            config.harden_process()
63        }
64    };
65    (@@ $config:ident, anti_tracing = false) => {
66        $config.set_anti_tracing(false);
67    };
68    (@@ $config:ident, anti_tracing = true) => {
69        $config.set_anti_tracing(true);
70    };
71    (@@ $config:ident, fs = false) => {
72        $config.set_fs(false);
73    };
74    (@@ $config:ident, fs = true) => {
75        $config.set_fs(true);
76    };
77    (@@ $config:ident, fs.procfs = false) => {
78        $config.set_fs_procfs(false);
79    };
80    (@@ $config:ident, fs.procfs = true) => {
81        $config.set_fs_procfs(true);
82    };
83    (@@ $config:ident, unstable = false) => {
84        $config.set_unstable(false);
85    };
86    (@@ $config:ident, unstable = true) => {
87        $config.set_unstable(true);
88    };
89    (@@ $config:ident, unstable.win.ntapi = false) => {
90        $config.set_unstable_win_ntapi(false);
91    };
92    (@@ $config:ident, unstable.win.ntapi = true) => {
93        $config.set_unstable_win_ntapi(true);
94    };
95    (@@ $config:ident, unstable.win.kernelmem = false) => {
96        $config.set_unstable_win_kernelmem(false);
97    };
98    (@@ $config:ident, unstable.win.kernelmem = true) => {
99        $config.set_unstable_win_kernelmem(true);
100    };
101    (@@ $config:ident, unstable.assert_feature_enabled = true) => {
102        const _: () = core::assert!(
103            core::cfg!(feature = "unstable"),
104            "`secmem_proc` crate feature `unstable` is not enabled, \
105            while the configuration requires it"
106        );
107    };
108    (@@ $config:ident, win.dacl = default) => {
109        $config.set_win_dacl_default();
110    };
111    (@@ $config:ident, win.dacl = empty) => {
112        $config.set_win_dacl_empty();
113    };
114    (@@ $config:ident, win.dacl = custom_user_perm($access:expr)) => {
115        let access: $crate::config::WinDaclProcessAccess = $access;
116        $config.set_win_dacl_custom_user_perm(access);
117    };
118    (@@ $config:ident, win.dacl = custom_fnptr($fnptr:expr)) => {
119        let fnptr: fn() -> $crate::components::Result = $fnptr;
120        $config.set_win_dacl_custom_fn(fnptr);
121    };
122}
123
124pub use define_harden_function;
125
126#[cfg(test)]
127#[allow(dead_code)]
128mod tests {
129    use super::define_harden_function;
130
131    #[test]
132    fn macrotest_empty() {
133        define_harden_function! {
134            fn harden {}
135        }
136    }
137
138    #[test]
139    fn macrotest_visibility() {
140        define_harden_function! {
141            pub(crate) fn harden {}
142        }
143    }
144
145    #[test]
146    fn macrotest_anti_tracing() {
147        define_harden_function! {
148            fn harden {
149                anti_tracing = false,
150            }
151        }
152    }
153
154    #[test]
155    fn macrotest_multisetting() {
156        define_harden_function! {
157            fn harden {
158                anti_tracing = false,
159                fs = false,
160                unstable = false,
161            }
162        }
163    }
164
165    #[test]
166    fn macrotest_subsetting() {
167        define_harden_function! {
168            fn harden {
169                fs.procfs = false,
170            }
171        }
172    }
173
174    #[cfg(feature = "unstable")]
175    #[test]
176    fn macrotest_assert_unstable_feature() {
177        define_harden_function! {
178            fn harden {
179                unstable.assert_feature_enabled = true,
180            }
181        }
182    }
183}