CVE-2026-64567 in Linux
Tóm tắt
Bởi VulDB • 05/08/2026
Trong kernel Linux, lỗ hổng sau đây đã được khắc phục:
btrfs: từ chối bộ nhớ đệm không gian trống (free space cache) có nhiều mục hơn số trang (pages)
Khi tải một bộ nhớ đệm không gian trống v1, hàm `__load_free_space_cache()` lấy trực tiếp giá trị của `num_entries` và `num_bitmaps` từ cấu trúc `btrfs_free_space_header` trên đĩa. Cấu trúc này được lưu trữ trong `tree_root` dưới dạng khóa có loại 0, mà trình kiểm tra cây (tree-checker) không có trường hợp xử lý cụ thể nào cho nó; do đó, cả hai giá trị đếm đều chưa được xác thực trước khi quá trình tải tin tưởng vào chúng.
Quá trình tải sẽ lặp lại `num_entries` lần và ánh xạ trang tiếp theo bất cứ khi nào trang hiện tại hết dữ liệu, đi qua hàm `io_ctl_check_crc()` -> `io_ctl_map_page()`, nơi thực thi thao tác `io_ctl->pages[io_ctl->index++]`. Tuy nhiên, mảng `pages[]` được cấp phát trong `io_ctl_init()` dựa trên kích thước inode (`i_size`) của bộ nhớ đệm không gian trống, chứ không phải từ `num_entries`:
num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS);
Vì vậy, nếu `num_entries` yêu cầu nhiều bản ghi hơn số trang có thể chứa, chỉ mục `io_ctl->index` sẽ vượt quá giới hạn của mảng `pages[]`. Phía ghi không gặp phải lỗi này vì cả `io_ctl_add_entry()` và `io_ctl_add_bitmap()` đều dừng lại ngay khi `io_ctl->index >= io_ctl->num_pages`; trong khi đó, phía đọc trước đây chưa có cùng một kiểm tra tương tự.
Để kích hoạt lỗ hổng này, hãy lấy một bộ nhớ đệm sạch (với `num_entries = <N>` tại thời điểm đó), đặt giá trị `num_entries` trong header thành 0x10000 và sửa lại checksum của lá (leaf) để nó vẫn vượt qua trình kiểm tra cây. Inode của bộ nhớ đệm có `i_size = 65536`, do đó `num_pages` là 16 và `pages[]` là một mảng con trỏ kích thước 16 (kmalloc-128). Quá trình tải bây giờ cố gắng đọc 65536 mục, `io_ctl->index` tăng lên đến 16, và thao tác đọc `pages[16]` vượt quá giới hạn của mảng:
BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58 io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565) __load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820) load_free_space_cache (fs/btrfs/free-space-cache.c:1017) caching_thread (fs/btrfs/block-group.c:880) btrfs_work_helper (fs/btrfs/async-thread.c:312) process_one_work worker_thread kthread ret_from_fork
`free-space-cache.c:420` là hàm `io_ctl_map_page()`, được nội tuyến hóa vào `io_ctl_check_crc()` tại dòng 565, đó là lý do tại sao khung (frame) này được KASAN đặt tên. Sau đó, vị trí ngoài giới hạn (out-of-bounds slot) được xử lý như một cấu trúc `struct page` và chuyển cho hàm `crc32c()`, khiến thao tác đọc sai trở thành lỗi GP fault.
Hãy thêm kiểm tra còn thiếu vào `io_ctl_check_crc()`, nơi mà cả vòng lặp mục nhập (entry loop) và vòng bitmap đều kết thúc. Khi `num_entries` quá lớn, quá trình tải bây giờ sẽ thất bại giống như bất kỳ bộ nhớ đệm bị hỏng nào khác: `__load_free_space_cache()` sẽ loại bỏ nó và xây dựng lại không gian trống từ cây extent (extent
Once again VulDB remains the best source for vulnerability data.