CVE-2026-23339 Kernel Leak: nci_transceive Ownership Bug

  • Thread Author
CVE-2026-23339 is a small-looking Linux kernel bug with the kind of lifecycle mistake that kernel engineers never ignore: nci_transceive() takes ownership of an skb, then returns early on several error paths without freeing it. The result is a memory leak on the -EPROTO, -EINVAL, and -EBUSY exits, and the issue was concrete enough for kmemleak to catch during nci_dev selftests in NIPA. The bug was published on March 25, 2026, and the kernel.org record ties it directly to the upstream fix that now exists in stable form st glance, this is the sort of vulnerability that can be easy to dismiss: no remote code execution claim, no flashy privilege-escalation narrative, and no evidence of an immediate exploit chain. But that would be the wrong lesson to draw. In the Linux kernel, a leak in an owned buffer path is often a sign that error handling and object lifetime are drifting apart, and those are exactly the kinds of mistakes that become expensive under repeated retries, driver churn, and long-lived systems. The key phrase in the CVE text is that nci_transceive() “takes ownership” of the skb; once a caller hands that object over, the callee must either consume it or free it on failure
The bug also matterjust theoretical. The CVE description says the issue showed up in the nci/nci_dev selftest when NIPA occasionally hit the error path, and kmemleak then reported unreferenced objects of size 640 bytes. That makes the vulnerability more than a tidy-up patch. It becomes evidence that the code path is reachable, that the leak is reproducible under test conditions, and that repeated failures can accumulate memory pressure over time
This kind of CVE also fits a broader LinThe kernel documentation notes that CVEs are assigned after fixes are available and integrated into stable trees, and that the assignment process is intentionally cautious because many kernel bugs can become security-relevant depending on context. In other words, even when the immediate impact looks like a leak rather than a compromise primitive, the upstream project treats the issue as worthy of public tracking once the fix is real and backportable.
Another reason this case is interesting is the way it surfaced in the ecosystem. Microsoft’s Security Update Guide has been expanding its handling of security advisories and externally assigned CVEs, making Linux vulnerabilities visible inside a cross-platform enterprise workflow. That matters because a vulnerability like this may be technically narrow, but operationally it is part of a much larger patch-management picture: OEMs, cloud images, container hosts, appliance builds, and mixed Windows/Linux fleets all see the same identifier and must decide what it means for their environment.

Background​

NFC in the Linux kernel is one of those subsystems that rarely dominates headlines but still sits close to the hardware boundary where robustness matters most. The NCI layer, which stands for NFC Controller Interface, acts as a transport and management layer between the host and an NFC controller. That means it is responsible not only for moving data, but for handling state transitions, controller readiness, and the awkward reality of hardware that can be busy, unreachable, or temporarily inconsistent. In that kind of code, error paths are not edge cases; they are part of the expected operating model.
Kernel developers are especially careful about ownership rules in these paths because they determine who is responsible for cleanup. Once a function accepts ownership of a buffer, the caller can no longer safely free it unless the callee explicitly returns ownership. The CVE text says exactly that about nci_transceive(), and that makes the early-return leak particularly important. The code fail to complete the transaction; it fails to discharge the ownership contract on the way out
That is why memory leaks in kernel subsystems are not “just leaks.” In user space, a leak often disappears when the process exits. In the kernel, leaks can persist for the life of the system or until a driver reload, making them cumulative and potentially disruptive. If a selftest can repeatedly trigger a path that leaks an skb, then a real workload that encounters similar transient failures could do the same. The result may be gradual memory pressure, degraded availability, or difficult-to-diagnose instability.
The NVD record for this CVE was still marked for enrichment at publication time, which is normal for a newly assigned issue. The important source of truth is the kernel-side fix and the upstream stable references, which are already listed in the CVE entry. The CVE metadata confirms the publication date and the upstream e NVD had not yet assigned a CVSS score or final weakness classification
One subtle but important point is that this issue was discovered through testing infrastructure, not a public exploit report. That is a strength of the Linux ecosystem, not a weakness. A sanitizer or selftest finding a leak means maintainers can fix the bug before it becomes a field problem. The downside, of course, is that users may underestimate the operational significance of a bug that appears “only” to leak memory. In kernel land, repeated small mistakes are often how service degradation starts.

What the Bug Actually Does​

The technical defect is straightforward once you strip away the subsystem jargon. nci_transceive() receives an skb, attempts to transmit or process it, and then exits early on certain error conditions. On the -EPROTO, -EINVAL, and -EBUSY paths, it returns without freeing the skb, even though the function already owns it. The leak therefore happens not in the succfailure logic that is supposed to be the safety net
That distinction matters because error paths are often less exercised than the “happy path” in production. Developers spend a lot of effort making the nominal case fast and correct, but many real-world kernel bugs live in the bail-out code that only runs when hardware is misbehaving or the subsystem is under transient stress. Here, the CVE description suggests exactly that: the selftest occasionally hit the path when NCI_DATA_EXCHANGE clearing was in a bad state, and the function then leaked the skb. This is the kind of fault that hides until a system is already under strain.

Why ownership bugs are dangerous​

Ownership bugs are especially nasty because they look like ordinary return-value handling mistakes until they scale. A single leaked skb may be trivial. A hundred leaked skbs in a loop may still be survivable. But in kernel code, where allocations are constrained and fragmentation matters, repeated leaks can poison the available memory pool and change the behavior of unrelated subsystems. The bug may therefore present as a latency issue, a transient failure, or a memory reclaim problem long before anyone recognizes it as a CVE.
The presence of kmemleak in the record is a strong clue that the failure was not hypothetical. kmemleak is designed to identify objects that no longer have references but have not been freed, and the CVE description includes a concrete dump with object size, backtrace, and allocation chain. That makes the case stronger than an abstract static-analysis warning. It means the kernel actually observed the object surviving longer than it should have, and the stack trace location and the NFC send path
  • The bug is an ownership mismatch, not a parsing error.
  • The failure appears on early exits, not the main success path.
  • The leak is visible to kmemleak, which means it is real, not theoretical.
  • The impact is cumulative, because kernel allocations do not vanish on process exit.
  • The affected path belongs to a hardware-facing subsystem where retries are normal.

Why the specific errno values matter​

The fact that the leak happens on -EPROTO, -EINVAL, and -EBUSY tells you a lot about the shape of the bug. Those are exactly the kinds of errors a subsystem should be prepared to hit under controller mismatch, invalid state, or transient contention. In other words, the vulnerability lives in the code that should have been the most defensive. That is part of why this bug earned a CVE: the leak is triggered not by bizarre input, but by conditions the driver must anticipate as part of normal hardening.

The NCI and NFC Layer Context​

NFC drivers are not glamorous, but they are deeply stateful. The controller may be connected intermittently, the device may move between active and idle states, and the driver must mediate data exchange without assuming that every transaction will complete cleanly. In that environment, skb lifetime management becomes a first-class correctness property. A leaked skb is not just waste; it is a signal that the subsystem has lost track of a transaction object at a point where it should have been explicit about cleanup.
The kernel’s network-buffer abstraction is also deceptively simple. An skb can carry payload, metadata, fragmentation state, and bookkeeping tied to transport layers. That means a leak here is not identical to leaking a plain heap object of the same size. It is an object with context, and context is what makes kernel bugs reproducible in weird ways. The leak might only appear when a particular exchange state is in flight, when a retry collides with a controller transition, or when the selftest is exercising a sequence the developer did not mentally treat as failure-prone.

Why early error paths are the real test​

A robust kernel subsystem is usually judged by how it fails, not just by how it succeeds. If a device becomes busy, the code should release all owned objects and return control cleanly. If a protocol error occurs, the cleanup path must be at least as correct as the success path. nci_transceive() appears to have violated that discipline on a few return values, and the fix is therefore conceptually simple: free the skb branches
That simplicity should not be mistaken for triviality. The hardest part of these bugs is often recognizing that a function really owns the object all the way through its error handling. Once that contract is clarified, the patch becomes small. But the operational lesson remains large: ownership transfer needs to be documented and enforced, especially in kernel code where buffer accounting is tied to the stability of the whole machine.
  • Error handling must be treated as part of the primary design, not a cleanup afterthought.
  • A narrow subsystem can still create broad memory pressure if it leaks in a loop.
  • Hardware-facing code should assume busy, invalid, and protocol failures are routine.
  • The more stateful the driver, the more important explicit object ownership becomes.

Why This Became a CVE​

The Linux kernel project does not reserve CVEs only for dramatic exploits. The documentation explicitly says that CVEs are assigned to bugfixes identified in the stable process, and that the team is intentionally cautious because many kernel bugs can matter for security depending on how they are reached or combined with other issues. That policy explains why a leak in a core ownership path can get a public identifier even when no exploit technique is attached.
There is also a practical reason for public tracking. Enterprises need stable identifiers to map advisories across vendors, backports, and patch streams. Microsoft’s Security Update Guide has increasingly served as an aggregation point for advisories and CVEs, including issues that originate outside Microsoft itself. When a Linux kernel CVE appears there, it becomes part of the same triage queue as Windows, cloud, and third-party platform issues. That is a big deal for organizations trying to normalize vulnerability management.

