# Procfs and Process Identity
`proc` parses `/proc` for process identity and stats; `process` exposes raw
process syscalls. Both are stateless primitives — Core never decides which pid
or path to inspect, callers pass them explicitly.
## `proc` module
### Status and command line
- `read_proc_status(pid)` / `read_proc_status_at(proc_root, pid)` → `ProcStatus`
(`{ name: String, uid: u32 }` parsed from `/proc/<pid>/status`; the `Uid:` line
contributes the **real** uid, the first whitespace field — not effective/saved).
- `parse_proc_status(content)` — pure parse of a status blob (testable); fails
with `EINVAL` if `Name:` or `Uid:` is missing.
- `read_proc_cmdline(pid)` / `read_proc_cmdline_at(proc_root, pid)` → the
process's command line string (lossy UTF-8; interior NULs become spaces,
trailing NULs trimmed).
- `ProcDir::open(pid)` / `open_at(proc_root, pid)` — an owned dirfd for
race-free multi-probe access (`uid()`, `stat()`, `status()`, `cmdline()`).
### Stats and ownership
- `stat(pid)` / `stat_at()` / `path_stat(path)` / `path_lstat(path)` → `Stat`
(`{ uid, inode, ctime_sec, ctime_nsec, mtime_sec, mtime_nsec }` — no mode/gid/dev
fields; callers needing those must syscall directly). `stat`/`path_stat` follow
symlinks, `path_lstat` does not.
- `uid(pid)` / `uid_at()` / `path_uid(path)` — the **owner** (`st_uid`) of the
path. For `/proc/<pid>` that is the procfs directory owner (the process's real
uid), **not** its effective uid. To get an effective uid, use
`effective_uid()` — which returns the *calling* process's effective uid.
- `chown(path, uid, gid)` — ownership change; `gid: None` leaves the group
unchanged.
- `clock_ticks_per_second()` — `sysconf(_SC_CLK_TCK)`, needed to scale `stat`
time fields.
All read paths are open/read-looping primitives that return `CoreError` on
failure; nothing is silently skipped.
## `process` module
Raw syscall wrappers for the current process / child setup:
- `fork()` (unsafe) → `ForkResult` (parent vs child).
- `setsid()`, `setpgid(pid, pgid)` — session / process-group membership.
- `setuid(uid)`, `setgid(gid)` — implemented via `setresuid`/`setresgid` (real +
effective + saved IDs set atomically — "drop privileges" semantics), plus
`getuid()`, `getgid()`.
- `set_pdeathsig(sig)` — `PR_SET_PDEATHSIG`. Precision: the signal is sent
when the **parent thread that created this task** exits (`forget_original_parent`
runs on every thread's `do_exit`), not when the parent *process* dies — in a
thread-pool caller a worker-thread exit kills its children while the process
lives. Retained across exec except under `bprm->secureexec`. Leader-only in
`SpawnOptions::pdeath_signal`: it reaches the spawned leader's whole process
(PIDTYPE_TGID), not session members in other process groups. The wiring in
`child_entry` arms the prctl **first**, then verifies `getppid()` still
equals the expected parent and `_exit(127)`s if it does not — closing the
fork→prctl race where the parent dies before the call and the signal would
otherwise be silently bound to init.
- `close_fds_from(start)` — close every fd `>= start`. This is a **standalone
primitive**; the spawn backends' fd-policy enforcement actually runs
`fork.rs::close_child_fds_for_policy` (a getdents64 scan of `/proc/self/fd`,
fail-closed), not this function. Owns a `/proc/self/fd` dirfd while
enumerating (avoids the double-close hazard); if `opendir` fails it falls
back to a blind `start..1024` close — call with `start >= 3`.
- `redirect_stdio_to_devnull()` (`unsafe`) — open `/dev/null` and `dup2` it
onto fd 0/1/2 (daemon hygiene).
- `redirect_fd_to(src, dst)` (`unsafe`, no `Result`) — `dup2(src, dst)`; closes
`src` only when `src != dst` (so `redirect_fd_to(5, 5)` is a no-op, not a
close). Errors are silently ignored.
## Safety
The nofollow/dirfd variants exist specifically to close TOCTOU windows:
`open_at(proc_root, pid)` holds the proc dirfd so the pid cannot be recycled to
a different process between probes.