CVE-2025-39677
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
05/09/2025
Last modified:
08/09/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
net/sched: Fix backlog accounting in qdisc_dequeue_internal<br />
<br />
This issue applies for the following qdiscs: hhf, fq, fq_codel, and<br />
fq_pie, and occurs in their change handlers when adjusting to the new<br />
limit. The problem is the following in the values passed to the<br />
subsequent qdisc_tree_reduce_backlog call given a tbf parent:<br />
<br />
When the tbf parent runs out of tokens, skbs of these qdiscs will<br />
be placed in gso_skb. Their peek handlers are qdisc_peek_dequeued,<br />
which accounts for both qlen and backlog. However, in the case of<br />
qdisc_dequeue_internal, ONLY qlen is accounted for when pulling<br />
from gso_skb. This means that these qdiscs are missing a<br />
qdisc_qstats_backlog_dec when dropping packets to satisfy the<br />
new limit in their change handlers.<br />
<br />
One can observe this issue with the following (with tc patched to<br />
support a limit of 0):<br />
<br />
export TARGET=fq<br />
tc qdisc del dev lo root<br />
tc qdisc add dev lo root handle 1: tbf rate 8bit burst 100b latency 1ms<br />
tc qdisc replace dev lo handle 3: parent 1:1 $TARGET limit 1000<br />
echo &#39;&#39;; echo &#39;add child&#39;; tc -s -d qdisc show dev lo<br />
ping -I lo -f -c2 -s32 -W0.001 127.0.0.1 2>&1 >/dev/null<br />
echo &#39;&#39;; echo &#39;after ping&#39;; tc -s -d qdisc show dev lo<br />
tc qdisc change dev lo handle 3: parent 1:1 $TARGET limit 0<br />
echo &#39;&#39;; echo &#39;after limit drop&#39;; tc -s -d qdisc show dev lo<br />
tc qdisc replace dev lo handle 2: parent 1:1 sfq<br />
echo &#39;&#39;; echo &#39;post graft&#39;; tc -s -d qdisc show dev lo<br />
<br />
The second to last show command shows 0 packets but a positive<br />
number (74) of backlog bytes. The problem becomes clearer in the<br />
last show command, where qdisc_purge_queue triggers<br />
qdisc_tree_reduce_backlog with the positive backlog and causes an<br />
underflow in the tbf parent&#39;s backlog (4096 Mb instead of 0).<br />
<br />
To fix this issue, the codepath for all clients of qdisc_dequeue_internal<br />
has been simplified: codel, pie, hhf, fq, fq_pie, and fq_codel.<br />
qdisc_dequeue_internal handles the backlog adjustments for all cases that<br />
do not directly use the dequeue handler.<br />
<br />
The old fq_codel_change limit adjustment loop accumulated the arguments to<br />
the subsequent qdisc_tree_reduce_backlog call through the cstats field.<br />
However, this is confusing and error prone as fq_codel_dequeue could also<br />
potentially mutate this field (which qdisc_dequeue_internal calls in the<br />
non gso_skb case), so we have unified the code here with other qdiscs.