Context
Raised by @oech3 in uutils/coreutils#11828: the current make install installs a single multicall shadow-rs binary with symlinks, then chmod 4755 the passwd/chfn/chsh/newgrp symlinks. Because chmod on a symlink follows through to the ELF target, the binary ends up setuid root, so useradd/usermod/userdel/etc. also run with euid=0 when invoked via their symlinks. Each tool has an internal getuid() == 0 check as defense-in-depth, but that's not OS-level least privilege.
Proposal
Switch the default make install to build and install 14 standalone per-tool binaries (each tool crate already has its own [[bin]]), with:
chmod 4755 on passwd, chfn, chsh, newgrp (the four tools that traditionally need setuid for non-root callers)
chmod 0755 on useradd, userdel, usermod, groupadd, groupdel, groupmod, chage, chpasswd, pwck, grpck (root-only tools)
This matches GNU shadow-utils' install layout exactly and gives OS-level least privilege.
Keep the multicall binary available as an opt-in target for container/embedded use cases where the ~14× disk savings matter and the enlarged setuid footprint isn't a concern:
make install # default: 14 standalone binaries, proper setuid layout
make install-multicall # opt-in: single multicall binary + symlinks
Update README.md's "Building" section to reflect the new default.
Context
Raised by @oech3 in uutils/coreutils#11828: the current
make installinstalls a single multicallshadow-rsbinary with symlinks, thenchmod 4755thepasswd/chfn/chsh/newgrpsymlinks. Becausechmodon a symlink follows through to the ELF target, the binary ends up setuid root, souseradd/usermod/userdel/etc. also run witheuid=0when invoked via their symlinks. Each tool has an internalgetuid() == 0check as defense-in-depth, but that's not OS-level least privilege.Proposal
Switch the default
make installto build and install 14 standalone per-tool binaries (each tool crate already has its own[[bin]]), with:chmod 4755onpasswd,chfn,chsh,newgrp(the four tools that traditionally need setuid for non-root callers)chmod 0755onuseradd,userdel,usermod,groupadd,groupdel,groupmod,chage,chpasswd,pwck,grpck(root-only tools)This matches GNU shadow-utils' install layout exactly and gives OS-level least privilege.
Keep the multicall binary available as an opt-in target for container/embedded use cases where the ~14× disk savings matter and the enlarged setuid footprint isn't a concern:
Update
README.md's "Building" section to reflect the new default.