ostree_ext/
isolation.rs

1use std::process::Command;
2
3use once_cell::sync::Lazy;
4
5pub(crate) const DEFAULT_UNPRIVILEGED_USER: &str = "nobody";
6
7/// Checks if the current process is (apparently at least)
8/// running under systemd.  We use this in various places
9/// to e.g. log to the journal instead of printing to stdout.
10pub(crate) fn running_in_systemd() -> bool {
11    static RUNNING_IN_SYSTEMD: Lazy<bool> = Lazy::new(|| {
12        // See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#%24INVOCATION_ID
13        std::env::var_os("INVOCATION_ID")
14            .filter(|s| !s.is_empty())
15            .is_some()
16    });
17
18    *RUNNING_IN_SYSTEMD
19}
20
21/// Return a prepared subprocess configuration that will run as an unprivileged user if possible.
22///
23/// This currently only drops privileges when run under systemd with DynamicUser.
24pub(crate) fn unprivileged_subprocess(binary: &str, user: &str) -> Command {
25    // TODO: if we detect we're running in a container as uid 0, perhaps at least switch to the
26    // "bin" user if we can?
27    if !running_in_systemd() {
28        return Command::new(binary);
29    }
30    let mut cmd = Command::new("setpriv");
31    // Clear some strategic environment variables that may cause the containers/image stack
32    // to look in the wrong places for things.
33    cmd.env_remove("HOME");
34    cmd.env_remove("XDG_DATA_DIR");
35    cmd.env_remove("USER");
36    cmd.args([
37        "--no-new-privs",
38        "--init-groups",
39        "--reuid",
40        user,
41        "--bounding-set",
42        "-all",
43        "--pdeathsig",
44        "TERM",
45        "--",
46        binary,
47    ]);
48    cmd
49}