Skip to content

chage: let a user read their own aging line - #310

Merged
pierre-warnier merged 1 commit into
mainfrom
fix/chage-reads-shadow
Sep 15, 2026
Merged

pierre-warnier merged 1 commit into
mainfrom
fix/chage-reads-shadow

Conversation

@pierre-warnier

Copy link
Copy Markdown
Collaborator

chage -l is the one mode a user may run, on their own account, and it did not work for them: make install put chage at 0755, which cannot read /etc/shadow, and the multicall binary dropped its privilege before running it. The Makefile's own comment said chage sat in bin "for chage -l, the one mode a user may run on their own account".

Contract, probed on the packaged binaries. Debian ships chage 2755 root:shadow, the same as expiry. Fedora and Arch have no shadow group and ship it 4755 root.

Change. chage follows expiry: setgid shadow, or setuid root where the group is absent (#309's mechanism), and an applet that keeps euid 0 in the multicall binary. chage decides what the caller may do from the real uid (caller_is_root is getuid), and --root is refused before the chroot on the same basis, so the privilege buys a user their own line and nothing else.

Verified. Per-tool binaries installed in the debian image under both layouts (2755 root:shadow, and 4755 root with SHADOW_GROUP set to a group that does not exist); as an unprivileged user under each: chage -l on the own account answers, chage -l root, chage -M 5 <self> and chage --root / -l <self> are refused, and the shadow field is unchanged afterwards. The deployment suite gains those four assertions for the multicall layout; make check in the container.

Docs: README tool table and install notes, the chage man page, changelog under Fixed.

`chage -l` is the one mode a user may run, on their own account, and it
did not work for them: `make install` put chage at 0755, which cannot
read /etc/shadow, and the multicall binary dropped its privilege before
running it. The Makefile's own comment placed chage in bin "for chage
-l, the one mode a user may run on their own account".

The packaged binaries settle the contract: Debian ships chage 2755
root:shadow, the same as expiry; Fedora and Arch have no shadow group
and ship it 4755 root. chage now follows expiry -- setgid shadow, or
setuid root where the group is absent, and an applet that keeps euid 0
in the multicall binary. chage decides what the caller may do from the
real uid, and --root is refused before the chroot on the same basis, so
the privilege buys a user their own line and nothing else.

Verified with the per-tool binaries installed in the debian image under
both layouts; as an unprivileged user under each, chage -l on the own
account answers, chage -l root, chage -M 5 and chage --root are refused,
and the shadow field is unchanged afterwards. The deployment suite
gains those four assertions for the multicall layout.
@pierre-warnier
pierre-warnier merged commit ab6b3df into main Sep 15, 2026
13 checks passed
@pierre-warnier
pierre-warnier deleted the fix/chage-reads-shadow branch September 15, 2026 09:12
@pierre-warnier pierre-warnier mentioned this pull request Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant