KernelScan.io

HIGH Introduced in 6.12

tcp ReqskTimer UAF

CVE-2026-99270

CVSS 8.1 / 10.0 NVD

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

KernelScan AI8.1HIGH

01

In the Linux kernel, the following vulnerability has been resolved: tcp: Fix potential UAF in reqsk_timer_handler(). When TCP socket migration fails at inet_ehash_insert() in reqsk_timer_handler(), we jump to the no_ownership: label and free the new reqsk immediately with __reqsk_free(). Thus, we must stop the new reqsk's timer before jumping to the label, but the timer might be missed since the cited commit, resulting in UAF. As we are in the original reqsk's timer context, we can safely call timer_delete_sync() for the new reqsk. Let's pass false to __inet_csk_reqsk_queue_drop() to stop the new reqsk's timer.

02

Engine v0.10.0

Risk summary

Remote-reachable only on servers that opt into TCP listener migration (`net.ipv4.tcp_migrate_req=1` or a `BPF_SK_REUSEPORT_SELECT_OR_MIGRATE` program on an SO_REUSEPORT group) **and** close a listener while handshakes are pending; default systems never execute the vulnerable branch, and the realistic remote outcome is a kernel panic, not RCE. The more practical risk is **local**: an unprivileged user with user namespaces can enable the per-netns sysctl, own both listeners and drive the race over loopback, making this a plausible privilege escalation on hosts that allow unprivileged userns. No long-term kernel has the fix as of 2026-11-04 (fixed in 7.1 and later); set `tcp_migrate_req=0` and restrict unprivileged user namespaces.

Affectednet/ipv4/inet_connection_sock.c (reqsk_timer_handler, TCP listener migration)

Vulnerability analysis

Type: use-after-free of a cloned `request_sock` (`nreq`) whose `rsk_timer` is still armed.

Root cause: in `reqsk_timer_handler()` the migration branch (listener no longer `TCP_LISTEN`, `reuseport_migrate_sock()` picks a new listener) clones the req and re-arms the clone's timer with `mod_timer()`. If `inet_ehash_insert(nreq, oreq)` then fails because `oreq` was unhashed concurrently (final ACK / RST won the `own_req` race on another CPU), the code calls `__inet_csk_reqsk_queue_drop(sk_listener, nreq, true)` and jumps to `no_ownership:` which `__reqsk_free(nreq)`. `from_timer=true` skips `timer_delete_sync()`, so the freed object stays linked in the timer wheel and its handler later runs on freed memory.

Real introducer: e8c526f2bdf1 ("tcp/dccp: Don't use timer_pending() in reqsk_queue_unlink()", v6.12-rc4, backported to 5.15.170 / 6.1.115 / 6.6.59 / 6.11.6). Before it, the drop used `timer_pending() && del_timer_sync()`, and the just-armed, CPU-pinned `nreq` timer was always pending, so it was deleted. The `Fixes:` tag (83fccfc3940c, 4.2) and the 5.14 lock (c905dee62232, migration added) are both broader than real exposure.

Fix (97c8a3c1f73d, v7.1-rc4): pass `from_timer=false` for `nreq`; safe because we run in `oreq`'s timer, not `nreq`'s.

Preconditions: SO_REUSEPORT group + migration enabled (sysctl default 0, per-netns, writable by userns root) + listener close during pending handshakes + a microsecond race between the timer and ACK processing on another CPU. The `request_sock_TCP` slab is `SLAB_TYPESAFE_BY_RCU`, so attacker SYNs readily reclaim the slot as another reqsk (refcount/timer-list corruption), but control-flow hijack needs cross-cache reclaim plus a KASLR bypass, which is unrealistic remotely.

03

BranchIntroducedFixed inPatch commit
5.155.15.170—
6.16.1.115—
6.116.11.6—
6.186.126.18.6197c8a3c1f73d
6.66.6.59—
mainline6.127.197c8a3c1f73d

04

State of the newest release of each Civil Infrastructure Platform SLTS tree, from CIP's own fix records.

CIP treeState
cip/6.12Affected — no CIP fix yet (latest 6.12.114-cip34)
cip/6.1Affected — no CIP fix yet (latest 6.1.190-cip62)
cip/6.1-rtAffected — no CIP fix yet (latest 6.1.189-cip61-rt32)