May has been a kernel month. Three Linux LPEs landed in two weeks:
| CVE | Subsystem | Disclosed | Rocky patch |
|---|---|---|---|
| CVE-2026-43284 — “Dirty Frag” (esp) | esp4 / esp6 xfrm decrypt | 2026-05-07 | Shipped in 5.14.0-611.55.1.el9_7 and 6.12.0-124.56.1.el10_1 |
| CVE-2026-43500 — “Dirty Frag” (rxrpc) | rxrpc | 2026-05-07 | Not yet in any Rocky kernel |
| CVE-2026-46300 — “Fragnesia” | ESP-in-TCP, bypasses Dirty Frag | 2026-05-13 | Not yet in any Rocky kernel |
The fleet already runs kernels containing the 43284 fix — the last patching pass made sure of that. That left two unpatched holes and no errata on the horizon. Microsoft’s blog on May 8 made it clear 43284 was being exploited post-compromise in the wild; assuming the same fate awaits 43500 and 46300 is the safe bet. Waiting two weeks for Rocky 9.7 / 10.1 errata kernels isn’t acceptable when the mitigation is a five-line config file.
So tonight was about deploying that file.
The mitigation
All three CVEs require the relevant kernel module to be loadable. esp4, esp6, and rxrpc aren’t used by anything on this fleet — no IPsec, no AFS, no Kerberos rxrpc. The modules sit in /lib/modules/.../kernel/net/ waiting to be loaded by something that asks for them, and nothing asks. The risk is that something post-compromise could ask: a foothold with CAP_SYS_MODULE (or a sysadmin tricked into loading it for diagnostics) can modprobe rxrpc and immediately have an LPE primitive in front of them.
The fix is to make modprobe refuse:
blacklist esp4
blacklist esp6
blacklist rxrpc
install esp4 /bin/true
install esp6 /bin/true
install rxrpc /bin/true
The blacklist line stops auto-loading (e.g. via udev or netfilter); the install <mod> /bin/true line is the real teeth. It tells modprobe that the command to “install” the module is /bin/true — a no-op. Even an explicit modprobe rxrpc resolves to running /bin/true, and the module never enters the kernel. It’s the same trick people use to disable USB storage or firewire on hardened workstations.
Verifying it works:
sudo modprobe -n -v rxrpc # "install /bin/true"
sudo modprobe -n -v esp4 # "install /bin/true"
sudo modprobe -n -v esp6 # "install /bin/true"
lsmod | grep -E '^(esp4|esp6|rxrpc)' # no output
If the first three resolve to actual module paths, the modprobe cache is stale or the file didn’t write — sudo depmod -a fixes the former. I ran this on every host after deploying. All nine returned install /bin/true for all three modules.
The dracut question
The thing I wasn’t sure about going in: do I need to rebuild the initramfs?
If a vulnerable module is baked into the initramfs, blacklisting it in /etc/modprobe.d/ doesn’t matter during early boot. The initramfs has its own copy. The standard escalation is dracut --force after editing modprobe config, which propagates the new rules into the initramfs.
But that costs a reboot to take full effect — and reboots across nine production hosts are not a thing I want to do at 22:30 on a Tuesday for a mitigation that’s defensive-in-depth. So I checked first.
lsinitrd | grep -E '(esp4|esp6|rxrpc)\.ko'
Returned no matches on both 5.14.0-611.55.1.el9_7 (the Rocky 9.7 line) and 6.12.0-124.56.1.el10_1 (the Rocky 10.1 line). Neither default initramfs ships these modules. The userspace /etc/modprobe.d/ rules are the only gate that has to hold, and they hold from boot — because the modules only enter the running kernel via userspace modprobe, which is now /bin/true.
No dracut --force needed. No reboot. The mitigation is live on every host from the moment the file finished writing.
The one exception
netbird-server is the odd host out. It runs a CIQ kernel rather than stock Rocky, and CIQ has already shipped both the 43500 and 46300 patches as part of their security-as-a-service line. I checked rpm -q --changelog kernel-core on that host — both CVE IDs are present in the changelog. Blacklisting the modules there would be redundant, and worse, it would silently disable any IPsec functionality I happen to need on the only host where the Netbird control plane lives. Skipping it was the right call.
That’s the kind of asymmetry the fleet had to accommodate. Eight hosts on stock Rocky errata; one host on a different patch cadence. The runbook now explicitly carves out the exception so the next person reading it doesn’t deploy too aggressively.
n8n docs that contradicted the ADR
The earlier commit tonight was smaller but bothered me more. Back on 2026-04-29 (commit af59479), applications/n8n/deploy.sh was changed to pin n8n to 2.18.5, matching ADR-0001 — the image-pinning policy I keep writing posts about. The deploy path was correct.
But applications/n8n/README.md and applications/n8n/docs/QUICK-REFERENCE.md still showed docker.io/n8nio/n8n:latest in their image and update instructions. Both files had been written months earlier and never updated when the pin landed.
Anyone following the documented update path would have pulled :latest. The Quadlet pin would have held the running container on whatever digest :latest resolved to at the time the unit was created, but the next podman pull step in the docs would have grabbed a newer image — and the next systemctl restart n8n would have picked it up. The exact drift pattern ADR-0001 exists to prevent, surviving inside the documentation for that ADR’s enforcement mechanism.
The fix was eight lines of diff. The docs now show docker.io/n8nio/n8n:2.18.5 and reference ADR-0001 for the bump cadence. n8n itself is already on 2.18.5, which clears the CVE-2026-33660 fix line (>=2.18.1), so Homelab issue #266 closed at the same time.
I’m noting this because it’s the second time in two weeks I’ve found docs that disagreed with deploy code. The first time was the canary-on-latest post a week ago. Both followed the same pattern: a control gets added in one file, the docs that describe how to use the system don’t get the memo, and the gap is invisible until someone tries to follow the docs. The control was real. The path to it was wrong.
Sidebar: the bug-finding ratchet keeps tightening
The research digest tonight surfaced Project Glasswing, which Krebs wrote about under the May Patch Tuesday banner. The headline finding: Mythos Preview (an Anthropic model variant focused on code analysis) found a 27-year-old bug in OpenBSD and a 16-year-old bug in FFmpeg, both shipped to production stable releases. Both projects feed downstream into Rocky and the rest of this lab’s software supply chain.
None of the Glasswing-found bugs hit this stack as a specific CVE yet. But the implication is uncomfortable: large language models are surfacing memory-safety bugs in well-audited C codebases at a rate the upstream maintainers couldn’t sustain manually for three decades. The same tooling, in different hands, finds the same bugs. Today’s blacklist file mitigates two unpatched LPEs. The next disclosure window won’t be three weeks long. It’ll be the gap between “Mythos finds it” and “an exploit kit picks it up.” The runbook I wrote tonight is going to get more practice than I want it to.
