There is a severe TCP Use-After-Free: CVE-2026-98432 without proper mitigation via stock Linux Kernels from Ubuntu. However Ubuntu has published an advisory. Here is a script that applies temporary mitigation on Ubuntu
This script is based on the advisory : https://web.archive.org/web/20261103091553/https://ubuntu.com/security/CVE-2026-98432
How to run:
bash cve-2026-98432-mitigation.sh apply
The script:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Mitigation for CVE-2026-98432 (Linux kernel IPv4 TCP ireq_opt use-after-free). | |
| # Drops inbound IPv4 TCP packets that carry IP options, using a private | |
| # nftables table. This REDUCES risk; it is not a fix. Install the patched | |
| # kernel as soon as it is available and reboot. | |
| # | |
| # Usage: sudo ./cve-2026-98432-mitigation.sh {apply|unapply|status} | |
| # | |
| # Env: WITH_FORWARD=1 also drop such packets on the forward hook (protects | |
| # containers/VMs behind this host; breaks IP options | |
| # on transit traffic if this host is a router). | |
| # | |
| # Persistence uses a dedicated systemd unit that loads ONLY our own table, | |
| # so /etc/nftables.conf (and its "flush ruleset") is never touched and other | |
| # firewalls (ufw, firewalld, Docker, libvirt) are not disturbed. | |
| set -euo pipefail | |
| umask 022 | |
| CVE="cve-2026-98432" | |
| TABLE="cve_2026_98432" | |
| RULE_FILE="/etc/${CVE}.nft" | |
| UNIT_NAME="${CVE}-mitigation.service" | |
| UNIT_FILE="/etc/systemd/system/${UNIT_NAME}" | |
| NFT_CONF="/etc/nftables.conf" | |
| LEGACY_INCLUDE="include \"${RULE_FILE}\"" | |
| WITH_FORWARD="${WITH_FORWARD:-0}" | |
| die() { echo "Error: $*" >&2; exit 1; } | |
| warn() { echo "Warning: $*" >&2; } | |
| [ "${EUID}" -eq 0 ] || die "run as root (use sudo)." | |
| NFT_BIN="$(command -v nft || true)" | |
| [ -n "${NFT_BIN}" ] || die "nftables (nft) is not installed or not in PATH." | |
| TMP_FILES=() | |
| cleanup() { [ "${#TMP_FILES[@]}" -gt 0 ] && rm -f "${TMP_FILES[@]}"; return 0; } | |
| trap cleanup EXIT | |
| # Sets $TMP (no command substitution, so TMP_FILES is updated in this shell). | |
| TMP="" | |
| mktmp() { TMP="$(mktemp)"; TMP_FILES+=("${TMP}"); } | |
| have_systemd() { command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; } | |
| # Single-instance lock | |
| exec 9>"/run/${CVE}-mitigation.lock" | |
| flock -n 9 || die "another instance is already running." | |
| render_rules() { | |
| # add+delete makes the file idempotent: re-loading replaces the table | |
| # instead of appending a duplicate rule. | |
| cat <<EOF | |
| add table inet ${TABLE} | |
| delete table inet ${TABLE} | |
| table inet ${TABLE} { | |
| chain input { | |
| type filter hook input priority -310; policy accept; | |
| ip protocol tcp ip hdrlength > 5 counter drop | |
| } | |
| EOF | |
| if [ "${WITH_FORWARD}" = "1" ]; then | |
| cat <<EOF | |
| chain forward { | |
| type filter hook forward priority -310; policy accept; | |
| ip protocol tcp ip hdrlength > 5 counter drop | |
| } | |
| EOF | |
| fi | |
| echo "}" | |
| } | |
| render_unit() { | |
| cat <<EOF | |
| [Unit] | |
| Description=CVE-2026-98432 mitigation (drop IPv4 TCP packets with IP options) | |
| DefaultDependencies=no | |
| After=local-fs.target nftables.service | |
| PartOf=nftables.service | |
| Wants=network-pre.target | |
| Before=network-pre.target | |
| [Service] | |
| Type=oneshot | |
| RemainAfterExit=yes | |
| ExecStart=${NFT_BIN} -f ${RULE_FILE} | |
| ExecStop=-${NFT_BIN} delete table inet ${TABLE} | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| } | |
| table_loaded() { "${NFT_BIN}" list table inet "${TABLE}" >/dev/null 2>&1; } | |
| apply_mitigation() { | |
| echo "Applying ${CVE} mitigation..." | |
| # 1. Render to a temp file and validate BEFORE touching anything on disk. | |
| local tmp; mktmp; tmp="${TMP}" | |
| render_rules > "${tmp}" | |
| "${NFT_BIN}" -c -f "${tmp}" || die "rule validation failed; nothing changed." | |
| # 2. Install atomically (no clobber of a good file with a bad one). | |
| install -m 0644 -o root -g root "${tmp}" "${RULE_FILE}" | |
| echo "Installed ${RULE_FILE}" | |
| # 3. Load into the live ruleset (idempotent). | |
| "${NFT_BIN}" -f "${RULE_FILE}" | |
| table_loaded || die "table ${TABLE} not present after load." | |
| echo "Live rule loaded." | |
| # 4. Boot persistence via our own unit. | |
| if have_systemd; then | |
| local utmp; mktmp; utmp="${TMP}" | |
| render_unit > "${utmp}" | |
| install -m 0644 -o root -g root "${utmp}" "${UNIT_FILE}" | |
| systemctl daemon-reload | |
| systemctl enable "${UNIT_NAME}" >/dev/null \ | |
| || die "live rule is active, but enabling ${UNIT_NAME} failed (no persistence)." | |
| echo "Persistence enabled (${UNIT_NAME})." | |
| else | |
| warn "systemd not detected: rule is live but will NOT survive a reboot." | |
| fi | |
| if grep -Fxq "${LEGACY_INCLUDE}" "${NFT_CONF}" 2>/dev/null; then | |
| echo "Note: legacy include found in ${NFT_CONF}; harmless (rule file is idempotent)." | |
| fi | |
| warn "this is a partial mitigation. Install the kernel fix when released: uname -r = $(uname -r)" | |
| [ "${WITH_FORWARD}" = "1" ] || \ | |
| echo "Note: forwarded traffic (containers/VMs behind this host) is NOT covered; use WITH_FORWARD=1 if needed." | |
| echo "Mitigation applied." | |
| } | |
| unapply_mitigation() { | |
| echo "Removing ${CVE} mitigation..." | |
| if have_systemd && [ -f "${UNIT_FILE}" ]; then | |
| systemctl disable --now "${UNIT_NAME}" >/dev/null 2>&1 || true | |
| rm -f "${UNIT_FILE}" | |
| systemctl daemon-reload | |
| echo "Removed ${UNIT_NAME}." | |
| fi | |
| if table_loaded; then | |
| "${NFT_BIN}" delete table inet "${TABLE}" | |
| echo "Removed live table inet ${TABLE}." | |
| else | |
| echo "Live table not present." | |
| fi | |
| # Clean up a legacy include from the vendor/old-script method, if present. | |
| if [ -f "${NFT_CONF}" ] && grep -Fxq "${LEGACY_INCLUDE}" "${NFT_CONF}"; then | |
| local bak t | |
| bak="${NFT_CONF}.bak.$(date +%Y%m%d%H%M%S)" | |
| mktmp; t="${TMP}" | |
| cp -p "${NFT_CONF}" "${bak}" | |
| grep -Fxv "${LEGACY_INCLUDE}" "${NFT_CONF}" > "${t}" || true | |
| cat "${t}" > "${NFT_CONF}" # preserves mode/owner/symlink | |
| echo "Removed legacy include from ${NFT_CONF} (backup: ${bak})." | |
| fi | |
| rm -f "${RULE_FILE}" | |
| echo "Mitigation removed." | |
| } | |
| status() { | |
| echo "Kernel: $(uname -r)" | |
| if table_loaded; then | |
| "${NFT_BIN}" list table inet "${TABLE}" | |
| else | |
| echo "Table inet ${TABLE}: NOT loaded" | |
| fi | |
| if have_systemd; then | |
| echo "Boot persistence: $(systemctl is-enabled "${UNIT_NAME}" 2>/dev/null || echo not-enabled)" | |
| fi | |
| } | |
| case "${1:-}" in | |
| apply) apply_mitigation ;; | |
| unapply) unapply_mitigation ;; | |
| status) status ;; | |
| *) echo "Usage: $0 {apply|unapply|status}" >&2; exit 1 ;; | |
| esac |


















