Skip to main content

arti/
process.rs

1//! Code to adjust process-related parameters.
2
3use tracing::error;
4
5use crate::ArtiConfig;
6
7/// Set our current maximum-file limit to a large value, if we can.
8///
9/// Since we're going to be used as a proxy, we're likely to need a
10/// _lot_ of simultaneous sockets.
11///
12/// # Limitations
13///
14/// This doesn't actually do anything on windows.
15#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
16#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
17pub(crate) fn use_max_file_limit(config: &ArtiConfig) {
18    match rlimit::increase_nofile_limit(config.system.max_files) {
19        Ok(n) => tracing::debug!("Increased process file limit to {}", n),
20        Err(e) => tor_error::warn_report!(e, "Error while increasing file limit"),
21    }
22}
23
24/// Enable process hardening, to make it harder for low-privilege users to
25/// extract information from Arti.
26///
27/// This function only has effect the first time it is called.  If it returns an
28/// error, the caller should probably exit the process.
29///
30/// # Limitations
31///
32/// See notes from the [`secmem_proc`] crate: this is a best-effort defense, and
33/// only makes these attacks _harder_.  It can interfere with debugging.
34#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
35#[cfg(feature = "harden")]
36pub(crate) fn enable_process_hardening() -> anyhow::Result<()> {
37    use anyhow::Context as _;
38    use std::sync::atomic::{AtomicBool, Ordering};
39    /// Have we called this method before?
40    static ENABLED: AtomicBool = AtomicBool::new(false);
41
42    if ENABLED.swap(true, Ordering::SeqCst) {
43        // Already enabled, or tried to enable.
44        return Ok(());
45    }
46
47    secmem_proc::harden_process().context("Problem while hardening process")?;
48
49    Ok(())
50}
51
52/// Check that we are not running as "root".
53///
54/// If we are, give an error message, and exit.
55pub(crate) fn exit_if_root() {
56    if running_as_root() {
57        error!(
58            "You are running Arti as root. You don't need to, and \
59             you probably shouldn't. \
60             To run as root anyway, set application.allow_running_as_root."
61        );
62        std::process::exit(1);
63    }
64}
65
66/// Return true if we seem to be running as root.
67fn running_as_root() -> bool {
68    #[cfg(target_family = "unix")]
69    unsafe {
70        libc::geteuid() == 0
71    }
72    #[cfg(not(target_family = "unix"))]
73    false
74}
75
76/// Return an async stream that reports an event whenever we get a `SIGHUP`
77/// signal.
78///
79/// Note that the signal-handling backend can coalesce signals; this is normal.
80#[cfg(target_family = "unix")]
81pub(crate) fn sighup_stream() -> crate::Result<impl futures::Stream<Item = ()>> {
82    cfg_if::cfg_if! {
83        if #[cfg(feature="tokio")] {
84            use tokio_crate::signal::unix as s;
85            let mut signal = s::signal(s::SignalKind::hangup())?;
86            Ok(futures::stream::poll_fn(move |ctx| signal.poll_recv(ctx)))
87        } else if #[cfg(feature="async-std")] {
88            use async_signal::{Signal, Signals};
89            use futures::stream::StreamExt as _;
90            let signals = Signals::new(&[Signal::Hup])?;
91            Ok(signals.map(|_| ()))
92        } else {
93            // Not backend, so we won't ever get a SIGHUP.
94            Ok(futures::stream::pending())
95        }
96    }
97}