#![allow(unsafe_code)]
pub fn harden_process() {
#[cfg(unix)]
harden_unix();
#[cfg(target_os = "linux")]
harden_linux();
#[cfg(windows)]
harden_windows();
}
#[cfg(unix)]
fn harden_unix() {
let zero = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
let rc = unsafe { libc::setrlimit(libc::RLIMIT_CORE, &zero) };
if rc != 0 {
tracing::warn!("harden_process: setrlimit(RLIMIT_CORE, 0) failed (rc={rc})");
}
}
#[cfg(target_os = "linux")]
fn harden_linux() {
let rc = unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0, 0, 0, 0) };
if rc != 0 {
tracing::warn!("harden_process: prctl(PR_SET_DUMPABLE, 0) failed (rc={rc})");
}
let rc = unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) };
if rc != 0 {
tracing::warn!("harden_process: prctl(PR_SET_NO_NEW_PRIVS, 1) failed (rc={rc})");
}
}
#[cfg(windows)]
fn harden_windows() {
#[cfg(any(feature = "signing", feature = "encryption"))]
{
crate::internal::core::process::harden_process();
}
#[cfg(not(any(feature = "signing", feature = "encryption")))]
{
extern "system" {
fn SetErrorMode(uMode: u32) -> u32;
}
unsafe { SetErrorMode(0x0001 | 0x0002) };
tracing::debug!(
"harden_process: partial Windows hardening applied \
(memory-only build; enable 'signing' or 'encryption' for full mitigation coverage)"
);
}
}
#[cfg(all(test, unix))]
#[allow(clippy::unwrap_used, unsafe_code)]
mod tests {
use super::*;
#[test]
fn harden_process_zeroes_core_dump_rlimit() {
harden_process();
let mut lim: libc::rlimit = unsafe { std::mem::zeroed() };
let rc = unsafe { libc::getrlimit(libc::RLIMIT_CORE, &mut lim) };
assert_eq!(rc, 0, "getrlimit failed");
assert_eq!(lim.rlim_cur, 0, "rlim_cur must be 0 after harden_process");
assert_eq!(lim.rlim_max, 0, "rlim_max must be 0 after harden_process");
}
}