2026-03-24 15:59:04 +01:00
|
|
|
# Changelog
|
|
|
|
|
|
|
|
|
|
All notable changes to this project will be documented in this file.
|
|
|
|
|
|
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
|
|
2026-04-03 15:16:41 +02:00
|
|
|
## [Unreleased]
|
|
|
|
|
|
2026-04-22 19:21:02 +02:00
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- `audit.yml` workflow for daily `cargo-audit` security advisory checks (#155)
|
|
|
|
|
- AT_EXECFN validation in multicall binary: rejects spoofed `argv[0]` in
|
|
|
|
|
setuid context by comparing against the kernel-recorded executable path (#154)
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
|
|
|
|
- AT_EXECFN check uses `rustix::param::linux_execfn()` instead of unsafe
|
|
|
|
|
`libc::getauxval` — zero new unsafe for this feature
|
|
|
|
|
- All workspace crate versions aligned to 0.2.0
|
|
|
|
|
|
2026-04-22 16:53:01 +02:00
|
|
|
## [0.2.0] - 2026-04-22
|
|
|
|
|
|
2026-04-03 15:16:41 +02:00
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- `usermod -p/--password` flag for setting pre-hashed passwords (#114)
|
|
|
|
|
- End-to-end deployment tests in Docker: 117 assertions covering symlink
|
|
|
|
|
dispatch, setuid, PAM, Landlock, nscd, and Ansible interop (#102, #115)
|
|
|
|
|
- Docker multi-distro CI in GitHub Actions (debian, alpine, fedora)
|
|
|
|
|
- Shell completion generation for bash, zsh, fish (#106)
|
|
|
|
|
- Renovate for automated dependency updates
|
|
|
|
|
- `rust-toolchain.toml` for contributor convenience
|
|
|
|
|
- `feat_common_core` feature alias (all 14 tools)
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
|
|
|
|
- Cargo.toml metadata aligned with uutils ecosystem conventions
|
|
|
|
|
- Tool crate descriptions normalized to `"tool ~ (shadow-rs) verb phrase"` format
|
|
|
|
|
- Edition 2024 consistently applied across root and workspace packages
|
2026-04-15 14:19:21 +02:00
|
|
|
- `make install` now defaults to 14 standalone per-tool binaries with
|
|
|
|
|
least-privilege setuid layout matching GNU shadow-utils (#138). Only
|
|
|
|
|
`passwd`/`chfn`/`chsh`/`newgrp` are setuid-root; the other 10 are `0755`.
|
|
|
|
|
The previous multicall install is available as `make install-multicall`.
|
2026-04-22 16:36:09 +02:00
|
|
|
- `nix` crate fully replaced by `rustix` (raw syscalls, no libc overhead).
|
|
|
|
|
`libc` kept only for PAM FFI, crypt(3) FFI, and process-wide POSIX
|
|
|
|
|
wrappers (setuid/sigprocmask/getpwuid_r) (#140)
|
|
|
|
|
- `uucore` upgraded from 0.7 to 0.8 (#150)
|
|
|
|
|
- Repo transferred from `shadow-utils-rs/shadow-rs` to `uutils/shadow-rs`
|
2026-04-03 15:16:41 +02:00
|
|
|
|
2026-04-22 10:27:46 +02:00
|
|
|
### Security
|
|
|
|
|
|
|
|
|
|
- PAM password buffers zeroed immediately after use (`zeroize`)
|
|
|
|
|
- `initgroups()` called in newgrp before exec (prevents supplementary group leak)
|
|
|
|
|
- `SignalBlocker` scoped to file-mutation critical sections only; dropped before
|
|
|
|
|
long-running operations (home deletion, recursive chown, skel copy)
|
|
|
|
|
- `UmaskGuard` marked `!Send`/`!Sync` via `PhantomData<Rc<()>>` (thread-safety)
|
|
|
|
|
- `newgrp` uses targeted hardening (`suppress_core_dumps` + `sanitized_env`)
|
|
|
|
|
instead of `harden_process()` to avoid leaking `RLIMIT_FSIZE` to exec'd shell
|
|
|
|
|
- `atomic_write` retries once on stale temp file from prior crash
|
|
|
|
|
- `crypt(3)` wrapper documented as non-thread-safe (uses global state)
|
|
|
|
|
- Centralized hardening utilities in `shadow_core::hardening` (deduplicated
|
|
|
|
|
from per-tool copies)
|
|
|
|
|
- `println!`/`eprintln!` replaced with non-panicking writes (#141)
|
2026-04-22 11:41:17 +02:00
|
|
|
- Unwind tables suppressed via `-C force-unwind-tables=no` (#143)
|
2026-04-22 10:27:46 +02:00
|
|
|
|
2026-04-03 15:16:41 +02:00
|
|
|
### Fixed
|
|
|
|
|
|
|
|
|
|
- Password hash validation rejects `:`, `\n`, `\r` (field injection prevention)
|
|
|
|
|
- Error on missing shadow entry in usermod (was silent no-op)
|
|
|
|
|
- `days_since_epoch()` centralized in shadow-core (was duplicated)
|
|
|
|
|
|
2026-03-24 15:59:04 +01:00
|
|
|
## [0.1.0] - 2026-03-24
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- All 14 shadow-utils tools implemented as drop-in replacements:
|
|
|
|
|
`passwd`, `useradd`, `userdel`, `usermod`, `groupadd`, `groupdel`,
|
|
|
|
|
`groupmod`, `pwck`, `grpck`, `chage`, `chpasswd`, `chfn`, `chsh`, `newgrp`
|
|
|
|
|
- Single multicall binary with symlink dispatch (894 KB stripped)
|
|
|
|
|
- PAM integration for password authentication and changes
|
|
|
|
|
- Atomic file writes with lock-via-hard-link pattern (TOCTOU resistant)
|
|
|
|
|
- Stale lock detection via ESRCH-only PID checking
|
|
|
|
|
- Password zeroing via `zeroize` crate
|
|
|
|
|
- Core dump suppression and file size limit hardening
|
|
|
|
|
- Environment sanitization (safe for setuid-root context)
|
|
|
|
|
- Signal blocking during critical file operations
|
|
|
|
|
- SELinux file context support (best-effort via external tools)
|
|
|
|
|
- Audit logging to syslog and auditd
|
|
|
|
|
- subuid/subgid allocation for rootless containers (useradd)
|
|
|
|
|
- Recursive chown on UID change (usermod)
|
|
|
|
|
- Proper date validation with leap year and month-length rules
|
|
|
|
|
- GNU-compatible output and exit codes for all tools
|
2026-04-22 10:27:46 +02:00
|
|
|
- 580+ unit tests, property-based tests (proptest), 6 fuzz targets
|
2026-03-24 15:59:04 +01:00
|
|
|
- Integration tests for 14 tools
|
|
|
|
|
- Docker test matrix: Debian (glibc), Alpine (musl), Fedora (SELinux)
|
|
|
|
|
- CI gates: fmt, clippy, test, MSRV (1.94.0), cargo-deny
|
|
|
|
|
- Debian and RPM packaging
|
|
|
|
|
- Man pages for all 14 tools
|
|
|
|
|
- GNU compatibility test suite and PAM end-to-end test
|
|
|
|
|
|
|
|
|
|
### Security
|
|
|
|
|
|
|
|
|
|
- `unsafe_code = "deny"` enforced at workspace level (only PAM/crypt FFI exempted)
|
|
|
|
|
- `dead_code = "deny"` enforced at workspace level
|
|
|
|
|
- O_EXCL temp files (symlink attack prevention)
|
|
|
|
|
- Umask guard (RAII) for restrictive file permissions
|
|
|
|
|
- GPL clean-room development (MIT license, no GPL source referenced)
|
|
|
|
|
- Reviewed by GitHub Copilot (automated) and Google Gemini CLI (manual)
|
|
|
|
|
- 20+ security findings addressed across 4 review rounds
|