Kernel release 6.18.38-rt-cuckoo+: reproducible build, guarded installer
Rebuilt with KBUILD_BUILD_USER/HOST/TIMESTAMP pinned. Without them the kernel bakes the builder's user@hostname and wall-clock build time into /proc/version, which publishes operator identity in a public artifact and makes the build unreproducible. Pinned, anyone can rebuild and diff the bytes — the only trust story available for an unsigned community kernel. The installer refuses to run on anything but a Pi 4, refuses a mismatched image/modules pair (vermagic failure means no /dev/pps0 on a kernel that otherwise boots fine — silent and miserable to debug), verifies SHA256SUMS, never touches kernel8.img, and leaves rollback as deleting one config.txt line. Boot-tested on the Pi: Stratum 1, 273 ns offset, PPS handler confirmed NOT threaded. Binaries ship as release assets, not in git.
This commit is contained in:
parent
6b6d80ded3
commit
3b505644b2
15 changed files with 333 additions and 62 deletions
|
|
@ -56,4 +56,4 @@ deploy: ## Pull main + rebuild the docs container on the prod host
|
|||
@echo "==> deploying $(DEPLOY_HOST):$(DEPLOY_PATH)"
|
||||
ssh -A $(DEPLOY_HOST) "cd $(DEPLOY_PATH) && git fetch origin main && git reset --hard origin/main && cd docs-site && make prod"
|
||||
@echo "==> sanity check"
|
||||
@curl -s -o /dev/null -w " HTTP %{http_code} %{url_effective}\n" "https://cuckoo.warehack.ing/explanation/bug-detection/"
|
||||
@curl -s -o /dev/null -w " HTTP %{http_code} %{url_effective}\n" "https://cuckoo.warehack.ing/explanation/preempt-rt-made-it-worse/"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Downloads — prebuilt RT kernel
|
||||
description: A patched PREEMPT_RT kernel for the Raspberry Pi 4, so you don't need a cross-compile toolchain.
|
||||
description: A patched PREEMPT_RT kernel for the Raspberry Pi 4, boot-tested and benchmarked, so you don't need a cross-compile toolchain.
|
||||
sidebar:
|
||||
order: 5
|
||||
---
|
||||
|
|
@ -9,28 +9,37 @@ The only expensive part of [the patch](/reference/the-patch/) is the toolchain.
|
|||
Building natively on a Pi 4 takes hours; cross-compiling needs an x86 box and a
|
||||
setup session. So here's the artifact.
|
||||
|
||||
**Current release: `6.18.38-rt-cuckoo+`** — Raspberry Pi's `rpi-6.18.y`,
|
||||
`bcm2711_defconfig`, `PREEMPT_RT`, plus the `IRQF_NO_THREAD` patch.
|
||||
|
||||
:::danger[Read this before you download]
|
||||
- **Raspberry Pi 4 / arm64 only.** `bcm2711_defconfig`. It will not boot a Pi 5 or
|
||||
a Pi 3.
|
||||
- **Unsigned, community-built.** We built this on a workstation. There is no chain
|
||||
of trust here beyond "we published the exact recipe and the checksums." If that
|
||||
isn't good enough for your environment — and for some environments it correctly
|
||||
isn't — [build it yourself](/how-to/cross-compile-rt-kernel/). It's forty
|
||||
minutes.
|
||||
- **Verify the checksums.** They're in `SHA256SUMS`.
|
||||
- **Raspberry Pi 4 / arm64 only.** The installer refuses to run on anything else,
|
||||
because a `bcm2711` kernel on a Pi 5 doesn't boot — and a black screen on a
|
||||
headless box is exactly the outcome we're trying to prevent.
|
||||
- **Unsigned, community-built.** There is no chain of trust here beyond published
|
||||
checksums and a reproducible recipe. For some environments that is correctly
|
||||
not good enough. [Build it yourself](/how-to/cross-compile-rt-kernel/) — it's
|
||||
forty minutes, and `kernel/build.sh` in the repo does the whole thing.
|
||||
- **Verify the checksums.** The installer does it for you if `SHA256SUMS` is
|
||||
present. Don't skip it.
|
||||
:::
|
||||
|
||||
## Artifacts
|
||||
|
||||
Published on the [releases page](https://git.supported.systems/warehack.ing/cuckoo-escapement/releases):
|
||||
On the [releases page](https://git.supported.systems/warehack.ing/cuckoo-escapement/releases):
|
||||
|
||||
| File | What |
|
||||
| File | |
|
||||
|---|---|
|
||||
| `kernel-rt-<ver>.img.gz` | The kernel image, gzipped (Pi OS's own format) |
|
||||
| `rt-modules-<ver>.tar.gz` | Matching modules — **must** be installed with the image |
|
||||
| `install-rt-kernel.sh` | Installer. Adds a *new* image, never replaces `kernel8.img` |
|
||||
| `kernel-rt-6.18.38-rt-cuckoo+.img.gz` | The kernel, gzipped (Pi OS's own format) — 9.8 MB |
|
||||
| `rt-modules-6.18.38-rt-cuckoo+.tar.gz` | Matching modules — 22 MB. **Must** be installed with the image. |
|
||||
| `install-rt-kernel.sh` | Installer. Adds a *new* image; never replaces `kernel8.img`. |
|
||||
| `SHA256SUMS` | Checksums |
|
||||
|
||||
```
|
||||
97533ea81ec56ef090908560e88bccfb2a3f7dfcc3d33a5a1cbe4bbf15163b55 kernel-rt-6.18.38-rt-cuckoo+.img.gz
|
||||
6af126711eef2ae1651ac48e19353e6830f12fb0ef9a7e265f54c27206a4f0eb rt-modules-6.18.38-rt-cuckoo+.tar.gz
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
|
|
@ -39,34 +48,68 @@ sudo ./install-rt-kernel.sh
|
|||
sudo reboot
|
||||
```
|
||||
|
||||
The installer:
|
||||
Then confirm the patch is actually live. This is the check that matters:
|
||||
|
||||
1. Untars the modules into `/lib/modules/`
|
||||
2. Writes the image as `/boot/firmware/kernel-rt.img` — **`kernel8.img` is left
|
||||
alone**
|
||||
3. Appends one line, `kernel=kernel-rt.img`, to `config.txt`
|
||||
```console
|
||||
$ uname -a
|
||||
Linux … 6.18.38-rt-cuckoo+ #1 SMP PREEMPT_RT … aarch64
|
||||
|
||||
**Rollback is deleting that one line.** Mount the SD card's FAT partition on any
|
||||
machine, remove it, and the stock kernel boots. That's deliberate: you should never
|
||||
have to make a physical trip to a headless box because of a kernel you got from a
|
||||
website.
|
||||
|
||||
## What's in it
|
||||
|
||||
Raspberry Pi's `rpi-6.12.y` tree, `bcm2711_defconfig`, plus exactly two changes:
|
||||
|
||||
```bash
|
||||
scripts/config --enable PREEMPT_RT
|
||||
# + the IRQF_NO_THREAD patch in drivers/pps/clients/pps-gpio.c
|
||||
$ ps -eo comm | grep irq/.*pps
|
||||
(nothing)
|
||||
```
|
||||
|
||||
Nothing else. The full recipe is in
|
||||
[Cross-compile an RT kernel](/how-to/cross-compile-rt-kernel/), and you should be
|
||||
able to reproduce this byte-for-byte modulo build timestamps.
|
||||
**That empty output is the whole point.** If an `irq/NN-pps@…` thread appears,
|
||||
the handler is being force-threaded and [your timestamp is being taken behind the
|
||||
scheduler](/explanation/preempt-rt-made-it-worse/).
|
||||
|
||||
## Rollback is one line
|
||||
|
||||
The installer appends exactly one line to `config.txt` and never touches
|
||||
`kernel8.img`. If the Pi doesn't come back: pull the SD card, open `config.txt`
|
||||
on any machine (it's a FAT partition — a Windows laptop will do), delete the
|
||||
`kernel=kernel-rt.img` line, put the card back. The stock kernel boots.
|
||||
|
||||
It also leaves a `config.txt.before-rt` next to it.
|
||||
|
||||
## What we actually tested
|
||||
|
||||
Not "it compiled." This exact artifact, installed by that exact script, on a Pi 4:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Boots | yes |
|
||||
| `uname` | `6.18.38-rt-cuckoo+ SMP PREEMPT_RT` |
|
||||
| PPS handler threaded | **no** — patch confirmed live |
|
||||
| chrony | Stratum 1, ref PPS |
|
||||
| System offset | 273 ns |
|
||||
| Raw PPS jitter | 952 ns σ over 62 s |
|
||||
|
||||
:::note[One window is not a benchmark]
|
||||
That 952 ns is a single 62-second sample, on a fresh boot under a clear sky, and
|
||||
it is *better* than the 2568 ns in [the measurements](/reference/measurements/).
|
||||
We report it because it's what we saw — not as a revision of the headline
|
||||
numbers. Those came from an [A/B/A protocol](/how-to/benchmark-pps-jitter/), and
|
||||
one lucky window doesn't overturn them. Sky conditions move this figure around
|
||||
more than most software changes do. Measure your own board.
|
||||
:::
|
||||
|
||||
## Reproducing it
|
||||
|
||||
```bash
|
||||
git clone https://git.supported.systems/warehack.ing/cuckoo-escapement
|
||||
cd cuckoo-escapement/kernel && ./build.sh
|
||||
```
|
||||
|
||||
`KBUILD_BUILD_USER`, `KBUILD_BUILD_HOST` and `KBUILD_BUILD_TIMESTAMP` are pinned
|
||||
in that script. Without them a kernel bakes the builder's `user@hostname` and the
|
||||
wall-clock build time into `/proc/version` — which publishes whoever built it and
|
||||
makes the output unreproducible. Pinned, you should be able to rebuild this and
|
||||
compare bytes. For an unsigned kernel from a website, that's the only trust story
|
||||
we can honestly offer.
|
||||
|
||||
:::note[Pinned to a tested version]
|
||||
The published download always points at a kernel we have **actually booted and
|
||||
benchmarked** on a Pi 4 — not simply the newest upstream. Shipping a stranger an
|
||||
unvalidated kernel for a machine they may not be able to physically reach is not
|
||||
something we're willing to do.
|
||||
The published download always points at a kernel we have **booted and benchmarked
|
||||
on a Pi 4** — never simply the newest upstream. Shipping a stranger an unvalidated
|
||||
kernel, for a machine they may not be able to physically reach, is not something
|
||||
we're willing to do.
|
||||
:::
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue