Skip to main content

TECH VEDA

Linux kernel & Device drivers starts on 24th Oct 2026 enrollingCorporate on-site training - Submit proposal Pick your modulesSharpen your kernel skills: deep dives, drivers, Yocto, CVEs, careers โ€” updated daily. Read the blog โ†’Embedded Linux fast track starts 30th sept 2026 enrollingEmbedded Linux Mastery track starts 30th sept 2026 enrollingLinux systems engineering starts 30th sept 2026 enrolling
Insights

Linux Stable Kernel Updates: How to Tell Whether a CVE Fix Exists for Your Series

A stable kernel update lists which series a CVE was fixed in. Read the introduced version too, or an unfixed defect reads as a clean result.

Linux Stable Kernel Updates: How to Tell Whether a CVE Fix Exists for Your Series

When you filter a stable kernel update down to its CVE-referenced fixes, the next question is whether a fix exists for the series your product ships, and the announcement answers it in two lines rather than one. The “Issue introduced in” line tells you whether you are affected; the “fixed in” lines tell you which series have a patch. For an embedded-relevant CVE these frequently do not overlap: the bug is in your series and the fix is not. This article shows how to read those two lines, and works through a September 2026 CVE where the fix exists only for 7.2.y and cannot be cherry-picked into any longterm series.

An earlier piece here argued that patch-by-patch review of a stable kernel update is no longer a process a team can perform, and that the workable replacement is a filter: reduce the release to the files your configuration builds, then look closely at the CVE-referenced fixes. This piece is about what you find after applying it, because the CVE record answers a narrower question than most teams read it as answering.

Scope: any product pinned to one of the six series carried as longterm โ€” 5.10, 5.15, 6.1, 6.6, 6.12, 6.18 โ€” or to a vendor BSP forked from one. The examples are real CVE announcements from 25 to 29 September 2026, and every code claim below was checked by reading the file at the stable tag.

The two lines in a stable kernel update that decide your answer

Every CVE that arrives with a stable kernel update carries a section like this. The example is CVE-2026-98121, a null-pointer dereference in the msc313e watchdog driver’s power-management callbacks:

Issue introduced in 5.14 with commit e9800b7994642a794afd4894f072541c14277ce8 and fixed in 6.12.111 with commit b02f902fe4b59d65f74a25c4523a75453bd3f808
Issue introduced in 5.14 with commit e9800b7994642a794afd4894f072541c14277ce8 and fixed in 6.18.53 with commit 744b25040d8206f7925b8ba0be5edf93fa4bf81e
Issue introduced in 5.14 with commit e9800b7994642a794afd4894f072541c14277ce8 and fixed in 7.2.7 with commit 6495dc16e635356fd2b7535dcbf9b6779de4e753
Issue introduced in 5.14 with commit e9800b7994642a794afd4894f072541c14277ce8 and fixed in 7.3-rc3 with commit e3eceb76515910746e6268c4e4ac1c07516ebd7b

Two independent facts are encoded there. The introduced version, 5.14, says which series contain the bug: every series that branched after it, which here means 6.1, 6.6, 6.12 and 6.18. The fixed list names the series that have a patch: 6.12, 6.18 and 7.2. Subtract one from the other. A product on 6.6 or 6.1 is affected by CVE-2026-98121 and had no fix available when it was announced.

That the fix is a different commit in each series is not incidental. The kernel’s CVE process document states that assignment happens “after a fix is available and applied to a stable kernel tree, and it will be tracked that way by the git commit id of the original fix”. The record is built around commits, one per series.

Absence of your series means two opposite things

The mistake that follows is treating a missing series as a clean result. Sometimes it is. Four CVEs from one week of stable kernel updates, side by side, show why you cannot tell without the introduced version:

CVESubsystemIntroducedFixed inWhat 6.6.y should conclude
CVE-2026-100079USB Type-C UCSI, debugfs teardown6.66.6.157, 6.12.110, 6.18.52, 7.2.6Affected, and fixed. Take the update.
CVE-2026-98093ASoC fsl_micfil, mclk balance6.136.18.53, 7.2.7Not affected. The code postdates 6.6.
CVE-2026-98121msc313e watchdog, PM callbacks5.146.12.111, 6.18.53, 7.2.7Affected, no fix listed.
CVE-2026-98131stmmac, DMA mapping leak in TSO4.77.2.7Affected, no fix listed.

