CVE-2026-80734 in Linux
الملخص
بحسب VulDB • 03/09/2026
في نواة لينكس، تم إصلاح الثغرة التالية:
btrfs: تهيئة أعلام تعيين الـ inode للـ inodes المخزنة مؤقتاً (cached)
[الخلل]
عند تشغيل الاختبار generic/795 بحجم كتلة 8K وحجم صفحة 4K، يفشل الاختبار دائماً، مما يؤدي إلى تفعيل بعض دوال ASSERT() المتعلقة بحجم folio:
795 (241074): drop_caches: 3 assertion failed: IS_ALIGNED(start, blocksize) && IS_ALIGNED(end + 1, blocksize), in extent_io.c:1404 (blocksize=8192 root=262 ino=258 start=16826368 end=16830463 mapping min order=0) ------------[ cut here ]------------
kernel BUG at extent_io.c:1404! Oops: invalid opcode: 0000 [#1] SMP
CPU: 8 UID: 0 PID: 241105 Comm: fsstress Tainted: G OE 7.2.0-rc5-custom+ #442 PREEMPT(full) f4bfb352566f3949f29c233ce6f735050a03b245 Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022 RIP: 0010:assert_folio_range.cold+0x3d/0x3f [btrfs]
Call Trace: <TASK> btrfs_read_folio+0x9e/0x170 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
prepare_one_folio.constprop.0+0x104/0x2a0 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
btrfs_buffered_write+0x285/0xa50 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
btrfs_do_write_iter+0x1aa/0x210 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
iter_file_splice_write+0x31a/0x540 direct_splice_actor+0x53/0x170 splice_direct_to_actor+0xe9/0x240 do_splice_direct+0x76/0xb0 vfs_copy_file_range+0x1fd/0x630 __x64_sys_copy_file_range+0xf9/0x220 do_syscall_64+0xe1/0x790 entry_SYSCALL_64_after_hwframe+0x4b/0x53 </TASK> ---[ end trace 0000000000000000 ]---
تمت إضافة دالة ASSERT() نفسها بواسطة تحديث لاحق. يتم إحداث الانهيار باستخدام هذا التحديث الجديد الخاص بالتصحيح (debug patch)، وبدون الإصلاح الحالي.
[السبب]
في الحالة المذكورة أعلاه، يكون العنوان 16826368 متوافقاً بشكل صحيح مع حجم كتلة 8K، لكن النهاية (16830463 + 1) ليست متوافقة مع حجم كتلة 8K. علاوة على ذلك، فإن الترتيب الأدنى لـ folio في الـ mapping هو 0، وليس القيمة المتوقعة وهي 1 لحجم كتلة 8K مع حجم صفحة 4K.
هذا يعني أن بعض الـ inodes لا يتم استدعاء دالة btrfs_set_inode_mapping_order() عليها.
يحدث استدعاء dالة btrfs_set_inode_mapping_order() المفقود للـ inodes المخزنة مؤقتاً (cached) من خلال الأحداث التالية:
- استدعاء بروتوكول btrfs_create_new_inode() لـ inode X والذي يضبط بشكل صحيح الترتيب الأدنى لـ folio الخاص بـ VFS inode.
- استدعاء دالة btrfs_update_inode() لـ inode X والتي تستدعي dالة btrfs_delayed_update_inode() لإنشاء delayed_node داخل مجموعة xarray الخاصة بـ root->delayed_nodes.
- إفراغ الذاكرة/ضغط التخزين المؤقت، مما يؤدي إلى إخراج (evicting) inode X من الذاكرة والذي قام بإخراج inode X، لكن delayed_node لا يزال موجوداً في root->delayed_nodes لإعادة استخدامه مستقبلاً.
- استدعاء بروتوكول btrfs_iget() لـ inode X مرة أخرى
btrfs_iget() |- btrfs_iget_locked() | |- iget5_locked_rcu() | والذي ينشئ vfs_inode جديدًا لـ btrfs، لا يزال الـ mapping الخاص به يحتوي على الترتيب الأدنى كقيمة 0. | |- btrfs_read_locked_inode() |- btrfs_fill_inode() | |- btrfs_get_delayed_node() | والذي يجد العقدة السابقة ويستخدم ذلك delayed_node لتهيئة inode الجديد. | |- filled = true; |- if (filled) goto cache_index; والتي تتخطى استدعاءات dالة btrfs_update_inode_mapping_flags() وdالة btrfs_set_inode_mapping_order(). لذا لا يزال الـ inode يحتوي على الترتيب الأدنى لـ folio مضبوطاً كقيمة 0، وليس القيمة المطلوبة وهي 1.
وبالتالي، فإن قراءة ذاكرة التخزين المؤقت (page cache) لاحقاً ستحصل على folio يكون حجمه أصغر من حجم الكتلة، نظراً لأن الـ mapping يحتوي على الترتيب الأدنى لـ folio مضبوطاً كقيمة 0 بدلاً من 1، مما يؤدي إلى تفعيل دالة ASSERT().
[الإصلاح]
نقل استدعاءات dالتين btrfs_update_inode_mapping_flags() وbtrfs_set_inode_mapping_order() تحت تسمية (label) cache_index، بحيث يتم ضبط أعلام الـ mapping والترتيب الأدنى لـ folio دائماً بغض النظر عما إذا كان لدينا inode مخزن مؤقتاً.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.