Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-98432 — Ansible role and Python script that detect Linux kernel exposure to CVE-2026-98432 and apply an nftables rule dropping inbound IPv4 SYNs carrying IP options. | Kitploit
Tools/GitHubGitHub/axisops/cve-2026-98432
Defensive ToolsVulnerability AnalysisScripting & AutomationConfiguration AuditingNetwork SecurityDevSecOpsMisconfigurationIncident Response
GitHubaxisops/cve-2026-98432

CVE-2026-98432

Ansible role and Python script that detect Linux kernel exposure to CVE-2026-98432 and apply an nftables rule dropping inbound IPv4 SYNs carrying IP options.

115 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
View Repository
Website
Share

CVE-2026-98432 — detect and mitigate the IPv4 SYN IP-options use-after-free

A use-after-free in the Linux kernel's IPv4 TCP code (CVE-2026-98432, CVSS 9.8): IPv4 options saved off an incoming SYN can be freed while another CPU is still reading them to build a SYNACK, because two destructor paths free them with a plain kfree() instead of waiting for an RCU grace period. The upstream fix is e3f33b0a1d89 ("ipv4: free inet_opt and ireq_opt after an RCU grace period").

As of 2026-10-29 no fixed kernel is released for any Ubuntu series. Every affected status on Ubuntu's tracker reads "work in progress" or plain vulnerable, and the page lists no mitigation. This pack is the mitigation.

What the mitigation is, and why it is sound

Both racing paths read ireq->ireq_opt, the IPv4 options the kernel saved from the incoming SYN (tcp_v4_save_options()): the SYNACK build reads them while child-socket teardown can free them, and request-socket migration (net.ipv4.tcp_migrate_req=1, or a BPF_SK_REUSEPORT_SELECT_OR_MIGRATE program) shares then frees the same options. When a SYN carries no IPv4 options, ireq_opt is NULL: there is nothing to free and nothing to read. We read the fix commit before relying on that; both halves start from a SYN that carried IPv4 options.

So the pack installs one nftables rule that drops inbound IPv4 TCP SYNs carrying IP options, in a table of its own so it never collides with Docker's, the substrate's or the distribution's rules:

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"
  }
}

Verified on a real kernel before release: an IPv4 SYN carrying options hits the counter and is dropped; a plain SYN passes untouched. TCP traffic almost never carries IP options (several option types are dropped by many networks as a matter of course, per RFC 7126), so the operational cost of the rule is close to nil.

What it does not cover

  • A legitimate client that sends SYNs with IP options (rare; mostly ancient source-routing and timestamp probes) will not connect while the rule is loaded. The counter on the rule says how often that happens.
  • Fragmented SYNs. The hook runs at priority -300, after conntrack's defragmentation (-400) wherever conntrack is loaded, so reassembled packets are matched. On a host with no conntrack, fragments are not reassembled at this hook; a fragmented SYN is pathological traffic and worth dropping by policy anyway, but this rule alone does not do it.
  • IPv6. This CVE is the IPv4 path; Ubuntu's page notes IPv6 is not affected by the first issue and tracks the similar IPv6 migration race separately.
  • Non-Ubuntu hosts. Version 1.0.0 reads Ubuntu's tracker only. Debian, RHEL-family and Proxmox kernels (Proxmox ships its own pve kernel, which Ubuntu's page does not cover) report unknown: read their advisories. The rule itself would protect any Linux host; the verdict tables are what is Ubuntu-only.

Persistence, deliberately not

The rule lives in kernel memory and is not persisted to disk. A mitigation pack must not write to persistence paths (units, cron), and an nftables include file is only loaded where the distribution's nftables service is enabled, which on these estates it is not uniformly. So: after a reboot, a detection reads the rule absent (rule_live=0, persistent=0 on every result line) and the next apply restores it. Re-running the apply after reboots is the operating model, and the result line never claims otherwise.

Detection

Read-only, stages itself in a private temporary directory it removes, and reports:

  • The running kernel (uname -r, mapped to its package version) against Ubuntu's fixed versions per release and flavour. No fix released for the box's release: no_fix. A fixed kernel released but not running: vulnerable, with restart_needed=1 when it is installed and waiting for a reboot (an installed fix is never reported fixed).
  • Whether the mitigation rule is live: fixed with workaround: true on the result line while the rule covers an unfixed kernel; plain fixed once the running kernel is fixed.
  • not_affected for releases the tracker clears, unknown for releases and distributions the tables do not cover.
  • Exit codes. 0 clean (fixed, not_affected), 2 exposed or undecided (no_fix, vulnerable, unknown: never clean), 1 the run itself failed, 130 interrupted.
  • Shared code. syn_options_mitigation/files/samp_common.py is a byte-for-byte copy of samp-common 1.0.4 (the dpkg, rpm and apk version comparisons, the result line, config loading). Its sha256 is in samp.yaml, and tests/test_samp_pack.py fails if the copy differs. Never edit it here; re-vendor it with samp-common's scripts/vendor.py.
  • Releases are SSH-signed annotated tags, samp/v<version> (this one: samp/v1.0.1), signed with a hardware-backed key. The substrate imports a signed tag, never a branch.

The apply

One script step, one result line. While the running kernel is unfixed, it loads the rule; once a fixed kernel is running, it removes the rule and its table. It edits no files beyond the script, library and config it deploys (declared in samp.yaml touches), so the result line's backup list is empty. Removing the mitigation by hand is one command:

nft delete table inet samp_cve_2026_98432

Running it standalone

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

When Ubuntu releases fixed kernels, paste the versions from the tracker into syn_options_fixed_versions in the role defaults (the work-in-progress versions are already there in a comment) and release the change as the next signed tag; detection then starts reporting vulnerable/restart_needed against them, and the apply removes the rule from boxes that reboot into a fixed kernel.

Tests

python3 -m pytest tests/

Unit tests fake every external command; the contract test (tests/test_samp_pack.py, samp-common's) checks the manifest against the role, runs a real detection from a scratch directory and holds the apply entry to the one-result-line and needrestart rules.

License

MIT. See LICENSE.

Contributing

PRs and improvements welcome -> please fork and submit a merge request.

Download Tool