fix: a delta layer is the final tree diff against its parent #18

Merged
marcos-mendez merged 1 commit from fix/delta-layer-final-diff into 19.x 2026-10-08 00:15:14 -03:00
marcos-mendez commented 2026-10-07 22:09:16 -03:00 (Migrated from github.com)

A child layer was packed as the two deck upper directories in turn (root.build, then root.patched). A file created in stage 1 and deleted in stage 2 is content in one and a whiteout in the other, so the tarball shipped its bytes followed by the whiteout. The unpacked tree was right; the bytes were still published. This is how the postgresql layer of 2026-10-08 (not published) carried the snakeoil key ssl-cert makes; layer_audit_keys reads the final tree, where the whiteout already hides it.

  • layer_delta_lists computes the members from the final tree and the parent: paths either upper holds that root.patched still has (packed from root.patched); a whiteout only for a path the parent has and the final tree lacks; an opaque directory over a parent directory taken from its upper so the mark survives. Created-then-deleted leaves nothing.
  • NUL-separated sorted lists read with --null --no-recursion: reproducible (the -u re-export stays byte identical).
  • bt-layer passes the parent rootfs and fails if the members cannot be listed.

Tests (tests/layer, section 10a): a fake key created in stage 1 and whited out in stage 2 is neither named nor present byte for byte in a real tarball; parent file removed = whiteout; file re-created packed once; opaque directory from its upper; refusals; the real predicates. layer-lib 99.54 percent locally (gate 99); the one new uncovered line is a loop's done.

A child layer was packed as the two deck upper directories in turn (root.build, then root.patched). A file created in stage 1 and deleted in stage 2 is content in one and a whiteout in the other, so the tarball shipped its bytes followed by the whiteout. The unpacked tree was right; the bytes were still published. This is how the postgresql layer of 2026-10-08 (not published) carried the snakeoil key ssl-cert makes; `layer_audit_keys` reads the final tree, where the whiteout already hides it. - `layer_delta_lists` computes the members from the final tree and the parent: paths either upper holds that `root.patched` still has (packed from `root.patched`); a whiteout only for a path the parent has and the final tree lacks; an opaque directory over a parent directory taken from its upper so the mark survives. Created-then-deleted leaves nothing. - NUL-separated sorted lists read with `--null --no-recursion`: reproducible (the `-u` re-export stays byte identical). - `bt-layer` passes the parent rootfs and fails if the members cannot be listed. Tests (`tests/layer`, section 10a): a fake key created in stage 1 and whited out in stage 2 is neither named nor present byte for byte in a real tarball; parent file removed = whiteout; file re-created packed once; opaque directory from its upper; refusals; the real predicates. `layer-lib` 99.54 percent locally (gate 99); the one new uncovered line is a loop's `done`.
Sign in to join this conversation.
No description provided.