CVE-2026-74632 in Linux
Сводка
по VulDB • 22.08.2026
В ядре Linux была устранена следующая уязвимость:
mm/huge_memory: исправление гонки данных (race condition) в huge_zero_pfn
Серия патчей "mm/huge_memory: fix huge_zero_pfn race", версия 2.
Существует тонкая гонка данных в реализации huge_zero_folio с подсчетом ссылок.
Атомарная логика быстрого пути не учитывает тот факт, что shrinker (который сбрасывает последнее закрепление счетчика huge_zero_refcount) может перезаписать значение huge_zero_pfn на sentinel-значение ~0UL в функции shrink_huge_zero_folio_scan() после того, как конкурентный вызов get_huge_zero_folio() установил там корректное значение.
Это приводит к тому, что huge_zero_folio устанавливается правильно, но huge_zero_pfn — неверно, вследствие чего is_huge_zero_pfn(), а следовательно, и is_huge_zero_pmd() ошибочно идентифицируют огромный нулевой folio как обычный THP-folio (Transparent Huge Page).
Это может привести к некорректному разделению огромного нулевого folio и его неправильной обработке.
Решение этой проблемы очень тонкое, так как существует атомарный быстрый путь, поэтому порядок операций на архитектурах со слабой упорядоченностью (weakly ordered architectures) должен обрабатываться с особой тщательностью.
Первый коммит исправляет проблему путем введения спинлока вокруг записи в huge_zero_[pfn, folio, refcount], при этом особое внимание уделяется порядку операций загрузки/записи на быстром пути. Он размещен первым и оставлен максимально компактным, чтобы его можно было бэкпортировать отдельно.
Второй коммит является чистой очисткой кода (cleanup) и перерабатывает логику CONFIG_PERSISTENT_HUGE_ZERO_FOLIO для более четкого разделения постоянной логики от динамически выделяемой.
Этот патч (из 2):
Если !CONFIG_PERSISTENT_HUGE_ZERO_FOLIO, то huge_zero_folio имеет подсчет ссылок через huge_zero_refcount и возвращается функцией mm_get_huge_zero_folio().
Когда вызывающая сторона завершает работу со страницей огромного нуля, ее счетчик ссылок уменьшается. Только shrinker может установить счетчик ссылок в ноль.
К сожалению, может возникнуть гонка данных между уменьшением счетчика ссылок до нуля функцией shrinker и одновременным исключением страницы (page fault).
Это происходит потому, что shrink_huge_zero_folio_scan() может, при очень неудачном стечении обстоятельств, быть прерван после установки huge_zero_refcount в ноль, но перед записью некорректного значения.
В течение этого времени get_huge_zero_folio() может записать значение в huge_zero_pfn до того, как shrink_huge_zero_folio_scan() возобновит выполнение.
В этом случае огромный нулевой folio будет постоянно ошибочно идентифицирован, что приведет к некорректному переходу кодового пути THP для огромного нулевого folio:
CPU 0 CPU 1 =======================================|================================= shrink_huge_zero_folio_scan() | atomic_cmpxchg() устанавливает refcount в 0 | xchg() устанавливает huge_zero_folio в NULL | get_huge_zero_folio() | | atomic_inc_not_zero() -> ноль прерван на долгое время | Выделение нового огромного нулевого folio | | Запись корректного huge_zero_folio v | Запись корректного huge_zero_pfn Перезапись huge_zero_pfn значением ~0UL <--- Некорректная перезапись!
Это приводит к тому, что is_huge_zero_pfn() и is_huge_zero_pmd() ошибочно возвращают false для страницы огромного нуля, что может вызвать проблемы, такие как некорректное разделение огромного нулевого folio.
Обратите внимание, что проблема касается huge_zero_pfn, а не huge_zero_folio, поскольку get_huge_zero_folio() использует cmpxchg(), заблокированный на условии, что huge_zero_folio равен NULL, с циклом повторных попыток (retry loop), а shrink_huge_zero_folio_scan() использует xchg() для установки huge_zero_folio.
Исправьте проблему путем введения спинлока huge_zero_lock для предотвращения конкурентной записи в huge_zero_folio, huge_zero_pfn и huge_zero_refcount.
Здесь необходимо проявить значительную осторожность для обеспечения корректности:
Быстрый путь в get_huge_zero_folio() использует atomic_inc_not_zero(), который находится вне критической секции, и означает, что выделение огромного нуля заблокировано на условии нулевого значения huge_zero_refcount.
Быстрый путь не использует huge_zero_lock, поэтому критическая секция для него нерелевантна.
Таким образом, требуются инварианты — huge_zero_refcount ДОЛЖЕН:
* Устанавливаться только в критической секции huge_zero_lock для обеспечения сериализации huge_zero_pfn, huge_zero_folio и ---обрезано---
If you want to get best quality of vulnerability data, you may have to visit VulDB.