feat(manifest): add schema_version and ci_run_number #33
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/manifest-schema-v2"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Must land before the next build — manifests are append-only, so a release built without these fields can never gain them.
ci_run_numbercloses a provenance holebuild-kernel.yml:262passesgithub.run_numbertobuild-debs.shasREVISION, which becomesKBUILD_BUILD_VERSION(build-debs.sh:232) and thereforeUTS_VERSIONinsidevmlinux— whiletools/repro-check.sh:146hard-codesREVISION=1and the manifest recorded the value nowhere (verified: no such key in any of the twelve manifests).So every published release contains a number in its kernel banner that no verifier can discover, and no independent rebuild of
linux-imageorlinux-image-*-dbgcould ever match. A follow-up removes the build's dependency on it entirely (derivingKBUILD_BUILD_VERSIONfrom the tag instead); this field preserves the traceability that change gives up.schema_versionlets a reader branch instead of assumeAn absent
schema_versionmarks the twelve legacy releases, whichrepro-check.shmust report as partially verifiable rather than failed — they are missing a field that cannot be reconstructed. Without this marker the nightly check stays permanently red for a reason nobody can act on, which is worse than having no check.releases/README.mdnow documents what each version promises, including thatv7.0.10-hardened1andv7.0.10-hardened1.2carrynullforkernel_version/hardened_revisionand are not checkable at all.Verification
--ci-run-number 58schema_version: 2,ci_run_number: "58"null),schema_version: 2releases/*/manifest.jsonpy_compileclean,yamllint -d relaxedexit 0. No behaviour change to existing manifests; both fields are additive.🤖 Generated with Claude Code
CHANGES SHIPPED BYTES. Verify against the draft release before publishing. Every kernel this project has shipped publishes a runner temp-directory name. Confirmed by reading it off a running machine, not inferred: # zcat /proc/config.gz | grep MODULE_SIG_KEY CONFIG_MODULE_SIG_KEY="/tmp/tmp.TliL5BYWSL/signing.pem" Mechanism: configure-kernel.sh appended a per-build `mktemp -d` path to the TREE's .config after the fidelity assertion, and build-debs.sh normalized that value back to the placeholder only in the separately-captured final.config. But bindeb-pkg ships the tree's .config as /boot/config-<rel>, embeds it into vmlinux via CONFIG_IKCONFIG (= /proc/config.gz), and packages it in the headers .deb. Three consequences, ascending: 1. An information leak: the runner's temp-dir name is in every kernel. The private key itself was never shipped. 2. Same-tag rebuilds were never bit-identical, because mktemp differs per run -- directly contradicting build-debs.sh's own comment. 3. Possibly broken DKMS, untested either way: MODULE_SIG_ALL=y and the headers package carries that .config, so an out-of-tree build going through the kernel's own modules_install signing path reaches for a key file that does not exist. docs/users/dkms.md already concedes that path is unvalidated against a published release, so this is an open interaction. The Verification section below says how to settle it. Fix: make CONFIG_MODULE_SIG_KEY a CONSTANT in-tree path, so the value the fidelity assertion checks is the value that ships. Nothing to rewrite, nothing to normalize, no ordering requirement against the assertion. certs/unredacted-signing.pem, deliberately NOT the stock certs/signing_key.pem: upstream certs/Makefile guards a FORCE + if_changed,gen_key rule with `ifeq ($(CONFIG_MODULE_SIG_KEY),certs/signing_key.pem)`, so under the default name kbuild would REGENERATE our pre-placed key with a random one and ship a kernel trusting a key nobody holds. That name is also on MRPROPER_FILES. With a non-default name no generator rule exists, so a missing key fails loudly. That kbuild behaviour is the load-bearing assumption here and cannot be tested without a real build, so build-debs.sh now asserts the outcome instead of trusting it. Three new hard failures, all post-`make`, so the cost of tripping one is a rebuild and never a bad release: (a) cert identity: the DER kbuild extracted into certs/signing_key.x509 -- which it links into .builtin_trusted_keys, the trust root for every module signature this kernel accepts -- must equal our PEM's certificate. This is what turns a wrong kbuild assumption into an aborted build rather than a silently mis-keyed kernel. (b) no private key in any .deb. We now put a key inside a tree bindeb-pkg packages from; mkdebian's file list should not match certs/*.pem, but the cost of being wrong is publishing a signing key, so assert it. (c) config parity: the /boot/config-* inside the image .deb must be byte-identical to the captured final.config. That divergence IS this bug, undetected for twelve releases; now it cannot recur silently. Also removes the CI run number from the shipped bytes. It reached KBUILD_BUILD_VERSION and so UTS_VERSION inside vmlinux while being recorded nowhere and hard-coded to 1 in repro-check.sh -- three independent reasons a rebuild could never match. KBUILD_BUILD_VERSION now derives from the tag (PACKAGING_REVISION, default 1); traceability moved to manifest.ci_run_number. repro-check.sh: passes PACKAGING_REVISION parsed from the tag, which makes the five .P releases structurally verifiable for the first time (previously the rebuild emitted ...-hardened1 .debs and every file reported MISSING, reading like tampering rather than a missing input); cross-checks the manifest's kernel_version/hardened_revision against the tag; and generates a throwaway signing key, since without one the rebuild would now fail at `make` rather than silently generating a random one. Byte-identity on the cert-embedding artifacts (vmlinuz, System.map, -dbg) still needs the real private key -- handing over the published .der cannot help, because signing needs the private half -- so REPRO_SIGNING_KEY_PATH is honoured for operators who hold it. Localizing that divergence properly is follow-up work on the comparison itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>