[PATCH v2] btrfs: lzo: reject inline extents without compressed data
David Lee <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
inline Btrfs LZO payload shorter than two LZO headers. Fix the validation or lifetime rule at the vulnerable boundary so malformed or racing input cannot reach the faulting path. A four-byte extent produced the following KASAN report on Linux 7.2-rc2: BUG: KASAN: slab-out-of-bounds in lzo_decompress+0x57d/0x700 Read of size 4 at addr ffff888006f2e644 by task btrfs_lzo_inlin/77 Call Trace: <TASK> dump_stack_lvl+0x5b/0x70 print_report+0xd1/0x610 ? _raw_spin_lock_irqsave+0x78/0xc0 ? kasan_complete_mode_report_info+0x2a/0x200 kasan_report+0xe0/0x110 ? lzo_decompress+0x57d/0x700 ? lzo_decompress+0x57d/0x700 __asan_report_load_n_noabort+0x13/0x20 lzo_decompress+0x57d/0x700 ? lzo_decompress_bio+0x1e80/0x1e80 btrfs_decompress+0x140/0x1c0 uncompress_inline+0x147/0x1b0 btrfs_get_extent+0xb23/0x10a0 ? btrfs_rename2+0xb0/0xb0 ? _raw_spin_lock+0x72/0xb0 ? _raw_read_lock_irq+0x50/0x50 ? __kasan_check_read+0x15/0x20 ? btrfs_folio_test_uptodate+0xc8/0x140 btrfs_do_readpage.constprop.0+0x538/0x1ac0 ? btrfs_lookup_ordered_extent+0x2c0/0x2c0 ? xa_load+0xb0/0x1e0 btrfs_readahead+0x32f/0x5f0 ? btrfs_writepages+0x180/0x180 ? lruvec_stat_mod_folio+0x240/0x330 ? write_one_eb+0xb30/0xb30 read_pages+0x16f/0x850 ? __kasan_check_read+0x15/0x20 ? __folio_batch_add_and_move+0x134/0x1c0 ? ractl_alloc_folio.constprop.0+0x90/0x90 ? filemap_add_folio+0x1cd/0x4f0 ? __folio_alloc_noprof+0x69/0xa0 page_cache_ra_unbounded+0x296/0x490 do_page_cache_ra+0xd9/0x130 page_cache_sync_ra+0x3ee/0x6f0 filemap_get_pages+0x306/0x15c0 ? is_bpf_text_address+0x14/0x30 ? kernel_text_address+0x89/0xf0 ? filemap_add_folio+0x4f0/0x4f0 ? putname+0x78/0xc0 filemap_read+0x329/0xd00 ? kasan_save_track+0x18/0x40 ? __kasan_slab_free+0x44/0x60 ? putname+0x78/0xc0 ? entry_SYSCALL_64_after_hwframe+0x4b/0x53 ? filemap_get_pages+0x15c0/0x15c0 btrfs_file_read_iter+0x1f8/0x2b0 vfs_read+0x4ef/0x720 ? putname+0x78/0xc0 ? __kasan_slab_free+0x56/0x60 ? kernel_read+0x180/0x180 ? putname+0x78/0xc0 ? __kasan_check_read+0x15/0x20 ksys_read+0xf8/0x1d0 ? vfs_write+0xa30/0xa30 ? __x64_sys_open+0x180/0x180 __x64_sys_read+0x71/0xb0 ? __kasan_check_read+0x15/0x20 x64_sys_call+0x1ab0/0x1b70 do_syscall_64+0x61/0x470 entry_SYSCALL_64_after_hwframe+0x4b/0x53 </TASK> Link: https://lore.kernel.org/all/[email protected]/ Fixes: a6fa6fae40ec ("btrfs: Add lzo compression support") Assisted-by: Codex:gpt-5.5 Signed-off-by: David Lee <[email protected]> --- Changes in v2: - Reject an eight-byte extent containing headers but no compressed data. - Rebase onto btrfs for-next and update the invalid-header diagnostic. - Include the complete KASAN call trace. Trail of Bits has a reproducer for this bug demonstrating Kernel Panic which can be shared further if needed. fs/btrfs/lzo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c index 1531adb117d1..2f0996692da0 100644 --- a/fs/btrfs/lzo.c +++ b/fs/btrfs/lzo.c @@ -552,9 +552,10 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in, size_t max_segment_len = workspace_buf_length(fs_info); int ret; - if (unlikely(srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)) { + if (unlikely(srclen <= LZO_LEN * 2 || + srclen > max_segment_len + LZO_LEN * 2)) { btrfs_err(fs_info, "invalid lzo header length, has %zu expect (%u, %zu)", - srclen, LZO_LEN, max_segment_len + LZO_LEN * 2); + srclen, LZO_LEN * 2, max_segment_len + LZO_LEN * 2); return -EUCLEAN; } -- 2.43.0