CVE-2026-98797
NoneCVSS
—
EPSS
0.2%
Published
Oct 18, 2026
CISA due date
—
Cloudanix analysis
A bug in the Linux kernel's network traffic handling can let a local user crash the system when certain advanced queue and redirect rules are active.
- Exploitation
- Local Privilege
- Attacker needs
- Low Privilege
- Complexity
- Moderate
- Impact
- Denial Of Service
- Component
- OS kernel
- Class
- Buffer Overflow
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Out-of-bounds access in taprio_enqueue() when skb->queue_mapping from a forwarded packet (ingress rx_queue+1) indexes beyond the allocated q->qdiscs[] array after skbedit + mirred nesting bypasses queue capping.
Why it matters to the business
Kernel memory corruption or crash on systems using the taprio qdisc under specific traffic control configurations; limited to environments with complex egress mirroring and skbedit rules, increasing operational risk on network-heavy workloads.
How an attack unfolds
A local attacker with CAP_NET_ADMIN in a network namespace creates dummy devices with differing TX queue counts, installs taprio and clsact qdiscs plus matchall filters with skbedit and mirred actions, then sends a packet that triggers nested xmit; the stale queue_mapping from the inner device causes the outer taprio_enqueue to read past its child array.
How to fix it
Apply the upstream kernel fix that caps skb->queue_mapping in netdev_tx_queue_mapping(), properly saves/restores the skip_txqueue flag around sch_handle_egress(), and arms the flag only from within the egress classifier; rebuild and reboot with the patched kernel.
How to confirm the fix worked
Confirm the presence of netdev_cap_txqueue() store and the skb->nf_skip_egress handling changes in net/core/dev.c and net/sched/sch_generic.c; test recreation conditions with KASAN to verify absence of slab-out-of-bounds faults.
Typical attack path
- Create multiple dummy net devices with different TX queue counts inside a network namespace
- Attach taprio on the smaller-queue device and clsact on all devices
- Install egress matchall filters that use skbedit queue_mapping followed by mirred redirect/mirror
- Transmit a packet that traverses the nested mirred path
- Consume the skip_txqueue flag on the outer xmit to index taprio qdiscs[] out of bounds
How to detect it
Search kernel logs and KASAN reports for slab-out-of-bounds faults in taprio_enqueue triggered after skbedit or mirred actions; inspect netfilter egress paths and skb queue_mapping values on forwarded packets.
- slab-out-of-bounds in taprio_enqueue
- skb->queue_mapping exceeding device tx queue count
- taprio qdiscs[] index past allocation
What your security team should do
- Prioritize kernel updates on systems with CONFIG_NET_SCH_TAPRIO=y and CONFIG_NET_ACT_SKBEDIT=y enabled
- Audit tc egress configurations that combine skbedit queue_mapping with mirred actions
- Monitor for slab-out-of-bounds reports involving taprio_enqueue in kernel logs
- Restrict CAP_NET_ADMIN in untrusted network namespaces until patched
The record
In the Linux kernel, the following vulnerability has been resolved: net: cap skb->queue_mapping when the tx queue is picked skbedit can set skb->queue_mapping and raise the per-CPU skip_txqueue flag so __dev_queue_xmit() honours the mapping. __dev_queue_xmit() cleared the flag before sch_handle_egress() and only read it afterwards, so the flag was not confined to the xmit that set it: a nested xmit (mirred redirect or mirror, or a drop after skbedit) could set the flag and the outer xmit would consume it for an skb that never went through skbedit. A forwarded packet still carries the ingress NIC's rx_queue + 1 in skb->queue_mapping, so the outer device then indexes its tx queue state with that stale value. Taprio's child array q->qdiscs[] is sized to the device's queue count, so taprio_enqueue() indexes past its allocation and dereferences the result as a struct Qdisc *. We (ab)use the skb->nf_skip_egress which means "skip netfilter egress for this packet" to tag to "am I in tc egress?". Despite the overload I dont see it as a conflict since the marker is set only around the single sch_handle_egress() call and ingress path is guarded by tc_at_ingress. I will send a followup(net-next) patch once this hits net-next to rename the skb->nf_skip_egress bit/flag to skb->skip_egress Arm the flag only from the egress classifier that can use it: raise skip_txqueue from tcf_skbedit_act() only when it runs inside sch_handle_egress(), thanks to skb->nf_skip_egress. An egress qdisc classifier runs in q->enqueue(), after the tx queue has been picked, so a mapping it sets cannot affect the current packet; arming the flag there only pollutes it for a later xmit. Then own the flag for the xmit frame the egress hook runs in: save the incoming value and clear it just before sch_handle_egress(), and restore it after the hook - on the consumed (drop) path, or, in the same call that reads it, on the surviving path. The save and the restores stay inside the egress_needed_key static branch, so a packet pays for them only when egress hooks are active (2f1e85b1aee4). Store the value netdev_cap_txqueue() selected back into skb->queue_mapping in netdev_tx_queue_mapping(), as netdev_core_pick_tx() already does, so the skip_txqueue path never hands a later reader on the xmit path a mapping the device cannot serve. A store made still later in the same frame, by a tc BPF program attached to a transmit qdisc, is outside this path and is not re-capped; a separate followup will resolve that path. netdev_xmit_skip_txqueue() returns the previous flag value so the save-and-clear is one call, and a no-op stub is provided when CONFIG_NET_EGRESS is disabled. skb->nf_skip_egress is compiled under CONFIG_NET_EGRESS rather than CONFIG_NETFILTER_SKIP_EGRESS, so skb_at_tc_egress() is valid whenever the egress path is built. A local user in a network namespace can redirect a packet from a device with more TX queues to one with fewer after setting a mapping valid only on the larger device. That reaches these reads and, under KASAN, faults with "slab-out-of-bounds in taprio_enqueue". Conditions to recreate the bug: the report's own trigger is a local user with CAP_NET_ADMIN in a network namespace, so no eBPF program is needed. With CONFIG_NET_SCH_TAPRIO=y, CONFIG_NET_ACT_SKBEDIT=y, CONFIG_NET_ACT_MIRRED=y, CONFIG_NET_CLS_MATCHALL=y, CONFIG_NET_SCH_PRIO=y and KASAN enabled, create qa (3 queues), qb (2 queues) and qc (1 queue) as dummy devices; put a taprio root on qb (num_tc 1, queues 2@0) and clsact on all three; then add an egress matchall filter on every device. On qa: "action skbedit queue_mapping 2 pipe action mirred egress redirect dev qb". On qb: "action mirred egress mirror dev qc". On qc: "action skbedit queue_mapping 0 pipe". Send one packet out qa. qc's skbedit sets the flag while qb's outer xmit is in flight; without the fix qb consumes it and reads its two-entry taprio child array with the forwarded packet's stale mapping. A qc whose skb ---truncated---
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|