
Eine Ansible-Rolle und ein Python-Skript, die die Exposition des Linux-Kernels gegenüber CVE-2026-98432 erkennen und eine nftables-Regel anwenden, die eingehende IPv4-SYNs mit IP-Optionen verwirft.
Eine Use-after-free im IPv4-TCP-Code des Linux-Kernels
(CVE-2026-98432, CVSS 9.8):
IPv4-Optionen, die aus einem eingehenden SYN gespeichert wurden, können
freigegeben werden, während eine andere CPU sie noch liest, um ein SYNACK
zu erstellen, weil zwei Destruktor-Pfade sie mit einem einfachen kfree()
freigeben, anstatt auf eine RCU-Grace-Period zu warten.
Der Upstream-Fix ist
e3f33b0a1d89
("ipv4: free inet_opt and ireq_opt after an RCU grace period").
Stand 2026-10-29 ist für keine Ubuntu-Serie ein gepatchter Kernel veröffentlicht. Jeder betroffene Status im Ubuntu-Tracker lautet „work in progress" oder schlicht verwundbar, und die Seite listet keine Gegenmaßnahme auf. Dieses Paket ist die Gegenmaßnahme.
Beide konkurrierenden Pfade lesen ireq->ireq_opt, die IPv4-Optionen, die der Kernel aus
dem eingehenden SYN gespeichert hat (tcp_v4_save_options()): Der SYNACK-Aufbau liest
sie, während der Abbau des Child-Sockets sie freigeben kann, und die Migration von
Request-Sockets (net.ipv4.tcp_migrate_req=1 oder ein
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE-Programm) teilt und gibt dieselben
Optionen frei. Wenn ein SYN keine IPv4-Optionen enthält, ist ireq_opt NULL: Es gibt
nichts freizugeben und nichts zu lesen. Wir haben den Fix-Commit gelesen, bevor wir uns
darauf verlassen haben; beide Hälften gehen von einem SYN aus, der IPv4-Optionen enthielt.
Daher installiert das Paket eine einzige nftables-Regel, die eingehende IPv4-TCP-SYNs mit IP-Optionen verwirft, in einer eigenen Tabelle, damit sie nie mit den Regeln von Docker, der Substrat-Umgebung oder der Distribution kollidiert:
table inet samp_cve_2026_98432 {
chain prerouting {
type filter hook prerouting priority -300; policy accept;
ip hdrlength > 5 tcp flags & (syn | ack) == syn counter drop \
comment "CVE-2026-98432: drop inbound IPv4 SYN carrying IP options"
}
}
Vor der Veröffentlichung auf einem echten Kernel verifiziert: Ein IPv4-SYN mit Optionen trifft den Zähler und wird verworfen; ein einfacher SYN passiert unverändert. TCP-Verkehr trägt fast nie IP-Optionen (mehrere Optionstypen werden von vielen Netzwerken routinemäßig verworfen, gemäß RFC 7126), sodass die betrieblichen Kosten der Regel nahezu null sind.
pve-Kernel,
den Ubuntus Seite nicht abdeckt) melden unknown: lesen Sie deren
Advisories. Die Regel selbst würde jeden Linux-Host schützen; die Urteils-
tabellen sind das, was nur Ubuntu betrifft.Die Regel lebt im Kernel-Speicher und wird nicht auf die Festplatte persistiert. Ein
Mitigation-Pack darf nicht in Persistenzpfade schreiben (Units, cron), und eine
nftables-Include-Datei wird nur dort geladen, wo der nftables-Dienst der Distribution
aktiviert ist, was in diesen Umgebungen nicht einheitlich der Fall ist. Also: Nach
einem Neustart liest eine Erkennung die Regel als fehlend (rule_live=0,
persistent=0 in jeder Ergebniszeile) und das nächste Apply stellt sie wieder her.
Das erneute Ausführen des Apply nach Neustarts ist das Betriebsmodell, und die Ergebnis-
zeile behauptet nie etwas anderes.
Nur lesend, richtet sich in einem privaten temporären Verzeichnis ein, das es entfernt, und meldet:
uname -r, auf seine Paketversion abgebildet)
gegen Ubuntus feste Versionen pro Release und Flavour. Kein Fix veröffentlicht
für das Release der Box: no_fix. Ein fester Kernel veröffentlicht, aber nicht
laufend: vulnerable, mit restart_needed=1, wenn er installiert ist und
auf einen Neustart wartet (ein installierter Fix wird nie als fixed gemeldet).fixed mit workaround: true in
der Ergebniszeile, solange die Regel einen ungefixten Kernel abdeckt; schlicht fixed,
sobald der laufende Kernel gefixt ist.not_affected für Releases, die der Tracker freigibt, unknown für Releases
und Distributionen, die die Tabellen nicht abdecken.0 sauber (fixed, not_affected), 2 exponiert oder
unentschieden (no_fix, vulnerable, unknown: nie sauber), 1 der Lauf
selbst fehlgeschlagen, 130 unterbrochen.syn_options_mitigation/files/samp_common.py ist eine byte-genaue Kopie von
samp-common 1.0.4 (die dpkg-, rpm- und apk-Versions-
vergleiche, die Ergebniszeile, das Laden der Konfiguration). Sein sha256 steht in
samp.yaml, und tests/test_samp_pack.py schlägt fehl, wenn die Kopie abweicht. Niemals
hier bearbeiten; mit samp-commons scripts/vendor.py neu vendorn.samp/v<version> (dieses:
samp/v1.0.1), signiert mit einem hardwaregestützten Schlüssel. Das Substrat
importiert ein signiertes Tag, niemals einen Branch.Ein Skriptschritt, eine Ergebniszeile. Solange der laufende Kernel ungefixt ist,
lädt es die Regel; sobald ein gefixter Kernel läuft, entfernt es die Regel und
ihre Tabelle. Es bearbeitet keine Dateien außer dem Skript, der Bibliothek und der Konfiguration, die es
einsetzt (deklariert in samp.yaml touches), sodass die Backup-
liste der Ergebniszeile leer ist. Das Entfernen der Mitigation von Hand ist ein Befehl:
nft delete table inet samp_cve_2026_98432
ansible-playbook -i inventory play.yml # a play that runs the role
python3 syn_options_mitigator.py --config syn_options_config.yaml # detect
sudo python3 syn_options_mitigator.py --config syn_options_config.yaml --apply
Sobald Ubuntu feste Kernel veröffentlicht, füge die Versionen aus dem Tracker
in syn_options_fixed_versions in den Rollen-Defaults ein (die Work-in-Progress-
Versionen stehen dort bereits als Kommentar) und veröffentliche die Änderung als
nächstes signiertes Tag; die Erkennung beginnt dann, vulnerable/restart_needed
gegen diese zu melden, und das Apply entfernt die Regel von Maschinen, die in einen
festen Kernel neu starten.
python3 -m pytest tests/
Unit-Tests fälschen jeden externen Befehl; der Vertragstest
(tests/test_samp_pack.py, von samp-common) prüft das Manifest gegen die
Rolle, führt eine echte Erkennung aus einem Scratch-Verzeichnis aus und hält
den Apply-Eintrag an die Regeln für eine Ergebniszeile und needrestart.
MIT. Siehe LICENSE.
PRs und Verbesserungen sind willkommen -> bitte forken und einen Merge-Request einreichen.