CVE-2025-37821

Severity CVSS v4.0:
Pending analysis
Type:
CWE-476 NULL Pointer Dereference
Publication date:
08/05/2025
Last modified:
12/11/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> sched/eevdf: Fix se-&gt;slice being set to U64_MAX and resulting crash<br /> <br /> There is a code path in dequeue_entities() that can set the slice of a<br /> sched_entity to U64_MAX, which sometimes results in a crash.<br /> <br /> The offending case is when dequeue_entities() is called to dequeue a<br /> delayed group entity, and then the entity&amp;#39;s parent&amp;#39;s dequeue is delayed.<br /> In that case:<br /> <br /> 1. In the if (entity_is_task(se)) else block at the beginning of<br /> dequeue_entities(), slice is set to<br /> cfs_rq_min_slice(group_cfs_rq(se)). If the entity was delayed, then<br /> it has no queued tasks, so cfs_rq_min_slice() returns U64_MAX.<br /> 2. The first for_each_sched_entity() loop dequeues the entity.<br /> 3. If the entity was its parent&amp;#39;s only child, then the next iteration<br /> tries to dequeue the parent.<br /> 4. If the parent&amp;#39;s dequeue needs to be delayed, then it breaks from the<br /> first for_each_sched_entity() loop _without updating slice_.<br /> 5. The second for_each_sched_entity() loop sets the parent&amp;#39;s -&gt;slice to<br /> the saved slice, which is still U64_MAX.<br /> <br /> This throws off subsequent calculations with potentially catastrophic<br /> results. A manifestation we saw in production was:<br /> <br /> 6. In update_entity_lag(), se-&gt;slice is used to calculate limit, which<br /> ends up as a huge negative number.<br /> 7. limit is used in se-&gt;vlag = clamp(vlag, -limit, limit). Because limit<br /> is negative, vlag &gt; limit, so se-&gt;vlag is set to the same huge<br /> negative number.<br /> 8. In place_entity(), se-&gt;vlag is scaled, which overflows and results in<br /> another huge (positive or negative) number.<br /> 9. The adjusted lag is subtracted from se-&gt;vruntime, which increases or<br /> decreases se-&gt;vruntime by a huge number.<br /> 10. pick_eevdf() calls entity_eligible()/vruntime_eligible(), which<br /> incorrectly returns false because the vruntime is so far from the<br /> other vruntimes on the queue, causing the<br /> (vruntime - cfs_rq-&gt;min_vruntime) * load calulation to overflow.<br /> 11. Nothing appears to be eligible, so pick_eevdf() returns NULL.<br /> 12. pick_next_entity() tries to dereference the return value of<br /> pick_eevdf() and crashes.<br /> <br /> Dumping the cfs_rq states from the core dumps with drgn showed tell-tale<br /> huge vruntime ranges and bogus vlag values, and I also traced se-&gt;slice<br /> being set to U64_MAX on live systems (which was usually "benign" since<br /> the rest of the runqueue needed to be in a particular state to crash).<br /> <br /> Fix it in dequeue_entities() by always setting slice from the first<br /> non-empty cfs_rq.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.12 (including) 6.12.29 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.13 (including) 6.14.5 (excluding)
cpe:2.3:o:linux:linux_kernel:6.15:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.15:rc3:*:*:*:*:*:*