diff --git a/AGENTS.md b/AGENTS.md index 62c8053..9482cc0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -148,7 +148,8 @@ falling back from a release that does not come up. ## The kernel and firmware -- The base is Arch Linux's configuration for the same kernel (`kernel/Dockerfile`), with general-PC +- The base is Arch Linux's configuration for the same kernel, or its newest tag's while Arch has none + for a kernel we adopt first (`kernel/Dockerfile` says what that leaves out), with general-PC drivers as modules unless the supported-hardware policy and measured image or boot budgets say otherwise. Adopt an Arch kernel tag after its configuration assertions and relevant compatibility and performance checks pass; availability alone is not a release criterion. diff --git a/Taskfile.yml b/Taskfile.yml index 9083b8b..c4584c1 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -480,6 +480,10 @@ tasks: - go run ./cmd/image cache pull # The cache goes back however the job ends: what a failed release built is not built again. - defer: go run ./cmd/image cache push + # Every build no recipe makes goes first, and the index with it: a recipe renamed since the + # cache was stored leaves an older package of the name others ask for, or of a higher version, + # and the build that resolves to it fails. + - task: packages:prune - task: release:inputs # The harness on a test build of the same commit, its roots built from the locks: a release # whose checks fail is not built, and the release's stick is made from the same roots. @@ -490,8 +494,6 @@ tasks: - task: scan - task: release:publish vars: {VERSION: '{{.VERSION}}', NEW: '{{.NEW}}'} - # Every build no recipe makes goes before the cache takes packages/ back (the deferred push). - - task: packages:prune packages:prune: desc: "Remove every apk in packages/ that no recipe makes now, and index again: old versions, and a build of a recipe never committed, which apko would take over the recipe's own." diff --git a/build/versions.env b/build/versions.env index d070883..7dd4c56 100644 --- a/build/versions.env +++ b/build/versions.env @@ -6,7 +6,7 @@ WOLFI_BASE_IMAGE=cgr.dev/chainguard/wolfi-base:latest@sha256:88a20e2d017bd20cdc0cb3910de603e7bea9512a6c351a8dd3c9df212ab03d73 # The kernel, from kernel.org. A new series can fail the fragments' assertions; Arch's base config -# (kernel/Dockerfile) is pinned to the same version. +# (kernel/Dockerfile) is pinned to the same version, or Arch's newest while it has none for this one. KERNEL_VERSION=7.3.1 KERNEL_SHA256=fa595aad93734f829c963c2a90ef7c3673224fd7fdae7b49406e397cde2de231 diff --git a/cmd/image/test.go b/cmd/image/test.go index abfe45c..b979f7f 100644 --- a/cmd/image/test.go +++ b/cmd/image/test.go @@ -151,6 +151,7 @@ func test(args []string) (err error) { r.add("the login keyring is open", strings.TrimSpace(keyring) == "kept", oneLine(keyring)) if *stick { r.secureBoot(g) + r.dbxCurrent(g) r.efiPrograms(g) r.loaderCache(g) } @@ -944,11 +945,18 @@ func keyringRoundTrip(user string, uid int) string { func (r *report) secureBoot(g *guest) { out, _ := g.run(`bootctl status 2>/dev/null | grep -E 'Secure Boot:'; cat /sys/kernel/security/lockdown`, "") r.add("secure boot", strings.Contains(out, "Secure Boot: enabled (user)") && strings.Contains(out, "[integrity]"), oneLine(out)) - // The stick's dbx (espTree), and fwupd finding it current. A newer dbx from Microsoft fails this at - // once, rather than as a notification over the views on the runs GNOME Software is quick enough: - // build/dbx.auth moves, to the .bin of LVFS's newest com.microsoft.dbx.x64-kek2023.firmware cabinet. - dbx, _ := g.run(`test -s /sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f && echo enrolled; fwupdmgr get-updates --no-unreported-check --json 2>&1 | grep -c '"UEFI dbx"'`, "") - r.add("dbx current", strings.Contains(dbx, "enrolled") && strings.TrimSpace(lastLine(dbx)) == "0", oneLine(dbx)) +} + +// dbxCurrent checks the stick's dbx (espTree) is the one fwupd finds current. A newer dbx from +// Microsoft fails this at once, rather than as a notification over the views on the runs GNOME +// Software is quick enough: build/dbx.auth moves, to the .bin of LVFS's newest +// com.microsoft.dbx.x64-kek2023.firmware cabinet. It waits for LVFS's metadata, of megabytes where a +// machine's own remotes' are not: without it fwupd offers nothing, whatever the dbx. +func (r *report) dbxCurrent(g *guest) { + out, _ := g.run(`test -s /sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f && echo enrolled; `+ + `for i in $(seq 180); do test -n "$(find /var/cache/fwupd/metadata.xmlb -size +1M 2>/dev/null)" && { echo metadata; break; }; sleep 1; done; `+ + `fwupdmgr get-updates --no-unreported-check --json 2>&1 | grep -c '"UEFI dbx"'`, "") + r.add("dbx current", strings.Contains(out, "enrolled") && strings.Contains(out, "metadata") && strings.TrimSpace(lastLine(out)) == "0", oneLine(out)) } // efiPrograms checks the root's EFI programs are the signed ones the firmware runs: systemd-boot on diff --git a/kernel/patches/0012-erofs-interrupted-read-is-no-error.patch b/kernel/patches/0012-erofs-interrupted-read-is-no-error.patch new file mode 100644 index 0000000..23265ab --- /dev/null +++ b/kernel/patches/0012-erofs-interrupted-read-is-no-error.patch @@ -0,0 +1,49 @@ +construct: not upstream yet, to be sent to linux-erofs. A read of a block not yet in the page cache +waits killably, so a process killed meanwhile gets -EINTR, and erofs logged that as a filesystem +error: at every app that exits while its page faults are in flight (VS Code closing, about 3 harness +runs in 10, on the journal and in GNOME Logs). The filesystem is fine, and dm-verity would have said +otherwise: corruption is -EIO, and panics here. The other errors keep their message. + +Subject: [PATCH] erofs: Do not log a read interrupted by a fatal signal as an error + +--- a/fs/erofs/dir.c ++++ b/fs/erofs/dir.c +@@ -83,9 +83,10 @@ + + de = erofs_bread(&buf, dbstart, true); + if (IS_ERR(de)) { +- erofs_err(sb, "failed to readdir of logical block %llu of nid %llu", +- erofs_blknr(sb, dbstart), EROFS_I(dir)->nid); + err = PTR_ERR(de); ++ if (err != -EINTR) ++ erofs_err(sb, "failed to readdir of logical block %llu of nid %llu", ++ erofs_blknr(sb, dbstart), EROFS_I(dir)->nid); + break; + } + +--- a/fs/erofs/inode.c ++++ b/fs/erofs/inode.c +@@ -52,8 +52,9 @@ + ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), in_mbox); + if (IS_ERR(ptr)) { + err = PTR_ERR(ptr); +- erofs_err(sb, "failed to read inode meta block (nid: %llu): %d", +- vi->nid, err); ++ if (err != -EINTR) ++ erofs_err(sb, "failed to read inode meta block (nid: %llu): %d", ++ vi->nid, err); + goto err_out; + } + +@@ -91,8 +92,9 @@ + erofs_pos(sb, blkaddr + 1), in_mbox); + if (IS_ERR(ptr)) { + err = PTR_ERR(ptr); +- erofs_err(sb, "failed to read inode payload block (nid: %llu): %d", +- vi->nid, err); ++ if (err != -EINTR) ++ erofs_err(sb, "failed to read inode payload block (nid: %llu): %d", ++ vi->nid, err); + goto err_out; + } + ofs = vi->inode_isize - gotten;