use crate::error::{Result, ResultExt as _, Traced};
use crate::internals;
use anyhow::Context;
#[cfg(windows)]
pub fn check_tracer_winapi() -> Result {
const TR: Traced = Traced::DEFAULT;
if internals::win32::is_debugger_present() {
return Result::create_being_traced(TR);
};
let res = unsafe {
internals::win32::is_remote_debugger_present(internals::win32::get_process_handle())
};
match res {
Ok(true) => {
return Result::create_being_traced(TR);
},
Ok(false) => {},
Err(e) => {
return Result::create_err(
e.context("Failed to check whether a tracer is present via WinAPI"),
);
},
}
Result::create_ok()
}
#[cfg(all(windows, feature = "unstable"))]
pub fn check_tracer_unstable() -> Result {
const TR: Traced = Traced::DEFAULT;
let res = unsafe { internals::win32::is_kernelflag_debugger_present() };
if res {
return Result::create_being_traced(TR);
}
Result::create_ok()
}
#[cfg(all(windows, feature = "unstable"))]
pub fn hide_thread_from_debugger_ntapi() -> Result {
unsafe { internals::win32::hide_thread_from_debugger(internals::win32::get_thread_handle()) }
.context("Failed hide the thread from potential tracers")?;
Result::create_ok()
}
#[cfg(windows)]
pub fn set_empty_dacl_winapi() -> Result {
const CTX: &str = "Failed to set a process DACL";
let acl_spec = crate::win_acl::EmptyAcl;
let acl = acl_spec.create().context(CTX)?;
acl.set_process_dacl_protected().context(CTX)?;
Result::create_ok()
}
#[cfg(windows)]
pub fn set_custom_dacl_winapi(
access_mask: windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS,
) -> Result {
use crate::win_acl::TokenUser;
const CTX: &str = "Failed to set a process DACL";
let user = TokenUser::process_user().context(CTX)?;
let sid = user.sid();
let acl_spec = crate::win_acl::EmptyAcl;
let acl_spec = crate::win_acl::AddAllowAceAcl::new(acl_spec, access_mask, sid);
let acl = acl_spec.create().context(CTX)?;
acl.set_process_dacl_protected().context(CTX)?;
Result::create_ok()
}
#[cfg(windows)]
pub fn set_default_dacl_winapi() -> Result {
use windows::Win32::System::Threading::{
PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_SYNCHRONIZE, PROCESS_TERMINATE,
};
let access_mask = PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE | PROCESS_SYNCHRONIZE;
set_custom_dacl_winapi(access_mask)
}
#[cfg(unix)]
pub fn disable_core_dumps_rlimit() -> Result {
use crate::error::private::ResultExt as _;
const RESOURCE: rustix::process::Resource = rustix::process::Resource::Core;
let rlim = rustix::process::Rlimit {
current: Some(0),
maximum: Some(0),
};
rustix::process::setrlimit(RESOURCE, rlim)
.map_anyhow()
.context("Failed to disable core-dumps via rlimit")?;
Result::create_ok()
}
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
pub fn disable_tracing_prctl() -> Result {
internals::prctl::set_process_nontraceable()
.context("Failed to disable ptrace-ability of the process")?;
Result::create_ok()
}
#[cfg(all(target_os = "linux", feature = "std"))]
pub fn check_tracer_procfs() -> Result {
if let Some(pid) = internals::std::is_tracer_present()
.context("Failed to check tracer presence via /proc/self/status")?
{
return Result::create_being_traced(Traced::from_pid(pid));
};
Result::create_ok()
}
#[cfg(target_os = "freebsd")]
pub fn check_tracer_prctl() -> Result {
if let Some(pid) = internals::prctl::is_tracer_present()
.context("Failed to check tracer presence via procctl")?
{
return Result::create_being_traced(Traced::from_pid(pid));
};
Result::create_ok()
}