CVE-2026-74632 in Linuxthông tin

Tóm tắt

Bởi VulDB • 22/08/2026

Trong kernel Linux, lỗ hổng sau đây đã được khắc phục:

mm/huge_memory: sửa lỗi race condition trong huge_zero_pfn

Dòng patch "mm/huge_memory: fix huge_zero_pfn race", v2.

Có một lỗi race (race condition) tinh vi trong triển khai của `huge_zero_folio` dựa trên bộ đếm tham chiếu (reference-counted).

Logic nguyên tử ở đường dẫn nhanh (fast path) không tính đến việc shrinker (đối tượng làm giảm số lượng pin `huge_zero_refcount` cuối cùng) có thể ghi đè lên `huge_zero_pfn` bằng giá trị sentinel `~0UL` trong hàm `shrink_huge_zero_folio_scan()` sau khi một lệnh gọi `get_huge_zero_folio()` đang chạy song song đã thiết lập một giá trị hợp lệ tại đó.

Điều này dẫn đến việc `huge_zero_folio` được đặt đúng, nhưng `huge_zero_pfn` lại bị đặt sai, khiến cho các hàm `is_huge_zero_pfn()` và do đó là `is_huge_zero_pmd()` sẽ nhận diện nhầm folio zero khổng lồ (huge zero folio) thành một folio THP thông thường.

Hậu quả có thể dẫn đến việc folio zero khổng lồ bị tách ra và xử lý sai cách khác.

Giải pháp cho vấn đề này rất tinh vi vì tồn tại đường dẫn nhanh nguyên tử, do đó thứ tự thực thi trên các kiến trúc yếu về tính sắp xếp (weakly ordered architectures) cần được xử lý hết sức cẩn thận.

Commit đầu tiên khắc phục sự cố bằng cách đưa ra một spinlock bao quanh việc ghi vào `huge_zero_[pfn, folio, refcount]`, với sự cân nhắc kỹ lưỡng đối với thứ tự tải/lưu trữ trong đường dẫn nhanh. Nó được đặt ở vị trí đầu tiên và giữ cho kích thước nhỏ nhất có thể để có thể backport độc lập.

Commit thứ hai là một bản làm sạch thuần túy, tái cấu trúc logic `CONFIG_PERSISTENT_HUGE_ZERO_FOLIO` để tách biệt rõ ràng hơn giữa phần logic bền vững (persistent) và phần được phân bổ động.

Patch này (trong tổng số 2 patch):

Nếu không có `CONFIG_PERSISTENT_HUGE_ZERO_FOLIO`, thì `huge_zero_folio` sẽ được đếm tham chiếu bởi `huge_zero_refcount` và trả về qua hàm `mm_get_huge_zero_folio()`.

Khi caller hoàn tất việc sử dụng trang zero khổng lồ, bộ đếm tham chiếu của nó sẽ bị giảm đi. Chỉ có shrinker mới có thể đặt bộ đếm tham chiếu về 0.

Rất tiếc, một lỗi race có thể xảy ra giữa lúc shrinker đang giảm bộ đếm tham chiếu xuống 0 và một page fault đồng thời diễn ra.

Điều này là do `shrink_huge_zero_folio_scan()` có thể, nếu rất không may mắn, bị tiền chế (preempted) trong khoảng thời gian đặt `huge_zero_refcount` về 0 và trước khi ghi một giá trị không hợp lệ.

Trong khoảng thời gian đó, `get_huge_zero_folio()` có thể ghi vào `huge_zero_pfn` trước khi `shrink_huge_zero_folio_scan()` tiếp tục thực thi.

Trong sự kiện này, folio zero khổng lồ sẽ bị nhận diện sai một cách bền vững, khiến đường dẫn mã THP được kích hoạt không đúng cho folio zero khổng lồ:

CPU 0 CPU 1 =======================================|================================= shrink_huge_zero_folio_scan() | atomic_cmpxchg() đặt refcount về 0 | xchg() đặt huge_zero_folio thành NULL | get_huge_zero_folio() | | atomic_inc_not_zero() -> zero bị tiền chế trong thời gian dài | Phân bổ folio zero khổng lồ mới | | Ghi giá trị hợp lệ cho huge_zero_folio v | Ghi giá trị hợp lệ cho huge_zero_pfn Ghi đè lên huge_zero_pfn bằng ~0UL <--- Ghi đè không hợp lệ!

Điều này dẫn đến việc `is_huge_zero_pfn()` và `is_huge_zero_pmd()` trả về sai (false) đối với một trang zero khổng lồ, điều này có thể gây ra các vấn đề như folio zero khổng lồ bị tách ra sai cách.

Lưu ý rằng sự cố nằm ở `huge_zero_pfn` chứ không phải `huge_zero_folio`, vì `get_huge_zero_folio()` sử dụng `cmpxchg()` được khóa dựa trên việc `huge_zero_folio` là NULL, kèm theo vòng lặp thử lại; còn `shrink_huge_zero_folio_scan()` sử dụng `xchg()` để đặt `huge_zero_folio`.

Khắc phục sự cố bằng cách đưa ra một spinlock, `huge_zero_lock`, để ngăn chặn việc ghi đồng thời vào `huge_zero_folio`, `huge_zero_pfn` và `huge_zero_refcount`.

Cần có sự cẩn trọng đáng kể ở đây để đảm bảo tính chính xác:

Đường dẫn nhanh trong `get_huge_zero_folio()` sử dụng `atomic_inc_not_zero()`, nằm ngoài phần đoạn mã quan trọng (critical section), và điều này có nghĩa là việc phân bổ zero khổng lồ được khóa dựa trên `huge_zero_refcount` bằng 0.

Đường dẫn nhanh không sử dụng `huge_zero_lock`, do đó phần đoạn mã quan trọng không liên quan đến nó.

Vì vậy, các bất biến (invariants) là bắt buộc - `huge_zero_refcount` PHẢI:

* Chỉ được đặt trong đoạn mã quan trọng của `huge_zero_lock` để đảm bảo sự tuần tự hóa của `huge_zero_pfn`, `huge_zero_folio` và ---truncated---

Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.

chịu trách nhiệm

Linux

Đặt trước

15/08/2026

Tiết lộ

22/08/2026

Kiểm duyệt

được chấp nhận

EPSS

0.00000

KEV

không

Các hoạt động

rất thấp

Nguồn

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!