CVE-2026-98093 is absent from 6.6 because the affected code was written in 6.13. CVE-2026-98121 is absent because nobody has backported the fix. Both look identical in a report that lists only fixed versions, and they call for opposite actions: one is closed, the other is an open defect with no patch you can apply.

The announcement is explicit that this is a moving target: “Unaffected versions might change over time as fixes are backported to older supported kernel versions.” The same scan next month can give a different answer for the same CVE and the same kernel, with nothing changed on your device.

A fix that exists only for 7.2, and the code that proves it

The last row is worth following to the end, because it is the ordinary case rather than an unusual one. CVE-2026-98131 is a DMA mapping leak in stmmac_tso_xmit(), in the driver for the Synopsys DesignWare Ethernet MAC. That driver matters out of proportion to its name: the stmmac directory in 6.6.157 builds 23 platform glue drivers, among them dwmac-imx, dwmac-rk, dwmac-stm32, dwmac-meson8b, dwmac-sun8i, dwmac-mediatek, dwmac-qcom-ethqos, dwmac-tegra and dwmac-starfive.

The bug was introduced in 4.7 and the announcement lists one stable fix, in 7.2.7. Rather than take the implication on trust, read the error path in each longterm series. This is the tail of stmmac_tso_xmit() in 6.6.157:

dma_map_err:
	dev_err(priv->device, "Tx dma map failed\n");
	dev_kfree_skb(skb);
	priv->xstats.tx_dropped++;
	return NETDEV_TX_OK;
}

The function reaches that label after it has already called dma_map_single() for the headers and once per fragment. It frees the socket buffer, counts a drop, and returns. It does not unmap anything. Those five lines are byte-identical in 6.1.188, 6.6.157, 6.12.111 and 6.18.54, so the defect is present unchanged in every longterm series a product would ship today.

Now the fix, as it landed in 7.2.7. This is the error path it replaces the above with:

error_dma_unmap:
	for (;;) {
		desc = stmmac_get_tx_desc(priv, tx_q, first_entry);
		stmmac_release_tx_desc(priv, desc, priv->descriptor_mode);
		stmmac_free_tx_buffer(priv, &priv->dma_conf, queue,
				      first_entry);
		if (first_entry == entry)
			break;

		first_entry = STMMAC_NEXT_ENTRY(first_entry,
						priv->dma_conf.dma_tx_size);
	}
error:
	dev_err(priv->device, "Tx dma map failed\n");
	dev_kfree_skb(skb);
	priv->xstats.tx_dropped++;
	return NETDEV_TX_OK;
}

Why nobody backported it

Three of the symbols in that loop do not exist in any longterm series. Grepping the same file at each tag, priv->descriptor_mode, stmmac_get_tx_desc() and stmmac_set_tx_skb_dma_entry() each appear zero times in 6.1.188, 6.6.157, 6.12.111 and 6.18.54, and appear ten, fifteen and six times in 7.2.6, before the fix. They arrived with a descriptor-handling rework, which is a feature change and so not a candidate for a stable tree.

A git cherry-pick of commit e85adaac3dc6 into a 6.6-based tree therefore does not produce a merge conflict an engineer resolves in an afternoon. It produces a file referencing three identifiers the tree has never heard of, and the build fails. The fix also restructures the function beyond its error path: it threads a new entry variable through stmmac_tso_allocator(), changing that helper’s signature.

The stable rules anticipate this. Of the three ways to get a change into a stable tree, the third exists “for cases where a mainlined patch needs adjustments to apply in older series (for example due to API changes)”, and the rules require any stable patch to be “obviously correct and tested” and under 100 lines with context. A rewritten error-unwind loop for a series whose descriptor helpers differ is not obviously correct by inspection. Closing this hole in 6.6.y needs a different patch, written and tested by somebody who knows the driver.

