hematite/tools/
hardening.rs1#[cfg(unix)]
2use std::ffi::OsString;
3#[cfg(unix)]
4use std::os::unix::ffi::OsStrExt;
5
6pub fn pre_main_hardening() {
11 #[cfg(any(target_os = "linux", target_os = "macos"))]
12 pre_main_hardening_unix();
13
14 #[cfg(windows)]
15 pre_main_hardening_windows();
16}
17
18#[cfg(any(target_os = "linux", target_os = "macos"))]
19fn pre_main_hardening_unix() {
20 let rlim = libc::rlimit {
22 rlim_cur: 0,
23 rlim_max: 0,
24 };
25 unsafe {
26 libc::setrlimit(libc::RLIMIT_CORE, &rlim);
27 }
28
29 #[cfg(target_os = "macos")]
31 unsafe {
32 libc::ptrace(31, 0, std::ptr::null_mut(), 0);
34 }
35 #[cfg(target_os = "linux")]
36 unsafe {
37 libc::prctl(4, 0, 0, 0, 0);
39 }
40
41 remove_env_vars_with_prefix("LD_");
43 remove_env_vars_with_prefix("DYLD_");
44 remove_env_vars_with_prefix("MallocStackLogging");
45}
46
47#[cfg(windows)]
48fn pre_main_hardening_windows() {
49 let risky_prefixes = ["LD_", "DYLD_"];
52 for prefix in risky_prefixes {
53 for (key, _) in std::env::vars() {
54 if key.starts_with(prefix) {
55 std::env::remove_var(key);
56 }
57 }
58 }
59}
60
61#[cfg(unix)]
62fn remove_env_vars_with_prefix(prefix: &str) {
63 let prefix_bytes = prefix.as_bytes();
64 let keys_to_remove: Vec<OsString> = std::env::vars_os()
65 .filter_map(|(key, _)| {
66 if key.as_os_str().as_bytes().starts_with(prefix_bytes) {
67 Some(key)
68 } else {
69 None
70 }
71 })
72 .collect();
73
74 for key in keys_to_remove {
75 std::env::remove_var(key);
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_env_sanitization_prefixes() {
85 std::env::set_var("LD_TEST_LOG", "1");
86 std::env::set_var("DYLD_LIBRARY_PATH", "/tmp");
87 std::env::set_var("SAFE_VAR", "preserved");
88
89 pre_main_hardening();
91
92 assert!(std::env::var("LD_TEST_LOG").is_err());
93 assert!(std::env::var("DYLD_LIBRARY_PATH").is_err());
94 assert_eq!(std::env::var("SAFE_VAR").unwrap(), "preserved");
95 }
96}