Repository navigation
fix: preserve special file ownership from packages when cutting - #338
Open
chris-bainbridge wants to merge 1 commit into
Open
chris-bainbridge wants to merge 1 commit into
chris-bainbridge wants to merge 1 commit into
Conversation
Files extracted from packages were always created with the ownership of the running process (root:root in build environments), discarding the uid/gid recorded in the package tarball. This breaks any file relying on non-root ownership for its function: most notably the PAM chkpwd helpers (/usr/sbin/unix_chkpwd and /usr/sbin/pam_extrausers_chkpwd) ship setgid shadow so they can read the root:shadow, mode 0640 shadow files on behalf of an unprivileged PAM caller -- cut with chisel they end up setgid root, which grants no such access, so every password check performed by a non-root caller (e.g. screen lock/unlock in a confined desktop session) fails. The same flattening silently affects chage, expiry (shadow), crontab (crontab), plocate (plocate) and ssh-agent (_ssh). Extend fsutil.CreateOptions with optional Uid/Gid, applied with os.Chown to newly created entries (and pre-existing ones when OverrideMode is set, mirroring the mode semantics). Ownership is never applied to symlinks, and hard links inherit it from their target's inode. Unprivileged runs that cannot chown log a single warning and keep the previous behavior. tarball.Extract now carries the tar header uid/gid through for entries and their parent directories, but only requests ownership that differs from root:root: root-owned entries already end up root-owned when cutting as root, and cannot be chowned when cutting as a regular user, so the common case keeps its previous behavior exactly. Verified cutting the real libpam-modules-bin_auth slice from chisel-ubuntu-core (26.04): the chkpwd helpers now come out root:shadow 2755, matching a plain dpkg -x of the same package.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Files extracted by
chisel cutare always created with the ownership of the running process (root:rootin build environments), discarding the uid/gid recorded in the package tarball. This silently breaks any file that relies on non-root ownership for its function.Most notable victim: the PAM chkpwd helpers
/usr/sbin/unix_chkpwdand/usr/sbin/pam_extrausers_chkpwd. These ship setgid shadow (mode 2755) so they can read theroot:shadow, mode 0640 shadow files on behalf of an unprivileged PAM caller (the standard Debian/Ubuntu privilege-separation design). Cut with chisel they end up setgid root, which grants no such access, so every password check performed by a non-root caller fails — e.g. screen lock/unlock in a confined desktop session on Ubuntu Core, where the session snap's PAM stack execs the helpers from the base snap. The same flattening affectschageandexpiry(shadow),crontab(crontab),plocate(plocate) andssh-agent(_ssh).The mode (including the setgid bit) is already preserved; only the uid/gid are dropped, in
internal/tarball/extract.go, which buildsfsutil.CreateOptionsfrom the tar header without carrying the header'sUid/Gidover —internal/fsutilhas no way to express them at all.Fix
internal/fsutil:CreateOptionsgains optionalUid/Gid, applied withos.Chownto newly created entries, and to pre-existing ones whenOverrideModeis set (mirroring the existing mode semantics). Ownership is never applied to symlinks; hard links inherit it from their target's inode. Unprivileged runs that cannot chown log a single warning and keep the previous behavior.internal/tarball: the tar header's uid/gid is carried through for entries and their parent directories — but only requested when it differs from root:root. Root-owned entries already end up root-owned when cutting as root, and cannot be chowned when cutting as a regular user, so the overwhelmingly common case keeps its previous behavior exactly (no extra syscalls, no behavior change for chiseled container images).Slice definitions are unchanged; the ownership comes from the packages themselves, so cuts stay deterministic.
Verification
internal/fsutil(ownership applied/withheld per the mode semantics, symlink and hard link handling,CreateWriter, unprivileged EPERM warning) andinternal/tarball(a setgid, gid-42 entry modelingunix_chkpwd; asserting preservation as root and the warning fallback as a regular user). Full suite passes both as root and as a regular user (17/17 packages).libpam-modules-bin_authslice from chisel-ubuntu-core (26.04) as root now producesdpkg -xof the same package (previouslyroot:root).