The case where the bug arrived in your LTS by backport

A third shape defeats reasoning from branch dates. CVE-2026-97979, in the Intel ice driver, lists its versions like this:

Issue introduced in 6.2 with commit 16dfa49406bc5e1f4cbb115027cbd719d7e6c930 and fixed in 6.12.111 with commit 44cdd6b7e036303f7fecf841cf23c05a4a4faf2d
Issue introduced in 6.2 with commit 16dfa49406bc5e1f4cbb115027cbd719d7e6c930 and fixed in 6.18.53 with commit f5463bc124c0d6f922e272336584730c5c61c4f1
Issue introduced in 6.2 with commit 16dfa49406bc5e1f4cbb115027cbd719d7e6c930 and fixed in 7.2.7 with commit d6f38fb12069fb1edf762962b5fcf3f42d643b47
Issue introduced in 6.1.95 with commit a388961be5ed8ee037ac68220e389bc4e9339a39

The last line has no “and fixed in” clause. The bug was introduced into the 6.1 longterm series at 6.1.95, by a backport, and as of this announcement it is not fixed there. A team that reasoned “6.1 branched before 6.2, so we predate this bug” would be wrong, and the record says so on its own last line. This is what a defect entering an LTS through the backport stream looks like in the published data.

What the kernel team says to do about it

Every announcement carries the same mitigation paragraph, worth reading as written rather than summarised:

The Linux kernel CVE team recommends that you update to the latest
stable kernel version for this, and many other bugfixes.  Individual
changes are never tested alone, but rather are part of a larger kernel
release.  Cherry-picking individual commits is not recommended or
supported by the Linux kernel community at all.

The CVE process document makes the same point: “it is best to take all released kernel changes, as they are tested together in a unified whole”, and adds that “for many bugs, the solution to the overall problem is not found in a single change, but by the sum of many fixes on top of each other”, so “assume that some changes without a CVE assigned might be relevant to take”.

Two further statements reshape what a clean report means. First: “No CVEs will be assigned for any issue found in a version of the kernel that is not currently being actively supported by the Stable/LTS kernel team.” A product on 5.4 or 4.19 accumulates no new kernel CVEs, and that is a property of the policy, not of the software. Second: a bug that exists only because of changes a vendor made cannot get a kernel CVE at all, so whatever your vendor’s out-of-tree patches broke will never appear in a scan against kernel CVE data.

Check your own tree, not your version string

A vendor BSP that reports 6.6.157 may or may not contain what 6.6.157 contains. The version string comes from the Makefile and survives any amount of divergence, so it is evidence of intent rather than of content.

raghu@techveda.org:~$ git log --oneline v6.6.157..HEAD -- drivers/net/ethernet/stmicro/ | wc -l
raghu@techveda.org:~$ sed -n '/^dma_map_err:/,/^}/p' \
    drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

The first tells you how far your fork has drifted from the tag it claims. The second shows the actual error path. Look for the code rather than the commit: a vendor may have applied an equivalent patch under a different commit id, and a commit-id search would then report a false negative.

For a specific fix, ask whether the commit is an ancestor of your head:

raghu@techveda.org:~$ git merge-base --is-ancestor e85adaac3dc6317cae902372c6849189ec62cf7d HEAD && echo present || echo absent
absent

That answers the question when the commit exists in your object database, which for a fork of a stable series it usually does. Treat absent as “check the code as well”, not as a conclusion.

What this changes for stable kernel update planning

The series you pin is a security decision, not only a lifetime decision. Two products with identical hardware, one on 6.6 and one on 6.12, do not face the same open-defect set even after both take every stable release, because the backport reaches the newer series more often and sometimes only the newer series. That difference appears in no support-window table.

Second, a team that cannot move series needs a budget line for writing its own backports. The upstream fix will not apply, so somebody has to produce an equivalent for the series you ship, review it and test it. If nobody owns that work the defect stays, and it belongs on the risk register rather than quietly closed because a scanner found no fix to flag.

