A subtle logic bug in the Linux kernel’s traffic control code (qdisc) has been identified and fixed, tracked as CVE-2025-21702. This flaw involves the pfifo_tail_enqueue function, which incorrectly handles the case where a packet scheduler’s queue limit is set to zero. When exploited, it can break the expected accounting between parent and child queue discplines (qdiscs), setting up potential conditions for privilege escalation from user-space to kernel.
Let’s break this bug down in simple terms, understand its exploit potential, and review how it was resolved in upstream Linux. We’ll include code snippets and technical details so advanced users/admins can assess if they’re affected.
What Is A Qdisc?
Linux traffic control uses "queuing disciplines" (qdiscs) to manage how packets are queued and sent out an interface. Qdiscs can be hierarchical: a parent qdisc can have child qdiscs.
pfifo_head_drop: A simple queue that drops packets at the head on overflow.
- hfsc, drr, etc.: Hierarchical/qos schedulers that may have children qdiscs.
The Bug: pfifo_tail_enqueue and sch->limit ==
Let’s look at what should happen versus what does, in pfifo_tail_enqueue with limit zero.
Expected Behavior
- If the qdisc queue is full (sch->qlen >= sch->limit), it should drop a packet (to make room), decrease sch->qlen by 1.
Code snippet (simplified)
// From net/sched/sch_fifo.c (paraphrased)
int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch) {
if (unlikely(sch->q.qlen >= sch->limit)) {
// Drop a packet
struct sk_buff *to_drop = skb_dequeue(&sch->q);
if (to_drop)
qdisc_drop(to_drop, sch); // Actually only true if qlen >
}
// Enqueue new packet regardless
__skb_queue_tail(&sch->q, skb);
sch->q.qlen++;
return (sch->q.qlen >= sch->limit) ? NET_XMIT_CN : NET_XMIT_SUCCESS;
}
If you set sch->limit == , the "drop a packet" does nothing (queue is empty), but the new packet is still enqueued!
Returns NET_XMIT_CN (congestion).
3. Qdisc_A checks status; since it’s not NET_XMIT_SUCCESS, it does NOT increment its own qlen.
Qdisc_B->qlen == 1
Normally: _parent qlen = sum(child qlens_
Here: violation of kernel invariants.
Impact
This disconnect can corrupt the network scheduler’s internal state, confusing the kernel’s tracking of packet ownership and memory, and can be leveraged by attackers in some configurations to escalate privileges, e.g., by manipulating memory management or object lifetime in the kernel.
Here’s a rough PoC using tc (traffic control utility)
# Add hierarchical scheduler (hfsc) as root on interface eth
tc qdisc add dev eth root handle 1: hfsc
# Attach a pfifo_head_drop as a child with limit zero
tc qdisc add dev eth parent 1:1 handle 10: pfifo_head_drop limit
# Send a packet through this qdisc
ping -c 1 <your_ip>
- After the ping, check qlens by introspecting via tc -s qdisc show. You may observe mismatched qlens!
If sch->limit == , don’t enqueue any packet—drop new arrivals and maintain correct counters.
Reference Patch:
- Kernel commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=823bdcc67b5c9f25798908eae6bc333d253e69
Upstream Discussion:
- https://lore.kernel.org/all/20240212125945.19867-1-baozhu.yao@linux.alibaba.com/
Exploitability & Security Impact
When reachable by unprivileged users, especially in container/multitenant setups (where users can manipulate qdiscs), this strange accounting opens doors to kernel object abuse or even privilege escalation. Exploitability is environment-dependent; many production systems hide tc from non-root, but some scenarios (e.g., with custom netns tools in cloud) might let users reach qdisc controls.
Patch ASAP: Update to a kernel version with the fix for CVE-2025-21702.
- Restrict tc/qdisc changes to root only.
Conclusion
CVE-2025-21702 highlights how a tiny logic error in Linux's network scheduler can have serious consequences, breaking core invariants and creating the risk for escalation attacks.
Always keep your kernel up to date and monitor for subtle misconfigurations in advanced network setups.
References
- Linux Kernel Patch Commit
- Kernel Patch Mail Thread
- CVE Entry at mitre.org (when available)
- Linux Qdisc Documentation
If you administer multi-user or cloud Linux systems, make sure you assess your exposure to this subtle bug.
Timeline
Published on: 02/18/2025 15:15:18 UTC
Last modified on: 05/04/2025 07:19:19 UTC