CVE assignment without a CVSS score​

One thing readers should not over-interpret is the lack of a final NVD score at publication time. That does not mean the issue is unimportant; it means the record was still undergoing enrichment when the CVE was first posted. For teams doing real-world remediation, the fix status and affected code path are often more important than the numerical score on day one. A kernel memory leak in a hot error path can deserve attention even if it never receives a headline-grabbing severity rating.
The other reason CVEs like this matter is that they often point to a larger class of mistakes. Today the bug is a missing kfree_skb(). Tomorrow it could be a dangling reference, a double-free, or a lifecycle imbalance in the same subsystem. Security teams and kernel maintainers both prefer to catch the pattern while it is still small.

The Operational Impact​

In consumer terms, this vulnerability is likely niche. Most desktop users are not running NFC selftests or pushing the NCI path hard enough to notice a leak, and many systems may never exercise the relevant code at all. But that does not make the issue irrelevant. Kernel bugs are often most important in the long tail of embedded devices, appliance builds, and specialized hardware where updates are less frequent and workloads are more repetitive.
For enterprise environments, the calculation changes. If NFC support is present in a product line, a fleet image, or a device management stack, then a leak on repeated transient errors can become a service-quality issue. Even if the leak is modest per event, a controller that oscillates between busy and error states can turn that modest leak into an availability problem. A bug that looks like housekeeping on paper may surface as a support ticket that says “the device gets sluggish after retries” or “the driver recovers poorly after failed exchanges.”

Consumer vs enterprise exposure​

Consumer exposure depends heavily on whether the affected code is actually used. Laptops with NFC hardware, developer systems, and certain IoT or kiosk configurations could be more exposed than ordinary desktops. Enterprise exposure, by contrast, is driven by control and repetition: managed devices, scripted health checks, and test harnesses can generate exactly the sort of repeated error conditions that expose leaks. That is why a CVE like this can be low drama in consumer discussions and still matter a lot in operations rooms.
A useful rule of thumb here is that kernel leaks become important when they are reachable by:
  • repeated retries,
  • automation loops,
  • persistent services,
  • long-lived sessions, or
  • device-management workflows that don’t restart the kernel often.
If one of those patterns exists, the leak deserves real attention even if the bug seems “small.”

The Selftest and kmemleak Signal​

The CVE description makes the testing signal unusually concrete. It says the nci/nci_dev selftest hits the error path occasionally in NIPA because of issues clearing NCI_DATA_EXCHANGE, and kmemleak then detects the leak. That combinatings at once: the bug is reachable, the failure mode is reproducible under stress, and the kernel’s own instrumentation has enough visibility to prove the cleanup gap
That is a good example of why selftests matter. Security bugs are often discovered only after a maintenance or integration path begins to behave unpredictably under repeated automation. Selftests do not just validate functionality; they expose the assumptions that developers forgot they had made. In this case, the assumption appears to have been that the transaction object would always be freed elsewhere, even on a failure branch that had already taken ownership.

What the leak stack trace tells us​

The backtrace in the CVE record is valuable because it shows the leak originates from a normal skb allocation path through socket send helpers, NFC send allocation, and raw socket sendmsg processing. That makes the bug more relatable to kernel engineers: the leak is not in a bizarre custom allocator or an odd side channel, but in an ordinary flow from send request to transport object creation. When a bug appears in such a conventional path, it tends to be easier to backport and easier to reason about, which is good news for maintainers.
It also suggests that the fix surface is likely small. A narrow cleanup patch in early returns is exactly the sort of change st, because it reduces risk while closing the leak. That is one reason the CVE was quickly associated with multiple stable references in the record
  • The selftest provided a real-world reproducer.
  • kmemleak confirmed the object was unreferenced but not freed.
  • The allocation stack shows the bug sits in a normal transmit path.
  • The presence of a reproducible test case improves the odds of clean backports.
  • A small fix surface usually means lower regression risk.

Why This Matters Beyond NFC​

