CVE-2026-63799: sched/mmcid: Fix OOB clear_bit when CID is MM_CID_UNSET in fixup path
In the Linux kernel, the following vulnerability has been resolved:
sched/mmcid: Fix OOB clearbit when CID is MMCIDUNSET in fixup path
In mmcidfixupcpustotasks(), when rq->curr has the target mm and mmcid.active is set, the CID is checked with cidintransit() before setting the transition bit. In per-CPU mode a newly forked or exec'd task can be running with mmcid.cid == MMCIDUNSET because CIDs are assigned lazily on schedule-in. With cidintransit() the guard passes for MMCIDUNSET (no transit bit), converts it to MMCIDUNSET | MMCIDTRANSIT and stores it back; later mmcidschedout() feeds this to clearbit() with MMCIDUNSET as the bit number, triggering an out-of-bounds write.
Symptoms: this is genuine memory corruption, but a bounded out-of-bounds write, not an arbitrary one. MMCIDUNSET is the fixed sentinel BIT(31), so once the bad value reaches mmcidschedout() the cidfromtransitcid() strip leaves MMCIDUNSET, which fails the "cid < maxcids" convergence test and falls into mmdropcid() -> clearbit(MMCIDUNSET, mmcidmask(mm)). The cid bitmap is embedded in the mmstruct slab object (after cpubitmap and mmcpusallowed) and is only numpossiblecpus() bits wide, so clearing bit 31 is a deterministic OOB bit-clear at a fixed offset of 2^31 / 8 == 256 MiB past the bitmap base. The address is not attacker-influenced (fixed sentinel -> fixed offset) and the op only clears a single bit; what sits 256 MiB further along the direct map is whatever kernel object happens to live there, so this corrupts one bit of unpredictable kernel memory -- it is not an arbitrary-address or arbitrary-value write.
It triggers only in per-CPU CID mode, when a CPU is running an active task of the target mm whose cid is still MMCIDUNSET -- the fork()/execve() window before that task's next schedule-in assigns it a real CID -- and a per-CPU -> per-task fixup walks over it (the mode fallback driven by a thread exit, schedmmcidexit(), or by the deferred maxcids recompute in mmcidworkfn()).
In practice syzkaller surfaced it as a KASAN use-after-free reported in schedule -> mmcidswitchto, where the offending clearbit() is inlined via mmcidschedout() -> mmdropcid().
Guard the transition-bit assignment against MMCIDUNSET, in addition to the existing cidintransit() check, so the bit is only set on a genuine task-owned CID. A CPU-owned (MMCIDONCPU) CID of a running active task is handled by the cidoncpu(pcp->cid) branch above and never reaches this path, so excluding MMCIDUNSET (and the already-transitioning case) is sufficient.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
Patch the Linux kernel mmcid fixup path so transition-bit assignment and clear_bit() operations are guarded to exclude the sentinel MM_CID_UNSET (BIT(31)) in addition to existing checks (e.g., when rq->curr has the target mm and in per-CPU mode). This prevents clear_bit(MM_CID_UNSET, ...) which deterministically clears bit 31 and writes 256 MiB past the embedded cid bitmap base.
Linux kernel mmcid subsystem Guard transition-bit assignment against MM_CID_UNSET in mm_cid_fixup_cpus_to_tasks()/fixup path = Exclude MM_CID_UNSET when calling clear_bit for CID transition bits
Event History
Frequently Asked Questions
Who can exploit this issue?
The CVSS vector indicates local access with low privileges is required. No user interaction is required.
What conditions are needed to trigger the corruption?
The issue occurs in per-CPU mode when a newly forked or exec'd task is running with its CID still set to MM_CID_UNSET because CID assignment is lazy on schedule-in. The affected fixup path must process a current task whose target mm has active mm_cid state.
What is the impact of a successful trigger?
The flaw causes a genuine but bounded out-of-bounds write when clear_bit() receives MM_CID_UNSET as its bit number. The reported CVSS impact includes high confidentiality, integrity, and availability effects.
What should be done to remediate it?
Update to a Linux kernel release containing the fix. The referenced stable fixes are 8d32856fb72ba976d9c87ba405fd17e80419934c and de3ab9bd3133899efb92e4cd05ba4203e58fc0a3.