1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! Process-level hardening against the `/proc/<pid>/environ` side channel.
//!
//! `build_shell_env` (see `shell.rs`) sanitizes the environment array handed to each
//! spawned subprocess, but that only covers the array `Command` passes at `execve`
//! time. It does nothing about a bash child reading its own parent's raw kernel-recorded
//! environment via `/proc/$PPID/environ` — a channel entirely outside `Command`'s
//! control. Marking the runtime process non-dumpable closes that channel: the kernel's
//! `ptrace_may_access` check (which gates `/proc/pid/environ` reads) fails for a
//! non-dumpable target even when the reader shares the same UID.
//!
//! **Scope: this process, not its descendants.** The flag is inherited across `fork()`, but the
//! forked shell-tool child deliberately undoes it for itself
//! (`sandbox::linux_enforce::restore_child_dumpable`, inside `pre_exec`, before the seccomp filter
//! is installed). It has to: the same `ptrace_may_access` check that closes this side channel also
//! blocks the seccomp-notify supervisor thread — which lives in *this* process — from reading the
//! child's `/proc/<pid>/mem` to recover the pathname of a notified `execve`, so every allowlisted
//! `execve` was denied for a non-root user until the child re-enabled its own flag. The
//! asymmetry is the point: this process may hold raw, unfiltered secrets in its environment, while
//! the child's environment is already reduced to `shell::DEFAULT_ENV_BASELINE` plus explicit
//! overrides by `shell::build_shell_env` before it is spawned. The resulting exposure, and the
//! hand-run check for it, are in
//! `docs/content/reference/workdir-device-node-manual-verification.md`.
/// Marks the current process non-dumpable so no same-UID process — including its own
/// shell descendants — can read this process's `/proc/<pid>/environ`.
///
/// Must be called as the first statement of `main()` in every binary that links this
/// crate and can reach `execute_shell`, before any argument parsing or subprocess-capable
/// code runs. A future binary that links `capsule-runtime` and reaches `execute_shell`
/// inherits the same obligation.
///
/// Covers this process for its entire life and nothing else. The spawned shell-tool child
/// re-enables its own flag from `pre_exec` — see this module's header for why that is required
/// and what it trades away.
///
/// No-op on non-Linux targets: `/proc/<pid>/environ` and `prctl(2)` don't exist there,
/// so there is no side channel to close.