At the subsystem level, this is a reminder that kernel security is often about discipline, not drama. The most important bugs are not always the ones that crash loudly; they are the ones that quietly break resource accounting, ownership rules, or state transitions. That is especially true in device drivers and protocol layers, where the code has to cope with failure as a routine event.
At the ecosystem level, the Microsoft publication trail shows how Linux CVEs now live inside a mixed-vendor operations model. Enterprises do not care whether a bug came from kernel.org, Microsoft, a downstream distro, or a hardware vendor. They care about whether the issue is mapped correctly, whether the fixed build is available, and whether their scanning and patching tools understand the backport they actually run. That is why CVE records, advisory portals, and vendor-stable references matter together rather than separately

The broader lesson for kernel maintainers​

The broader lesson is simple: if a function takes ownership, every exit path must honor that ownership. The kernel has many helpers to make this easier, but they only work if the coding pattern is consistent. A leak on an early error path often means the code was written with success in mind and cleanup in theory. Mature kernel engineering demands the opposite: cleanup must be visible, deliberate, and obvious in every branch.

Strengths and Opportunities​

The good news is that this vulnerability appears to have been identified through internal testing and instrumentation rather than field exploitation. That is exactly the sort of discovery path defenders want, because it gives maintainers time to fix the bug before it becomes a persistent operational nuisance. It also means downstream vendors have a concrete patch lineage to follow rather than a vague report to interpret.
There are also broader opportunities here for maintainers and administrators alike. A bug like this is a good excuse to review error-path ownership in adjacent NFC code and to make sure selftests are exercising the right cleanup branches. In practical terms, the stronger the test coverage around early returns, the less likely the next leak will survive long enough to earn a CVE.
  • The fix is likely small and backportable.
  • The bug was found by testing and kmemleak, not exploitation.
  • The issue reinforces good ownership discipline in driver code.
  • The affected path is narrow enough to patch surgically.
  • The CVE improves tracking for enterprise vulnerability management.
  • The record provides a clean anchor for downstream advisories and backports.
  • The case reinforces the value of selftests in hidden failure paths.

Risks and Concerns​

The main risk is underestimation. Because this is a leak rather than a crash or an RCE primitive, some teams may treat it as low priority and postpone remediation. That can be a mistake in kernel land, where repeated failures can create memory pressure, service degradation, or confusing intermittent behavior that is hard to trace back to the root cause.
A second concern is that the affected code sits in a hardware-facing path. If NFC support is only rarely used, the bug may remain dormant in testing and only show up in production-like usage patterns. That means patch validation can be uneven, and organizations may wrongly assume they are safe because they do not actively use NFC today.
  • Memory leaks can look harmless until they repeat enough times to matter.
  • Error-path bugs are often less tested than success-path code.
  • Specialized hardware may hide exposure until deployment.
  • Downstream backports can vary across vendors and kernel branches.
  • Inventory gaps may cause teams to miss affected images or appliances.
  • A low-formality advisory can lead to delayed prioritization.
  • Reproducibility may depend on local controller behavior and retries.
One more concern is communication. Because NVD had not yet finalized enrichment at the time of publication, some consumers of vulnerability feeds may have only partial context at first glance. That can slow triage, especially in organizations that rely heavily on severity scoring instead of reading the source fix notes. For kernel issues like this, the fix details often tell the more usliminary rating ever will.

Looking Ahead​

The next thing to watch is downstream packaging. Stable references are already attached to the CVE record, which is a strong sign that the fix is in the normal Linux maintenance pipeline . The practical question for administrators is not whether the issue exists, but when the specific fixed build appears in their vendor’s kernel line.
It will also be worth watching whether adjacent NFC/NCI paths receive extra audit attention. Bugs like this rarely exist in a vacuum. When one function’s cleanup contract is weak, nearby functions often deserve a second look for the same pattern. That is especially true in driver subsystems where ownership and state transitions are tightly coupled.

What to watch next​

  • Vendor advisories that map the CVE to exact package versions.
  • Stable backports in long-term Linux branches.
  • Any follow-up patches in NFC/NCI error handling.
  • Whether selftests expand coverage of early-return paths.
  • Updates from enterprise scanners that improve fixed-build detection.
The broader security takeaway is that small kernel bugs are still kernel bugs. They deserve the same seriousness because they live at the foundation of the system, where repeated mistakes can become reliability issues long before they become obvious security incidents. This CVE is a good reminder that in Linux, as in every mature OS, the difference between a tidy cleanup path and a leak can be the difference between routine maintenance and a long-term operational headache.
For defenders, the smartest move is simple: verify the fixed build, carry the backport, and treat the issue as part of routine kernel hygiene rather than as a curiosity. That is usually how the best security outcomes happen in practice.

Source: NVD / Linux Kernel Security Update Guide - Microsoft Security Response Center