Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2026-63799

Gravedad CVSS v3.1:
ALTA
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
19/07/2026
Última modificación:
20/07/2026

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> sched/mmcid: Fix OOB clear_bit when CID is MM_CID_UNSET in fixup path<br /> <br /> In mm_cid_fixup_cpus_to_tasks(), when rq-&gt;curr has the target mm and<br /> mm_cid.active is set, the CID is checked with cid_in_transit() before<br /> setting the transition bit. In per-CPU mode a newly forked or exec&amp;#39;d<br /> task can be running with mm_cid.cid == MM_CID_UNSET because CIDs are<br /> assigned lazily on schedule-in. With cid_in_transit() the guard passes<br /> for MM_CID_UNSET (no transit bit), converts it to MM_CID_UNSET |<br /> MM_CID_TRANSIT and stores it back; later mm_cid_schedout() feeds this<br /> to clear_bit() with MM_CID_UNSET as the bit number, triggering an<br /> out-of-bounds write.<br /> <br /> Symptoms: this is genuine memory corruption, but a bounded out-of-bounds<br /> write, not an arbitrary one. MM_CID_UNSET is the fixed sentinel BIT(31),<br /> so once the bad value reaches mm_cid_schedout() the cid_from_transit_cid()<br /> strip leaves MM_CID_UNSET, which fails the "cid clear_bit(MM_CID_UNSET,<br /> mm_cidmask(mm)). The cid bitmap is embedded in the mm_struct slab object<br /> (after cpu_bitmap and mm_cpus_allowed) and is only num_possible_cpus()<br /> bits wide, so clearing bit 31 is a deterministic OOB bit-clear at a<br /> fixed offset of 2^31 / 8 == 256 MiB past the bitmap base. The address is<br /> not attacker-influenced (fixed sentinel -&gt; fixed offset) and the op only<br /> clears a single bit; what sits 256 MiB further along the direct map is<br /> whatever kernel object happens to live there, so this corrupts one bit of<br /> unpredictable kernel memory -- it is not an arbitrary-address or<br /> arbitrary-value write.<br /> <br /> It triggers only in per-CPU CID mode, when a CPU is running an active<br /> task of the target mm whose cid is still MM_CID_UNSET -- the<br /> fork()/execve() window before that task&amp;#39;s next schedule-in assigns it a<br /> real CID -- and a per-CPU -&gt; per-task fixup walks over it (the mode<br /> fallback driven by a thread exit, sched_mm_cid_exit(), or by the deferred<br /> max_cids recompute in mm_cid_work_fn()).<br /> <br /> In practice syzkaller surfaced it as a KASAN use-after-free reported in<br /> __schedule -&gt; mm_cid_switch_to, where the offending clear_bit() is inlined<br /> via mm_cid_schedout() -&gt; mm_drop_cid().<br /> <br /> Guard the transition-bit assignment against MM_CID_UNSET, in addition to<br /> the existing cid_in_transit() check, so the bit is only set on a genuine<br /> task-owned CID. A CPU-owned (MM_CID_ONCPU) CID of a running active task<br /> is handled by the cid_on_cpu(pcp-&gt;cid) branch above and never reaches<br /> this path, so excluding MM_CID_UNSET (and the already-transitioning case)<br /> is sufficient.