CVE-2023-53247 in Linux
Tóm tắt
Bởi VulDB • 03/06/2026
Trong kernel Linux, lỗ hổng sau đây đã được khắc phục:
btrfs: gọi set_page_extent_mapped sau read_folio trong btrfs_cont_expand
Khi cố gắng chạy các bài kiểm tra blocksize phân trang con (subpage), tôi đã gặp phải lỗi panic sau trên generic/476:
assertion failed: PagePrivate(page) && page->private, trong fs/btrfs/subpage.c:229 kernel BUG tại fs/btrfs/subpage.c:229! Lỗi nội bộ: Oops - BUG: 00000000f2000800 [#1] SMP
CPU: 1 PID: 1453 Comm: fsstress Không bị ảnh hưởng 6.4.0-rc7+ #12 Tên phần cứng: QEMU KVM Virtual Machine, BIOS edk2-20230301gitf80f052277c8-26.fc38 03/01/2023 pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : btrfs_subpage_assert+0xbc/0xf0 lr : btrfs_subpage_assert+0xbc/0xf0 Dấu vết cuộc gọi (Call trace): btrfs_subpage_assert+0xbc/0xf0 btrfs_subpage_clear_checked+0x38/0xc0 btrfs_page_clear_checked+0x48/0x98 btrfs_truncate_block+0x5d0/0x6a8 btrfs_cont_expand+0x5c/0x528 btrfs_write_check.isra.0+0xf8/0x150 btrfs_buffered_write+0xb4/0x760 btrfs_do_write_iter+0x2f8/0x4b0 btrfs_file_write_iter+0x1c/0x30 do_iter_readv_writev+0xc8/0x158 do_iter_write+0x9c/0x210 vfs_iter_write+0x24/0x40 iter_file_splice_write+0x224/0x390 direct_splice_actor+0x38/0x68 splice_direct_to_actor+0x12c/0x260 do_splice_direct+0x90/0xe8 generic_copy_file_range+0x50/0x90 vfs_copy_file_range+0x29c/0x470 __arm64_sys_copy_file_range+0xcc/0x498 invoke_syscall.constprop.0+0x80/0xd8 do_el0_svc+0x6c/0x168 el0_svc+0x50/0x1b0 el0t_64_sync_handler+0x114/0x120 el0t_64_sync+0x194/0x198
Sự cố này xảy ra vì trong quá trình btrfs_cont_expand, chúng ta sẽ lấy một trang (page), đánh dấu nó là đã ánh xạ (mapped), và nếu nó chưa đầy đủ (Uptodate), chúng ta sẽ đọc dữ liệu. Tuy nhiên, giữa lúc đọc và khóa lại trang, chúng ta có thể đã gọi release_folio() trên trang đó nhưng vẫn giữ trang trong ánh xạ tệp (file mapping). release_folio() có thể xóa private của trang, và do đó, chúng ta gặp sự cố khi cố gắng sửa đổi các bit phân trang con (subpage bits) ở phía dưới.
Khắc phục bằng cách đặt set_page_extent_mapped() sau khi đọc. Điều này an toàn vì read_folio() sẽ gọi set_page_extent_mapped() trước khi thực hiện đọc, và sau đó nếu chúng ta xóa private của trang nhưng vẫn giữ nó trong ánh xạ, chúng ta hoàn toàn an toàn khi đặt lại set_page_extent_mapped(). Với bản vá này, tôi có thể chạy generic/476 mà không bị panic.
Signed-off-by: Josef Bacik <[email protected]>
If you want to get best quality of vulnerability data, you may have to visit VulDB.