Re: [PATCH] btrfs: new test for logical inode resolution panic

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]





On 2022/12/16 16:46, Zorro Lang wrote:
On Wed, Dec 14, 2022 at 03:12:01PM -0800, Boris Burkov wrote:
If we create a file that has an inline extent followed by a prealloc
extent, then attempt to use the logical to inode ioctl on the prealloc
extent, but in the overwritten range, backref resolution will process
the inline extent. Depending on the leaf eb layout, this can panic.
Add a new test for this condition. In the long run, we can add spew when
we read out-of-bounds fields of inline extent items and simplify this
test to look for dmesg warnings rather than trying to force a fairly
fragile panic (dependent on non-standardized details of leaf layout).

The test causes a kernel panic unless:
btrfs: fix logical_ino ioctl panic

Hi,

Thanks for this new case.

Is this patch merged, does it has a commit id? BTW, please mark this
known issue by _fixed_by_kernel_commit in case source code.

This fix is not yet merged, but I believe it would soon get merged:

https://patchwork.kernel.org/project/linux-btrfs/patch/80f01f297721481fd0d4cbf03fd2550e25b578fb.1671058852.git.boris@xxxxxx/


is applied to the kernel.

Signed-off-by: Boris Burkov <boris@xxxxxx>
---
  tests/btrfs/279     | 95 +++++++++++++++++++++++++++++++++++++++++++++
  tests/btrfs/279.out |  2 +
  2 files changed, 97 insertions(+)
  create mode 100755 tests/btrfs/279
  create mode 100644 tests/btrfs/279.out

diff --git a/tests/btrfs/279 b/tests/btrfs/279
new file mode 100755
index 00000000..ef77f84b
--- /dev/null
+++ b/tests/btrfs/279

btrfs/279 was just token last weekend, please help to rebase to the latest
fstests for-next branch, or change the 279 to a big enough number which won't
cause conflict (I'll give it a proper number when merge it).

@@ -0,0 +1,95 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2022 Meta Platforms, Inc.  All Rights Reserved.
+#
+# FS QA Test 279
+#
+# Given a file with extents:
+# [0 : 4096) (inline)
+# [4096 : N] (prealloc)
+# if a user uses the ioctl BTRFS_IOC_LOGICAL_INO[_V2] asking for the file of the
+# non-inline extent, it results in reading the offset field of the inline
+# extent, which is meaningless (it is full of user data..). If we are
+# particularly lucky, it can be past the end of the extent buffer, resulting in
+# a crash.
+#
+. ./common/preamble
+_begin_fstest auto quick
+
+# Import common functions.
+. ./common/filter
+. ./common/dmlogwrites

Does this case really use helpers in above two included files?

+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs btrfs
+_require_scratch
+_require_xfs_io_command "falloc"

Add this case to prealloc or preallocrw group

+_require_xfs_io_command "fsync"
+_require_xfs_io_command "pwrite"
+
+dump_tree() {
+	$BTRFS_UTIL_PROG inspect-internal dump-tree $SCRATCH_DEV

_require_btrfs_command inspect-internal dump-tree

+}
+
+get_extent_data() {
+	local ino=$1
+	dump_tree $SCRATCH_DEV | grep -A4 "($ino EXTENT_DATA "
+}
+
+get_prealloc_offset() {
+	local ino=$1
+	get_extent_data $ino | grep "disk byte" | awk '{print $5}'
+}
+
+# This test needs to create conditions s.t. the special inode's inline extent
+# is the first item in a leaf. Therefore, fix a leaf size and add
+# items that are otherwise not necessary to reproduce the inline-prealloc
+# condition to get to such a state.
+#
+# Roughly, the idea for getting the right item fill is to:
+# 1. create an extra file with a variable sized inline extent item
+# 2. create our evil file that will cause the panic
+# 3. create a whole bunch of files to create a bunch of dir/index items
+# 4. size the variable extent item s.t. the evil extent item is item 0 in the
+#    next leaf
+#
+# We do it in this somewhat convoluted way because the dir and index items all
+# come before any inode, inode_ref, or extent_data items. So we can predictably
+# create a bunch of them, then sneak in a funny sized extent to round out the
+# difference.
+
+_scratch_mkfs "--nodesize 16k" >/dev/null

We recommend calling _fail at here if _scratch_mkfs fails with a *specified*
option.

_scratch_mkfs "--nodesize 16k" >>$seqres.full || _fail "mkfs failed"

+_scratch_mount
+
+f=$SCRATCH_MNT/f
+
+# the variable extra "leaf padding" file
+$XFS_IO_PROG -fc "pwrite -q 0 700" $f.pad
+
+# the evil file with an inline extent followed by a prealloc extent
+# created by falloc with keep-size, then two non-truncating writes to the front
+touch $f.evil

Not sure if you reall use this touch command as you've used "-f" option for
xfs_io.

+$XFS_IO_PROG -fc "falloc -k 0 1m" $f.evil
+$XFS_IO_PROG -fc fsync $f.evil
+ino=$(stat -c '%i' $f.evil)
+logical=$(get_prealloc_offset $ino)
+$XFS_IO_PROG -fc "pwrite -q 0 23" $f.evil
+$XFS_IO_PROG -fc fsync $f.evil
+$XFS_IO_PROG -fc "pwrite -q 0 23" $f.evil
+$XFS_IO_PROG -fc fsync $f.evil

xfs_io commands can be combined in one line, to make the code looks clear (except
you hope the fd closed after each command done) E.g:

$XFS_IO_PROG -fc "falloc -k 0 1m" -c fsync $f.evil
ino=$(stat -c '%i' $f.evil)
logical=$(get_prealloc_offset $ino)
$XFS_IO_PROG -c "pwrite -q 0 23" -c fsync \
	     -c "pwrite -q 0 23" -c fsync \
	     $f.evil

+sync
+
+# a bunch of inodes to stuff dir items in front of the extent items
+for i in $(seq 122); do
+	$XFS_IO_PROG -fc "pwrite -q 0 8192" $f.$i
+done
+sync
+
+btrfs inspect-internal logical-resolve $logical $SCRATCH_MNT | _filter_scratch
    ^^
    $BTRFS_UTIL_PROG

_require_btrfs_command inspect-internal logical-resolve

The .out file only has "Silence is golden", what's this _filter_scratch used for?

+_scratch_unmount

Is the ending _scratch_unmount useful?

+
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/279.out b/tests/btrfs/279.out
new file mode 100644
index 00000000..c5906093
--- /dev/null
+++ b/tests/btrfs/279.out
@@ -0,0 +1,2 @@
+QA output created by 279
+Silence is golden
--
2.38.1





[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux