Re: [PATCH] btrfs: send: reject extents for non-regular inodes

Qu Wenruo <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs,org.kernel.vger.linux-kernel
Message-ID <[email protected]>

在 2026/8/17 22:50, ZhengYuan Huang 写道:
> [BUG]
> A corrupted subvolume tree can leave an EXTENT_DATA item attached to an
> inode whose mode is not S_IFREG or S_IFLNK. During send, such an item can
> be treated as file data and crash through a NULL address_space operation:
> 
>    BUG: kernel NULL pointer dereference, address: 0000000000000000
>    #PF: supervisor instruction fetch in kernel mode
>    #PF: error_code(0x0010) - not-present page
>    Call Trace:
>      <TASK>
>      read_pages+0x80b/0xb30 mm/readahead.c:173
>      page_cache_ra_unbounded+0x40d/0x890 mm/readahead.c:302
>      do_page_cache_ra mm/readahead.c:332 [inline]
>      page_cache_ra_order+0xa16/0xcd0 mm/readahead.c:535
>      page_cache_sync_ra+0x5ce/0x9d0 mm/readahead.c:626
>      page_cache_sync_readahead include/linux/pagemap.h:1379 [inline]
>      put_file_data fs/btrfs/send.c:5224 [inline]
>      send_write fs/btrfs/send.c:5291 [inline]
>      send_extent_data+0x16b2/0x29b0 fs/btrfs/send.c:5715
>      send_write_or_clone fs/btrfs/send.c:6135 [inline]
>      process_extent+0x5d4/0x17b0 fs/btrfs/send.c:6504
>      changed_extent fs/btrfs/send.c:7079 [inline]
>      changed_cb+0x22f9/0x3cd0 fs/btrfs/send.c:7245
>      full_send_tree fs/btrfs/send.c:7318 [inline]
>      send_subvol fs/btrfs/send.c:7910 [inline]
>      btrfs_ioctl_send+0x46a9/0x57f0 fs/btrfs/send.c:8248
>      ...
> 
> [CAUSE]
> process_extent() skips extent items for symlinks but assumes every other
> inode with an extent item is a regular file. For a corrupted non-regular
> inode, btrfs_iget() does not install the regular file address_space
> operations. The readahead fallback can then call a NULL read_folio
> callback before the existing validation in btrfs_get_extent() can run.
> 
> [FIX]
> Reject extent items for inode types other than regular files and symlinks
> at the common send extent-processing boundary. Symlink handling is left
> unchanged because send emits symlink data from read_symlink(). This covers
> full, incremental and new-generation sends without adding a check to the
> regular I/O path.
> 
> Signed-off-by: ZhengYuan Huang <[email protected]>

Reviewed-by: Qu Wenruo <[email protected]>

> ---
>   fs/btrfs/send.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
> index dca3570168c7..f88623bbc491 100644
> --- a/fs/btrfs/send.c
> +++ b/fs/btrfs/send.c
> @@ -6417,6 +6417,13 @@ static int process_extent(struct send_ctx *sctx,
>   
>   	if (S_ISLNK(sctx->cur_inode_mode))
>   		return 0;
> +	if (unlikely(!S_ISREG(sctx->cur_inode_mode))) {
> +		btrfs_crit(sctx->send_root->fs_info,
> +			   "send: extent for non-regular inode %llu root %llu mode 0%llo",
> +			   key->objectid, btrfs_root_id(sctx->send_root),
> +			   sctx->cur_inode_mode & S_IFMT);
> +		return -EUCLEAN;
> +	}
>   
>   	if (sctx->parent_root && !sctx->cur_inode_new) {
>   		ret = is_extent_unchanged(sctx, path, key);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.