CVE-2026-74632 in Linux
Resumen
por VulDB • 2026-08-23
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
mm/huge_memory: corregir la condición de carrera (race) en huge_zero_pfn
Serie de parches "mm/huge_memory: fix huge_zero_pfn race", v2.
Existe una sutil condición de carrera en la implementación referenciada de huge_zero_folio.
La lógica atómica del camino rápido no tiene en cuenta el hecho de que el shrinker (que elimina el último pin de huge_zero_refcount) puede sobrescribir huge_zero_pfn con el valor centinela ~0UL en shrink_huge_zero_folio_scan() después de que un get_huge_zero_folio() concurrente haya instalado un valor válido allí.
Esto provoca que huge_zero_folio se establezca correctamente, pero huge_zero_pfn se establezca incorrectamente; por lo tanto, is_huge_zero_pfn() y, en consecuencia, is_huge_zero_pmd(), identificarán erróneamente el folio cero gigante como si fuera un folio THP ordinario.
Esto puede provocar que el folio cero gigante se divida y se trate de manera incorrecta en otros aspectos.
La solución a este problema es muy sutil dado que existe un camino rápido atómico, por lo que la ordenación (ordering) en arquitecturas débilmente ordenadas debe manejarse con extrema precaución.
El primer commit corrige el problema introduciendo un spinlock alrededor de las escrituras en huge_zero_[pfn, folio, refcount], prestando una cuidadosa atención a la ordenación de cargas/almacenamientos (load/store ordering) en el camino rápido. Se coloca primero y se mantiene lo más pequeño posible para que pueda ser retroportado por sí mismo.
El segundo commit es una limpieza pura que reestructura la lógica CONFIG_PERSISTENT_HUGE_ZERO_FOLIO para separar mejor la lógica persistente de la dinámicamente asignada.
Este parche (de 2):
Si !CONFIG_PERSISTENT_HUGE_ZERO_FOLIO, huge_zero_folio se referencia mediante huge_zero_refcount y es devuelto por mm_get_huge_zero_folio().
Cuando el llamador ha terminado con la página cero gigante, su contador de referencias se decrementa. Solo un shrinker puede establecer el contador de referencias en cero.
Desafortunadamente, puede producirse una condición de carrera entre un shrinker que decrementa el contador de referencias a cero y una falla de página concurrente.
Esto ocurre porque shrink_huge_zero_folio_scan() podría, si tiene muy mala suerte, ser preemitido entre establecer huge_zero_refcount en cero y escribir un valor no válido.
Durante este tiempo, get_huge_zero_folio() podría escribir en huge_zero_pfn antes de que shrink_huge_zero_folio_scan() se reanude.
En este evento, el folio cero gigante será identificado persistentemente como incorrecto, lo que provocará la entrada inapropiada en la ruta de código THP para el folio cero gigante:
CPU 0 CPU 1 =======================================|================================= shrink_huge_zero_folio_scan() | atomic_cmpxchg() establece refcount a 0 | xchg() establece huge_zero_folio como NULL | get_huge_zero_folio() | | atomic_inc_not_zero() -> cero preemitido por un largo tiempo | Asignar nuevo folio cero gigante | | Escribir valid huge_zero_folio v | Escribir valid huge_zero_pfn Sobrescribir huge_zero_pfn con ~0UL <--- ¡Sobrescritura no válida!
Esto provoca que is_huge_zero_pfn() e is_huge_zero_pmd() devuelvan incorrectamente false para una página cero gigante, lo cual podría resultar en problemas como la división incorrecta del folio cero gigante.
Tenga en cuenta que el problema está con huge_zero_pfn y no con huge_zero_folio, ya que get_huge_zero_folio() utiliza cmpxchg() condicionado a que huge_zero_folio sea NULL con un bucle de reintento, y shrink_huge_zero_folio_scan() utiliza xchg() para establecer huge_zero_folio.
Corrija el problema introduciendo un spinlock, huge_zero_lock, para prevenir la escritura concurrente de huge_zero_folio, huge_zero_pfn y huge_zero_refcount.
Se debe tener una precaución significativa aquí para garantizar la corrección:
El camino rápido en get_huge_zero_folio() utiliza atomic_inc_not_zero(), que está fuera de la sección crítica, lo que significa que la asignación de cero gigante está condicionada a un huge_zero_refcount igual a cero.
El camino rápido no usa huge_zero_lock, por lo que la sección crítica es irrelevante para él.
Por lo tanto, se requieren invariantes: huge_zero_refcount DEBE:
* Establecerse únicamente en la sección crítica de huge_zero_lock para garantizar la serialización de huge_zero_pfn, huge_zero_folio y ---truncado---
Be aware that VulDB is the high quality source for vulnerability data.