Repository navigation
package: the binary drop is the third packing site, and it inherits its inputs' modes - #1435
Conversation
…ts inputs' modes Follow-up to #1352 (closed by #1361), found by enumerating the packing sites instead of reasoning about the two already fixed: three scripts source scripts/pack-elf.sh and write an archive, and only two of them applied the mode rule. make-binary-drop.sh sources pack-elf.sh, writes a PUBLISHED tarball (docs/releases.md, "The public binary drop") -- neither helper called package-linux.sh fixed in #1361 weekly.sh the lemonade payload fold, fixed in #1360 pack-distro.sh normalises per payload pass; its own comment explains why it does not assert (it stages on the formatter's own copy, so the chmod cannot fail) Measured, on a real tree rather than argued: /home/bcloud/wt/rlk-build/hrx/llama/bin is 13 of 13 files at 0775 (-rwxrwxr-x), which is exactly what the drop stages with `cp -a` when built with --build; with --from-package it inherits whatever an already-published tarball had, including one packed before #1361/#1360 (c31's payload measured 111x0664 + 23x0775). So the drop now runs pack_normalise_modes and asserts with pack_writable_files before writing its archive, and docs/releases.md says so in the drop's own section. tests/pack_modes_test.sh grows the check whose absence let this reopen: it ENUMERATES the packing sites from the tree (sources pack-elf.sh + writes an archive) instead of listing them, requires a real invocation of pack_normalise_modes at every one, and requires pack_writable_files at the sites that pack a flat payload -- with pack-distro.sh the single documented exemption, recorded in the test so a second site that wants it has to edit the list. Three negative controls, run and restored: normalise removed from the drop -> rc 1 naming it; only the assert removed -> rc 1 naming it; the exempt site losing its normalise calls -> rc 1. The first version of this check MATCHED A COMMENTED-OUT call and passed with the guard disabled -- caught by the negative control, which is why the pattern now anchors at the start of a line. tools/copyright.py --check rc 0. 0 s GPU, 0 s NPU.
|
#1435 ready for review at 4bb2df2 Residue of #1352, found by enumerating the packing sites: Fix is the same pair #1361 introduced, applied before the archive, plus docs in the drop's own section. The regression guard enumerates the packing sites from the tree (sources Three negative controls run and restored (rc 1 each; the first version of the check matched a commented-out call and passed with the guard disabled — the control caught it).
|
|
/review |
|
Preparing review... |
PR Reviewer Guide 🔍(Review updated until commit ea0d708)Here are some key observations to aid the review process:
✅ Resolved findingstests/pack_modes_test.sh:94-131Enumeration of packing sites The test now enumerates packing sites from the tree instead of listing them, which helps prevent future regressions by ensuring that all scripts that stage files with |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 4bb2df21bfbab888d6d2903951a11c630e6f4860
Finding the third site by enumerating packing sites, rather than reasoning from the two already fixed, is the right method, and the fix is the same two calls the other sites use:
pack_normalise_modes "$stage", thenpack_writable_filesasserted, both before thetar -C "$work" -cf - "$name" | zstd …atmake-binary-drop.sh:228;docs/releases.mdsays so in the drop's own section.
What I ran at this head (base 880c9ae, on main):
bash tests/pack_modes_test.sh .:pack_modes: ok. It enumerates four sites:make-binary-drop.sh,package-linux.shandweekly.sh"normalises and asserts", andpack-distro.sh"normalises (…see its own comment)";bash -npasses on both files;shellcheck -S warningon the two files reports 1, the same 1 as on main;tools/copyright.py --check: rc 0.
The ^[[:space:]]* anchor, which stops a commented-out call from counting, is exactly the "check that cannot fail" trap, and your negative control found it. Good.
Two small robustness notes on the enumeration, not blocking:
- The predicate is "contains
tar -C", not "writes an archive". Inweekly.shboth matches are extracts (:332,:486-xf), andmake-binary-drop.sh:95is an extract too. Over-inclusion is the safe direction. Under-inclusion is the risk: a site that writestar --zstd -cf "$out" -C "$dir" …(flags before-C) won't match. - The floor is
>= 3while 4 sites are known today. So exactly the case above (one of the four dropping out of the enumeration) passes silently.>= 4keeps your "a fifth site with the guard is fine" property and catches one disappearing. A predicate likegrep -qE '\btar\b.*-c'(or a-cf/--creatematch) would select writers rather than extractors.
Attempted the end-to-end run of this site tonight — could not complete it, and the reason is worth recordingThe fixture test proves the functions; it does not prove this call site executes correctly inside the real drop. So I tried to produce a real
So: not verified end-to-end here. What would settle it is a drop built from a real release build — the script's own usage says I am recording this rather than leaving the fixture test to imply more coverage than it has. What is covered:
The residual risk if the call site were wrong is small and bounded: it sits immediately before Commands, for whoever has a release build to hand: |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at ea0d70852bae382d36966e65a807691cfad0bd96
This head adds only a merge of main on top of 4bb2df21, which I reviewed READY. The verdict carries forward on these checks:
- First parent is
4bb2df21, the reviewed head. - Own diff is unchanged: patch-id
10c387c4, the same before and after the merge. - Main didn't touch the PR's files. The only main commit brought in is #1439 (
tools/hyperloom/custom/*), which touches none ofscripts/make-binary-drop.sh,tests/pack_modes_test.shordocs/releases.md. - Its test passes at this head:
bash tests/pack_modes_test.sh .→pack_modes: ok.
My two notes from the earlier review (the tar -C predicate and the >= 3 floor) still stand as suggestions.
|
Persistent review updated to latest commit ea0d708 |
End-to-end verification — now measured, both arms, on real drop artifactsEarlier on this PR I recorded that this fix's call site was only covered at unit level, because every attempt to drive Source with unnormalised modes (so the comparison means something): the c31 payload's
Three things this settles that the unit test could not:
Also run for completeness: a drop from the post-#1361 package ( Method note: both arms were run in the same tree, sequentially, with the block disabled as a unit — disabling only the assignment leaves Harness: |
…row keeps them off (Fixes #1474) (#1544) * os: the BASE layer's group/other-writable modes are taken off, and a row keeps them off (Fixes #1474) The payload class (#1352/#1361/#1360/#1435/#1459/#1461/#1463) is closed for opt/1bit-package; this is the same class one layer down, which none of those rows looked at. Measured on the base SFS this pass: **2,176** group/other-writable paths outside the payload (1,814 files + 362 dirs), **2,166 of them outside a keep-list** - 352 directories, 542 executables, 1,272 other files, all inherited from woof-CE's build with the builder's umask. * `pack_normalise_base_modes` / `pack_writable_base_files` in scripts/pack-elf.sh, beside the payload pair. The normaliser applies **go-w ONLY**. The payload's rule (dirs 0755, executables 0755, other files 0644) is right for a package and wrong for an operating system: it GRANTS bits, and it would have made /etc/shadow and /etc/gshadow world-readable and every 0600 private key readable. The base layer has all of the secrets the payload does not. * `os/v3/puppy/base-modes-keep`: the eight classes that DO need to stay writable (tmp, var/tmp, var/run, var/lock, var/spool, var/log, run, dev, proc, sys) plus opt/1bit-package (the payload has its own normaliser and its own row). A prefix covers the path itself, so /tmp keeps 1777 rather than losing its sticky bit. * `scripts/base-modes.sh`: the CLI (`<tree>` normalises and self-checks, `--report-only` prints what is dirty). * applied in `os/v3/puppy/fix-ownership.sh`, the hook 3builddistro calls immediately before mksquashfs - the last moment the tree exists, and the same place that already refuses to pack when the setuid count moves. * `base_modes_verdict` + the `base-modes` row in os/mini/release-check.sh: counts the root filesystem outside the keep-list, PRINTS the keep-list that decided it (a silent change to that list is what a row should make visible), and the keep-list ships at /etc/1bit/base-modes-keep so the row judges against the machine's own copy. Six self-test arms. * `tests/base_modes_test.sh`: 16 arms, including the two that would have caught my own first version - a 0640 file stays 0640 and a 0700 directory stays 0700 (the normaliser must never widen), and `var/logrotate` is not kept by `var/log`. Boot proof on the real base tree: normalised (2,166 paths, 193 kept) -> mksquashfs with woof-CE's options -> mkimage.sh -> vm-check.sh: **77 PASS / 0 FAIL / 4 SKIP** (the 4 are structural: ssh key, two board rows, a second disk). After the run the reporter says clean and the bits that matter are untouched: etc/shadow 600, etc/gshadow 600, etc/sudoers 640, usr/bin/passwd 4755, tmp 1777, dev 775. * os: patch-sfs can normalise the base layer as it packs, so a CYCLE cut gets the fix too (#1474) The previous commit put the normaliser in fix-ownership.sh, which runs for a full woof-CE build. A cycle does not build: it unpacks the previous SFS, replaces a few paths and repacks - and that is what ships. `patch-sfs.sh --keep-modes <keeplist>` now normalises BOTH trees immediately before mksquashfs (the artifact IS $work/new), which keeps the declared-set metadata proof honest - the same transformation on each side means a mode line that differs is still a difference the patch made - and it refuses the packed SFS if the verify tree is still writable outside the keep-list. Measured on a fixture: `changed.txt` 664 -> 644 in the artifact, `other.txt` 775 -> 755, the keep-listed `usr/bin/kept.sh` stays 775, and the run ends "base modes: the packed SFS is clean outside keep.txt". `tests/patch_sfs_atomic_test.sh` still 11/11 (the flag is opt-in; without it a cut behaves exactly as before). The first attempt put the block after the pack, which the tool's own verify check caught as 'modes/owners/types/sizes are not the packed tree's' - the artifact had the un-normalised modes. * os: the base-modes row can be pointed at a tree, so it can be tested off a board (#1474) A row that can only be judged by booting an image cannot be tested - and this one was written with no way to run it. It now takes `BASE_SCAN_ROOT=<tree>` (the same trick the payload row already uses with `PAYLOAD_DIR`), with the prunes relative to that root, and it was checked both ways before the commit: the un-normalised base SFS tree reports 40+ writable paths (FAIL) and the normalised tree reports 0 (PASS). The boot-based check stays what the row does on a machine; this only makes it possible to run the scan without one. * os: the base-modes row counts the whole set, and its prune list comes from the keep-list (#1544 review) Two defects in the row, both real, both cheap: 1. `find ... | head -40` ran BEFORE the count, so `_bm_n_paths` was min(actual, 40): on the base layer this row exists for (2,176 writable paths) the failure sentence would have read "40 path(s)" - a 50x understatement in the one line a reader uses to judge severity. The find writes to a temp list, the count is `wc -l`, and only the SAMPLE is head-ed. 2. the prune list was a hand-copy of the keep-list, in a comment that claimed they were one thing. The next cycle to add a keep-list entry would have had no prune for it and the row would have failed on a path the keep-list explicitly allows, while the PASS branch printed that list as "the keep-list" that decided. The prune is now BUILT from the keep-list, and the four paths pruned for a different reason (`data initrd mnt media` - not part of the OS image) are named separately. Checked off-image with `BASE_SCAN_ROOT` (no boot needed): a fixture with 60 writable files and 7 writable directories now reports **67**, where the old row said 40; adding `big/` to the keep-list drops it to **65** with no other edit, which is the property the hand-copied list did not have. Also: the self-test's keep-list size is 11 (the shipped file's count, was 10), and the note about a zero-sized keep-list says where that case is covered (the row SKIPs on a missing file; an empty one is a repository error, not a machine state). --------- Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
Follow-up to #1352 (closed by #1361). No issue to close — this is the same defect class in a site both earlier fixes missed, found by enumerating the packing sites instead of reasoning about the two already fixed.
What was still open
Three scripts source
scripts/pack-elf.shand write an archive. Only two applied the mode rule:package-linux.shweekly.shmake-binary-drop.shbinary-drop-<version>.tar.zst— a published artifact (docs/releases.md, "The public binary drop")pack-distro.shMeasured, not argued
make-binary-drop.shstages withcp -afrom whatever it is pointed at:--build <dir>→ the build tree's modes. Measured on a real one,~/wt/rlk-build/hrx/llama/binis 13 of 13 files at0775(-rwxrwxr-x) — so a drop built that way ships 0775 binaries and libraries.--from-package <tarball>→ whatever that tarball had, including one packed before package-linux: a staged file's mode is the packer's decision, and the package asserts it #1361/package: the lemonade payload is the second packing site, and it shipped 0775 files (#1352) #1360. c31's payload measured 111×0664 + 23×0775.So the published drop's modes were entirely inherited from its inputs. It now runs
pack_normalise_modesand asserts withpack_writable_filesbefore writing the archive, anddocs/releases.mdsays so in the drop's own section.The regression guard, and why it looks the way it does
tests/pack_modes_test.shnow enumerates the packing sites from the tree (sourcespack-elf.sh+ writes an archive) rather than listing them, so a fourth site cannot be forgotten. Two tiers, because the sites are not the same job:pack_normalise_modes— no exceptions, it cannot change behaviour;pack_writable_files.pack-distro.shis the single exemption, and it is that script's own decision, documented at its lines 63-74: it stages on the formatter's own copy, so the chmod cannot fail there, and it judged the reporter to be decoration. The test records that decision explicitly, so a second site wanting the exemption has to edit the list — which is the point.Three negative controls, run and restored
The first version of this check matched a commented-out call and passed with the guard disabled — caught by the negative control, which is why the pattern now anchors at the start of a line. That is the second time in this work that a check I wrote could not fail; both times the control is what found it.
One observation I am not overriding:
pack-distro.sh's comment says the mode is "checked where it can actually be wrong … on the finished archives, byscripts/pack-proof.sh".pack-proof.shcompares modes between formats (deb/rpm/arch agree), so it cannot catch a uniformly-writable payload — the exemption rests on "the chmod cannot fail", not on a proof. Flagging it for that lane rather than changing their call.Checks:
bash tests/pack_modes_test.shrc 0 (plus the three controls above),bash -nclean on the touched script,tools/copyright.py --checkrc 0. 0 s GPU, 0 s NPU, no ticket, nothing merged.