mirror of
https://github.com/uutils/shadow.git
synced 2026-10-16 02:48:14 -07:00
The static musl archive aborted every setuid invocation with "argv[0] does not match executed binary". Deployed as `make install-multicall` deploys it, setuid root and reached through symlinks, no user could run passwd, chfn, chsh, newgrp, sg or gpasswd; root, for whom the check does not run, saw nothing wrong. Every static archive published so far, 0.2.2 through 0.4.0, has the defect. The glibc archives never did. The check compared the basename of argv[0] with AT_EXECFN obtained from rustix's `param` module. rustix reaches getauxval(3) by name at run time, through dlsym(3), so that it can tolerate a glibc older than 2.16. In a statically linked binary a symbol is present only if something links it in, and a lookup by name links nothing in: the archive carried no getauxval at all, rustix returned an empty string, and the tool's name never matched it. Instrumenting the abort showed argv0="passwd" against execfn=""; a probe that calls libc::getauxval directly made rustix's own lookup succeed too, the symbol being linked by then. verify_argv0_matches_execfn now calls libc::getauxval(AT_EXECFN) itself, which links the symbol and needs no lookup. glibc 2.34, the floor of the glibc archives, and musl both provide it. A null result still fails closed. Verified on the rebuilt archive in an Alpine container, installed 4755 root with symlinks, as an unprivileged user: passwd -S answers, a spoofed argv[0] (exec -a chsh passwd) is still refused, expiry -c is silent on a fresh account and refuses an expired one, expiry -f points at passwd(1), sg runs its command. The Static musl archive CI job now installs the archive setuid root, links passwd to it and runs passwd -S as nobody. Nothing exercised the static binary in setuid context before: the whole suite runs as root, where the check is skipped. Also silences, with the reason, the libc crate's musl deprecation warnings on the utmp calls: stubs are the documented behaviour of the static build.