A missing lock on a shared shopping list lets two shoppers grab the same item, and one walks out with the store
CVE-2026-68138 is a race condition in the Linux kernel's traffic-control rate-table code (net/sched). The functions qdisc_get_rtab() and qdisc_put_rtab() manipulate a process-global singly linked list (qdisc_rtab_list) and a plain non-atomic int refcnt without any lock. This was historically safe because all callers held the RTNL mutex — but the flower classifier sets TCF_PROTO_OPS_DOIT_UNLOCKED, allowing tc_new_tfilter() to reach the police action path without RTNL. The resulting use-after-free is exploitable for local privilege escalation from UID 1000 to root in the initial user namespace. Affected kernels span Linux 5.1 through 7.1.5 — roughly seven years of mainline releases. The fix landed in 7.1.6 and 7.2-rc5.
The vendor’s HIGH / 7.8 rating is accurate for this bug. The CVSS vector (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) correctly captures the local-only attack surface and complete CIA impact upon exploitation. There is a public, weaponized proof-of-concept by security researcher A. Ramos that reliably escalates to root in a QEMU environment. The wide affected-version range (5.1–7.1.5) means virtually every enterprise Linux fleet has vulnerable hosts right now. The only thing preventing a CRITICAL rating is the hard requirement for local code execution — an attacker must already be on the box.
5 steps from start to impact.
Attain local code execution
- Local shell access on a Linux host running kernel 5.1–7.1.5
- User namespace or network namespace creation permitted (default on Ubuntu, Fedora, many container runtimes)
- Requires prior initial access — this is not remotely exploitable
- Hardened hosts may disable unprivileged user namespaces via
kernel.unprivileged_userns_clone=0
tc filter creation or rapid namespace churnRace qdisc rate-table list via flower classifier
qdisc_get_rtab() and qdisc_put_rtab() concurrently, corrupting the global qdisc_rtab_list linked list and its reference count. This produces a use-after-free on the rate-table structure.- CONFIG_NET_SCHED=y and CONFIG_NET_CLS_FLOWER=m/y in the running kernel (standard in enterprise distros)
- Ability to create network namespaces
- Race window is tight but the PoC demonstrates it is reliably winnable with ~4 threads
- Some minimal/IoT kernels may lack the flower classifier module
tc filter add with flower + action police in rapid succession; kernel KASAN builds will detect the UAF immediatelyHeap reclamation via BPF + pipe spray
page and ops structures, breaking KASLR.- Memory-cgroup accounting enabled (default on Ubuntu with systemd)
- setsockopt SO_ATTACH_FILTER available to unprivileged users
- CONFIG_BPF_UNPRIV_DEFAULT_OFF=y blocks the classic BPF path on some hardened kernels
- Kernel heap layout randomization (SLAB_FREELIST_RANDOM) reduces reliability but does not prevent exploitation
Overwrite modprobe_path via page-cache corruption
simple_xattr spray to place a mergeable pipe buffer, the attacker overwrites the page-cache entry backing /sbin/modprobe. This redirects the kernel’s automatic module-load mechanism to an attacker-controlled script. The technique is a variant of the well-known DirtyPipe / DirtyCred pattern adapted to the qdisc UAF primitive.- Writable tmpfs or filesystem for the attacker’s payload script
- Page cache not pinned or integrity-checked (default on all mainstream kernels)
- Lockdown LSM in integrity mode blocks modprobe_path overwrite on some enterprise kernels
- SELinux in enforcing mode may prevent execution of the replacement binary
Trigger module autoload for root shell
call_modprobe() which now executes the attacker’s script as root in the initial user namespace. The script spawns a root shell or plants a persistent backdoor. Full compromise achieved.- Kernel module autoloading enabled (modules_disabled=0, the default)
- Setting
kernel.modules_disabled=1at runtime blocks this final step entirely - Container runtimes that drop CAP_SYS_MODULE and restrict socket families limit this path
The supporting signals.
| In-the-Wild Status | No confirmed in-the-wild exploitation as of 2026-08-19. Not listed on CISA KEV. No GreyNoise or Shadowserver observations reported (local-only bug — network scanners would not see it). |
|---|---|
| Proof-of-Concept | Public weaponized PoC by A. Ramos (@aramosf) at github.com/aramosf/CVE-2026-68138. Achieves UID 0 from UID 1000 in tested QEMU environment. Validated on Ubuntu 5.15.0-187-generic. |
| EPSS Score | 0.00129 (low — but EPSS under-weights LPE bugs that require local access; treat this number with skepticism given the public PoC) |
| KEV Status | Not listed as of 2026-08-19 |
| CVSS Vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — 7.8 HIGH. Local vector, low complexity despite being a race (attacker controls both sides), low privilege required, complete CIA impact. |
| Affected Versions | Linux kernel 5.1 (commit 470502de5bdb) through 7.1.5. Approximately seven years of mainline releases. All major distro kernels (Ubuntu, RHEL, Debian, SUSE, Amazon Linux) shipping kernels in this range are affected unless backport-patched. |
| Fixed Versions | Mainline: 7.2-rc5 (commit f43ee0c0730d). Stable: 7.1.6 (commit fb29e1b41052). Distro backports: check your vendor tracker — Ubuntu CVE tracker had no entry as of 2026-08-12. |
| Scanning / Exposure | Not applicable for network scanning (local-only). For fleet exposure, query your CMDB or vulnerability scanner for kernel versions in the 5.1–7.1.5 range. Expect >90% of unpatched Linux hosts to be in the affected window. |
| Disclosure Date | 2026-08-10 (public disclosure and CVE assignment) |
| Reporter | A. Ramos ([email protected], @aramosf) |
noisgate verdict.
The vendor’s HIGH / 7.8 is correct because the public weaponized PoC delivering reliable local root is the single most decisive factor — it eliminates any complexity discount, and the seven-year affected window means virtually every Linux host in fleet is vulnerable. The local-access prerequisite is the sole factor preventing an upgrade to CRITICAL.
Why this verdict
- Public weaponized PoC eliminates complexity discount. Despite being a race condition, the PoC by A. Ramos demonstrates reliable exploitation in a standard QEMU environment on a shipping Ubuntu kernel. AC:L is justified.
- Massive affected footprint. Kernels 5.1 through 7.1.5 cover roughly seven years of releases. In a 10,000-host fleet, expect 90%+ of Linux hosts to carry vulnerable kernels, making selective scoping impractical.
- Role multiplier: HIGH-value roles are directly impacted. The Linux kernel is the affected component itself. On Kubernetes nodes and container hosts (high-value role, >=10% of Linux installs in enterprise), this bug lets a container-escaped attacker (or a malicious co-tenant) escalate to host root — blast radius is node-level, potentially fleet-scale if the attacker pivots across nodes. On hypervisors (KVM hosts), exploitation yields hypervisor-root. On CI/CD runners (GitLab Runner, GitHub Actions self-hosted), a supply-chain actor with job execution gets host root. These roles floor the verdict at HIGH.
- Local-access prerequisite provides meaningful friction. AV:L means the attacker must already have a shell on the target host. This is a real barrier that prevents mass-exploitation at internet scale and is the primary reason the verdict stays HIGH rather than CRITICAL.
- No in-the-wild exploitation or KEV listing yet. The PoC is public but no campaigns have been observed. This removes urgency pressure that would push toward CRITICAL.
Why not higher?
The hard requirement for local code execution (AV:L) means this cannot be exploited remotely. An attacker must already have a foothold on the target host. While the role multiplier on container hosts and hypervisors is severe, the local-only vector means mass exploitation requires a separate initial-access vulnerability first. Without active KEV listing or observed campaigns, the urgency does not justify CRITICAL.
Why not lower?
A public, weaponized PoC that achieves reliable root from an unprivileged user on a shipping Ubuntu kernel eliminates any argument for MEDIUM. The affected version range spans seven years of kernels, meaning virtually every Linux host is in scope. On container hosts, Kubernetes nodes, and CI/CD runners, this LPE is the final link in a container-escape-to-fleet-compromise chain — the blast radius on high-value roles is too severe for anything below HIGH.
What to do — in priority order.
- Disable unprivileged user namespaces — Set
sysctl kernel.unprivileged_userns_clone=0(or the equivalentkernel.apparmor_restrict_unprivileged_userns=1on Ubuntu 24.04+). The PoC relies on creating network namespaces as an unprivileged user to reach the unlocked flower classifier path. This is the single highest-value mitigation. Deploy within 30 days per noisgate mitigation SLA. - Disable kernel module autoloading — Set
sysctl kernel.modules_disabled=1after boot completes and all required modules are loaded. This blocks the final exploitation step (modprobe_path hijack). Requires careful testing in your environment as late-loading modules will fail. Deploy within 30 days. - Unload or blacklist cls_flower if unused — Run
modprobe -r cls_flowerand addblacklist cls_flowerto/etc/modprobe.d/. The vulnerable code path requires the flower classifier. If your traffic-control policies do not use flower, removing it eliminates the attack surface entirely. - Enable SELinux or AppArmor in enforcing mode — Mandatory access control policies can prevent the attacker’s replacement modprobe script from executing, even if the page-cache overwrite succeeds. Ensure the policy confines
/sbin/modprobeexecution tightly. - Deploy LKRG or IMA — Linux Kernel Runtime Guard detects credential structure modifications (UID changes from the exploit). Integrity Measurement Architecture can alert on unexpected modprobe_path content. These provide detection-in-depth.
- Network firewalls / WAFs / IDS — This is a local privilege escalation; there is no network traffic to inspect or block.
- Container isolation alone — Default container runtimes (Docker, containerd) still expose enough kernel surface for this exploit. The tc netlink interface is reachable from within containers unless explicitly blocked by seccomp.
- KASLR — The PoC includes a KASLR bypass via pipe-buffer pointer leak; address randomization does not prevent exploitation.
Crowdsourced verification payload.
Run this script on each target Linux host as any user with read access to /proc/version. No elevated privileges required. Example: chmod +x check_cve_2026_68138.sh && ./check_cve_2026_68138.sh
#!/bin/bash\n# CVE-2026-68138 Checker - qdisc_rtab_list race condition\n# Checks kernel version and cls_flower module availability\n# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN\n\nset -euo pipefail\n\nKERNEL_VERSION=$(uname -r)\nMAJOR=$(echo "$KERNEL_VERSION" | cut -d. -f1)\nMINOR=$(echo "$KERNEL_VERSION" | cut -d. -f2)\nPATCH=$(echo "$KERNEL_VERSION" | cut -d. -f3 | cut -d- -f1)\n\n# Check if kernel is in affected range: 5.1 through 7.1.5\nif [ -z "$MAJOR" ] || [ -z "$MINOR" ] || [ -z "$PATCH" ]; then\n echo "UNKNOWN - Could not parse kernel version: $KERNEL_VERSION"\n exit 2\nfi\n\n# Kernels before 5.1 are not affected\nif [ "$MAJOR" -lt 5 ]; then\n echo "PATCHED - Kernel $KERNEL_VERSION predates the vulnerable commit (5.1+)"\n exit 0\nfi\nif [ "$MAJOR" -eq 5 ] && [ "$MINOR" -lt 1 ]; then\n echo "PATCHED - Kernel $KERNEL_VERSION predates the vulnerable commit (5.1+)"\n exit 0\nfi\n\n# Kernels 7.2+ are fixed (mainline fix in 7.2-rc5)\nif [ "$MAJOR" -gt 7 ]; then\n echo "PATCHED - Kernel $KERNEL_VERSION is past the fix (7.2-rc5+)"\n exit 0\nfi\nif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -ge 2 ]; then\n echo "PATCHED - Kernel $KERNEL_VERSION includes the fix (7.2-rc5+)"\n exit 0\nfi\n\n# Kernel 7.1.6+ is fixed (stable backport)\nif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 1 ] && [ "$PATCH" -ge 6 ]; then\n echo "PATCHED - Kernel $KERNEL_VERSION includes the stable fix (7.1.6+)"\n exit 0\nfi\n\n# Check for distro-specific backport by looking for the fix commit in changelogs\n# This is best-effort; distro kernels may backport without changing the version\nif grep -q 'qdisc_rtab_lock' /proc/kallsyms 2>/dev/null; then\n echo "PATCHED - Kernel $KERNEL_VERSION has qdisc_rtab_lock symbol (backport detected)"\n exit 0\nfi\n\n# Check if cls_flower is available (required for exploitation)\nFLOWER_LOADED=false\nif lsmod 2>/dev/null | grep -q cls_flower; then\n FLOWER_LOADED=true\nfi\nFLOWER_AVAILABLE=false\nif modinfo cls_flower >/dev/null 2>&1; then\n FLOWER_AVAILABLE=true\nfi\n\necho "VULNERABLE - Kernel $KERNEL_VERSION is in the affected range (5.1 - 7.1.5)"\nif [ "$FLOWER_LOADED" = true ]; then\n echo " WARNING: cls_flower module is currently LOADED"\nelif [ "$FLOWER_AVAILABLE" = true ]; then\n echo " NOTE: cls_flower module is available but not loaded"\nelse\n echo " MITIGATING: cls_flower module not found (exploitation unlikely)"\nfi\nexit 1If you remember one thing.
kernel.unprivileged_userns_clone=0) fleet-wide and blacklist cls_flower on hosts that don’t use it. Prioritize patching Kubernetes nodes, container hosts, CI/CD runners, and KVM hypervisors first — these are the hosts where a local-to-root chain has fleet-scale blast radius. The public PoC is weaponized and reliable; do not wait for active exploitation to appear before acting.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.