Re: [PATCH v2] btrfs: lzo: reject inline extents without compressed data
Qu Wenruo <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
The new subject line is a little confusing. The patch is not just rejecting empty payload, but also cases where there is not even enough space for needed headers. Something like "reject invalid sized inline extents" would be better. 在 2026/7/15 18:35, David Lee 写道: > inline Btrfs LZO payload shorter than two LZO headers. This is not even a sentence, sorry I didn't point this out in the initial patch. > Fix the validation or lifetime rule So what the "lifetime rule" is? > at the vulnerable boundary so malformed > or racing input cannot reach the faulting path. The same for "racing input". I see no racing behavior. Malformed on-disk data is self-explaining, but "racing input" is not. > > 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 Please remove unrelated stacks which start with a question mark. I have removed the remaining ones as an example. > kasan_report+0xe0/0x110 > __asan_report_load_n_noabort+0x13/0x20 > lzo_decompress+0x57d/0x700 > btrfs_decompress+0x140/0x1c0 > uncompress_inline+0x147/0x1b0 > btrfs_get_extent+0xb23/0x10a0 > btrfs_do_readpage.constprop.0+0x538/0x1ac0 > btrfs_readahead+0x32f/0x5f0 > read_pages+0x16f/0x850 > page_cache_ra_unbounded+0x296/0x490 > do_page_cache_ra+0xd9/0x130 > page_cache_sync_ra+0x3ee/0x6f0 > filemap_get_pages+0x306/0x15c0 > filemap_read+0x329/0xd00 > btrfs_file_read_iter+0x1f8/0x2b0 > vfs_read+0x4ef/0x720 > ksys_read+0xf8/0x1d0 > __x64_sys_read+0x71/0xb0 > x64_sys_call+0x1ab0/0x1b70 > do_syscall_64+0x61/0x470 > entry_SYSCALL_64_after_hwframe+0x4b/0x53 > </TASK> > A very short explanation would help, something like: An inlined lzo compressed extent should have one lzo header (4 bytes), followed by one segment header (4 bytes) then payload. For the 4 bytes sized inline extent, there is no space for the segment header. Without proper validation, reading the segment header will be out the inlined extent. Feel free to use LLM to fix whatever grammar errors in the above example. > Link: https://lore.kernel.org/all/[email protected]/ We do not use Link: just to point back to an older version. We use it for the original bug report (not the patch). > 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; > } > >