std::fs::create_dir(path) calls mkdir(path, 0o777) and the actual mode
is 0o777 & ~umask. With an attacker-controlled umask (inherited across
setuid since the kernel does not reset it), the directory exists with
permissive bits between mkdir and the subsequent set_permissions call.
Fix uses DirBuilder::mode(...).create(...) so the mode is set in the
syscall itself, wrapped in UmaskGuard::zero() to neutralize umask
interference. Same pattern applied to skel.rs for subdirectory and
file copies (file copies switch from fs::copy to OpenOptions::mode +
io::copy for the same reason).
Regression test asserts a process running with umask 0 still produces
a 0o700 home directory.
Reported by @collinfunk in uutils/coreutils#11828.
Fixes#157.
#154: Reject setuid multicall invocations where argv[0] doesn't match
AT_EXECFN from the ELF auxiliary vector. Prevents an attacker from
spoofing argv[0] to route the multicall binary to a different tool
in setuid context. Only enforced when euid != uid.
#155: Add daily cargo-audit workflow matching uutils/coreutils pattern.
Also triggers on Cargo.toml/Cargo.lock changes.
Fixes#154. Fixes#155.
First release under the uutils organization.
Highlights:
- Repo transferred to uutils/shadow-rs
- uucore upgraded to 0.8
- nix crate fully replaced by rustix
- Default install now uses standalone per-tool binaries with
least-privilege setuid layout
- println!/eprintln! replaced with non-panicking writes
- Unwind tables suppressed in release builds
- NSS-backed user lookup via getpwuid_r
- 35+ security findings addressed across 6 review rounds
Fully remove nix as a direct dependency of the shadow-rs workspace.
New module shadow_core::process provides process-wide POSIX wrappers
via libc for setuid/setgid/initgroups/execv/sigprocmask. These MUST
use libc (not rustix) because rustix intentionally provides only
per-thread versions, which are incorrect for setuid-root tools.
Migrations:
- hardening.rs: setrlimit → rustix::process, sigprocmask → process
module, User::from_uid → /etc/passwd parser lookup
- pam.rs: nix::sys::termios → rustix::termios
- passwd.rs: full migration (seteuid, setuid, getuid, User lookup)
- newgrp.rs: full migration (termios, User lookup, setgid, initgroups,
execv)
- chpasswd/chage/chfn/chsh: setuid → shadow_core::process
- lock.rs tests: fcntl_getfd → rustix::io
libc stays for: PAM FFI, crypt(3) FFI, process-wide POSIX wrappers.
nix remains only as a transitive dep of uucore (upstream).