On June 24, 2026 the Linux kernel CVE stream did something it does more and more often: it published 219 CVEs in a single day — and not one of them carried an official NVD severity score. Most are medium or low. But sitting in that wall of unscored line items is CVE-2026-52943, a use-after-free deep in the kernel's core networking code that the upstream maintainers themselves call "reliably exploitable" — "full root privilege escalation from an unprivileged local user on a default kernel configuration." When 219 entries land at once with an empty severity column, that is exactly the kind of thing that coasts past triage.
CONFIG_RDS_TCP build option and
shipped as an rds module that, as of 2026, most mainstream
distributions blacklist by default. So whether this 8.4 is your week's
emergency or a
documented "not affected" doesn't come from the score — it comes from
one concrete check: is that config option built, and is the module
present and reachable, in the kernel you actually run?
Why a bug this serious is easy to miss
The dangerous part here is not just the bug — it's the company it keeps. NVD scoring routinely lags days to weeks behind publication, so for a window that can stretch into weeks, all 219 of today's kernel CVEs show up with a blank CVSS field. Triage that sorts by severity has nothing to sort on, and a reliable local-root primitive looks identical to a cosmetic typo fix in that list.
CVE-2026-52943 is the case in point. On the numbers we can
compute it sits at 8.4 / High — one of only a
handful in the batch an unprivileged user can turn into root — yet
it carries the same empty official score as the hundreds around it. The
one real limitation works in defenders' favour: it is
local-only (AV:L). There is no remote or
wormable trigger, so the whole threat reduces to whether untrusted code
can run on the machine at all. On a multi-tenant host, a container
platform, or anything running customer code, assume yes; on a sealed
single-purpose appliance, often no.
The 8.4 / High figure is a KernelScan provisional assessment; NVD had not
scored the CVE at publication time. The vector we used is
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
A two-line fix for a bug that hid for almost a decade
The striking thing about this vulnerability is how small the fix is. The kernel keeps a running tally of how many parts of the system are still using a shared "zero-copy" object — a little ticket the network stack hands out when an application sends data with the zero-copy flag, so the kernel knows when it is finally safe to reclaim the memory. When the tally reaches zero, the object is freed. Two helper routines that relocate network buffers copied the pointer to that ticket into a second buffer but forgot to add one to the tally. The kernel then believed one fewer user was holding the ticket than really was — so it freed the ticket while a buffer still in flight was pointing straight at it. That dangling pointer is the use-after-free.
The entire correction is a two-line snippet, applied identically in each of the two helpers:
if (skb_zcopy(skb))
net_zcopy_get(skb_zcopy(skb));
In plain terms: "if this buffer carries a zero-copy ticket, add one to the tally." That is the whole fix.
So how does a one-line oversight survive for nearly a decade? The helper routines were added back in 2016 (kernel 4.7) for one obscure corner of the networking stack, and the later zero-copy sending feature brought a rule with it: any routine that copies a buffer's bookkeeping must also bump the tally. The common, heavily-used copy routine was taught that rule — but its rarely-travelled twin, the one in this report, was overlooked. It stayed hidden because it is a missing line, not a wrong one: nothing looks broken when you read the code, the neighbouring routine right beside it looks correct, and an absence is invisible unless you are specifically auditing every place the tally ought to be touched. On top of that, the crash only lines up under a very specific sequence of events, and the sanitizer that catches it only fires if the freed object is actually used again. For almost a decade the right combination simply never ran under the right microscope — until someone did a systematic audit of the zero-copy bookkeeping (with AI assistance, the commit notes) and spotted the one copy site still missing the rule.
You can't delete the code — so the question is whether you can reach it
Most kernel CVEs live in a driver or feature you can simply not compile in. This one doesn't: it sits in the core buffer-management code every networked Linux system is built on. There is no config switch that removes it short of removing networking. So at the code level it lands on affected for essentially every kernel in range (every release from 4.7 up to the fixed versions below), and the version-and-config filter that usually narrows a CVE can't narrow this one.
But "the vulnerable code is present" is not the same as "an attacker can
reach it." The only path into the buggy routines is a kernel helper called
pskb_extract(), and across current kernels only two callers
reach it: the RDS-over-TCP socket transport
(CONFIG_RDS_TCP) and the IPsec IPTFS mode
(CONFIG_XFRM_IPTFS). IPTFS has to be stood up through IPsec,
which requires CAP_NET_ADMIN — a privileged operation
— so an unprivileged attacker can't establish that path on their own.
That leaves exactly one unprivileged way in: RDS.
And here is the part worth acting on. Almost nobody deliberately uses RDS
(a niche datacenter messaging protocol), and historically the worry was
on-demand autoload: opening an AF_RDS socket asks the
kernel to pull in rds.ko — the same pattern behind a
decade of kernel privilege-escalation bugs (DCCP, TIPC, earlier RDS flaws).
The good news in 2026 is that most mainstream distributions took that lesson:
they ship RDS (alongside other rare protocols) on their
default module blacklist, so on a stock install of those
distros the module is not autoloaded and an unprivileged
AF_RDS socket simply fails to bring it in. That narrows "exploitable on a default install"
considerably — the realistic exposure is systems that actually use RDS,
older or minimal images that predate or omit those blacklists, and anything
an admin has explicitly re-enabled. It also reframes the upstream phrase
"default kernel configuration": the vulnerable code is built into
every distribution kernel (the kernel's own defconfig doesn't even build
RDS), but whether an unprivileged user can reach it comes down to
that module policy.
CONFIG_RDS_TCP in your kernel config
(grep CONFIG_RDS_TCP /boot/config-$(uname -r)); if it is unset,
nothing unprivileged reaches the bug and a minimal, appliance, or hardened
build that never enabled RDS is effectively not affected, 8.4 or not.
Is the module present and reachable? — if RDS is built as a
module (=m), is rds.ko actually shipped in your
kernel package, and does your distribution leave it loadable or blacklist
it? A module that isn't there, or that an unprivileged process can't bring
in, is a path that doesn't exist. Who could even run the trigger?
— the attack needs untrusted local code on the box, which a
multi-tenant host or container platform has and a sealed single-purpose
appliance usually doesn't. Enough "no"s and the headline number is just a
number: that presence-and-reachability answer, not the CVSS, is what tells
you whether you are racing a clock or patching on the normal cycle.
What might the exploit look like?
We don't have the proof-of-concept; the following is informed speculation from the crash fingerprint published in the commit.
Our read: this is almost certainly not a malicious packet arriving from the network — nothing in the bug is reachable from outside the machine. And, perhaps surprisingly, it is probably not a classic race condition either. It is a deterministic accounting error, and that distinction is the whole reason the author can call it "reliably exploitable": timing races are flaky and often fail, but a miscount happens the same way every single time.
The likely shape is a small unprivileged program that:
- opens the special sockets that route through the vulnerable path (the crash trace points straight at RDS-over-TCP, talking to itself across the loopback interface);
- sends data with the zero-copy flag, so the kernel attaches one of those tickets;
- steers those buffers through the relocate routine that quietly shares the ticket without bumping the tally;
- then frees buffers and drains the socket's error queue so the tally hits zero and the ticket is freed — while another in-flight buffer still points at it;
- immediately refills that freed slice of memory with attacker-shaped data, and waits for the kernel to follow the now-dangling pointer — which carries a function pointer the attacker now controls — to hijack execution and climb to root.
In one line: a local, deterministic, heap-grooming use-after-free over loopback — no external traffic, no flaky timing window. Which is also why "no public PoC yet" is only a brief comfort: the recipe is mostly legible from the fix and the crash trace.
Which kernels are fixed, and where
The fix was authored by Minh Nguyen, reviewed by Willem de Bruijn (the
MSG_ZEROCOPY maintainer), and merged via netdev in late May
2026 before being backported to every maintained branch. We confirmed
each backport commit resolves to the version listed here in our local
mirror of the stable trees:
| Stable branch | First fixed version |
|---|---|
| 5.10 | 5.10.259 |
| 5.15 | 5.15.210 |
| 6.1 | 6.1.176 |
| 6.6 | 6.6.143 |
| 6.12 | 6.12.93 |
| 6.18 | 6.18.35 |
| 7.0 | 7.0.12 |
| mainline | 7.1 |
If you run a kernel on one of these branches at or above the listed version, you already have the fix. Anything older, back to 4.7, is affected.
Mailing-list and PoC status
This went through the normal kernel patch process rather than a coordinated security-list disclosure: the patch was posted and reviewed on netdev/linux-kernel in late May 2026, then merged and backported. It was not discussed as an advisory on oss-security.
A working proof-of-concept demonstrably exists — the KASAN trace in
the commit names the triggering task poc — but, as of
publication, no public PoC or exploit has been released.
That is cold comfort, though: the bug is a one-line missing reference and
the published fix is effectively the roadmap. Anyone can diff the carve
helpers against pskb_expand_head() and see it. The window in
which "no public PoC" is reassuring is likely short.
The real lesson: presence beats severity
CVE-2026-52943 is worth patching, but the story it tells is bigger than one CVE. Kernel vulnerabilities increasingly arrive in big unscored batches, and this one was no anomaly — the days around it tell the real story:
| Day | New kernel CVEs |
|---|---|
| Sat, Jun 20 | 0 |
| Sun, Jun 21 | 1 |
| Mon, Jun 22 | 0 |
| Tue, Jun 23 | 0 |
| Wed, Jun 24 | 219 |
| Thu, Jun 25 | 147 |
| Fri, Jun 26 | 47 (so far) |
Three near-silent days, then 219, 147 and 47 back to back — more than 400 kernel CVEs in 72 hours, every one still unscored by NVD as it landed. Daily counts updated June 26, 2026.
The official severity that most programs triage on simply isn't there when the batch drops — and even once a number lands, it describes the bug, not your exposure: an 8.4 "reliable local root" in code every kernel ships sounds identical whether the path that reaches it is compiled into your build or was never enabled at all. The signal that separates "patch this week" from "note and move on" isn't the score; it's two concrete questions about your own kernel: is the vulnerable code — and the config option and module that reach it — actually present in my build, and can the attacker it needs even exist on my device?
That is the whole reason KernelScan exists. Upload your
.config, pick the version and architecture, and it answers the
presence question for you — which symbols are built, which CVE paths
they actually reach — while your product's security factors decide
whether an unprivileged local attacker is even part of your threat model.
For a kernel that never builds CONFIG_RDS_TCP — an
appliance, a hardened image, or any stock distribution that keeps the module
blacklisted — an 8.4 reliable-root headline becomes a defensible,
documented "not affected"; for a build that ships and exposes RDS, it is the
week's priority. Same CVE, opposite answers — and the deciding factor
was never the empty box NVD shows today, but whether the vulnerable path is
present at all.