Third, the scanner’s verdict is not your verdict. A report that maps installed version to fixed version will mark CVE-2026-98131 as not applicable to a 6.6 product, because there is no 6.6 fix version to compare against. The defect is present, and the process document pushes the judgement back to you: “the applicability of any specific CVE is up to the user of Linux to determine”.

Teams building a defensible update and validation process for a shipped device can find this material as structured training in TECH VEDA’s Embedded Linux BSP Development course.

Common wrong turns

Reading the fixed list and stopping. This is attractive because the fixed list looks like a table of facts, and for a CVE fixed everywhere it is the whole answer. The incomplete part of the model is that the list describes fixes, not exposure. Exposure comes from the introduced version, on the same line and easy to skim past.

Reasoning from branch dates alone. “Our series predates the introducing version, so we are clear” is correct most of the time, which is what makes CVE-2026-97979 dangerous. A backport can introduce a defect into an older series years after it branched, and the introduced version for that series is then a point release rather than a major one.

Cherry-picking the listed commit. The announcement gives the commit URLs, so this reads like an invitation. It is the opposite: the same paragraph says cherry-picking is not supported at all. Where the fix depends on newer infrastructure the cherry-pick does not build, which is loud. The quieter and worse case is one that does build while depending on a prerequisite you did not take.

Treating an old kernel’s empty CVE list as a good sign. No CVEs are assigned against unsupported versions, so a 4.19 or 5.4 product shows a flat line. That is the policy working as documented, and it is the one case where an empty report should worry you more than a full one.

Key takeaways

  • A CVE in a stable kernel update answers two questions: the introduced version says whether you are affected, the fixed list says whether a patch exists for your series. Read both.
  • Your series missing from the fixed list means either “not affected” or “affected and unfixed”, and only the introduced version tells you which.
  • CVE-2026-98131 leaves the same DMA leak in 6.1.188, 6.6.157, 6.12.111 and 6.18.54, with a byte-identical error path, and lists a fix only for 7.2.7.
  • That fix cannot be cherry-picked into a longterm series: three identifiers it uses do not exist there. Closing the hole needs a new patch.
  • A backport can introduce a defect into an LTS long after it branched, shown as an “Issue introduced” line with no fix beside it.
  • No CVEs are assigned against kernels the stable team no longer supports, so an empty report on an old kernel says nothing about the code.

A verification checklist

  1. Each CVE in your filtered list has its introduced version recorded next to the fixed versions. A row with only fixed versions is not triaged.
  2. Where your series appears in the fixed list, the fix version is at or below the release you are taking. If not, the fix is not in your build.
  3. Where your series is absent, the introduced version confirms whether the affected code exists there at all.
  4. Check for an “Issue introduced in <your series>.<point release>” line with no fix beside it. That is an open defect in your series, stated outright.
  5. git merge-base --is-ancestor <fix commit> HEAD on your BSP, and read the affected function as well. Agreement between the two is what confirms the fix is present.
  6. Every CVE closed as not applicable has a recorded reason stronger than the absence of a fix version.
Was this worth your time?

Frequently asked questions

My series is not in the fixed list. Am I safe?
Only if the affected code does not exist in your series. Compare the introduced version with where your series branched: if the bug predates your series, you are affected and no fix has been backported.

Can I just cherry-pick the commit the announcement links to?
The announcement says cherry-picking individual commits is not recommended or supported by the kernel community. In the stmmac case it is not possible either: the fix uses three identifiers that do not exist in any longterm series.

Why does an old kernel show almost no CVEs?
Because no CVEs are assigned for issues found in versions the stable team no longer supports. The absence of entries reflects the policy, not the state of the code.

Does taking every stable kernel update solve this?
Taking every stable kernel update is the best available default and the one the kernel team recommends, but it does not close a hole that has no backport for your series. Those need a patch written for your series, or a move to a series that has one.

Further reading

RB
Raghu Bharadwaj

Founder, TECH VEDA โ€” 20+ years teaching the Linux kernel, device drivers and embedded systems.

Follow on LinkedIn

Get new posts by email

Kernel, embedded Linux and AI-era engineering โ€” a few sharp reads a month. No spam.

We email occasionally and never share your address.