[PATCH experimental-tests] erofs-utils: tests: test FUSE error handling on corrupted inodes

Nithurshen nithurshen.dev at gmail.com
Mon Mar 30 15:28:01 AEDT 2026


This patch introduces a regression test (erofs/099) to verify that
the FUSE daemon gracefully handles corrupted inodes without crashing
or violating the FUSE protocol.

Recently, a bug was identified where erofs_read_inode_from_disk()
would fail, but erofsfuse_getattr() lacked a return statement
after sending an error reply. This caused a fall-through, sending
a second reply via fuse_reply_attr() and triggering a libfuse
segmentation fault.

To prevent future regressions, this test:
1. Creates a valid EROFS image.
2. Surgically corrupts the root inode (injecting random data at
   offset 1152) while leaving the superblock intact so it mounts.
3. Mounts the image in the foreground to capture daemon stderr.
4. Runs 'stat' to trigger the inode read failure.
5. Evaluates the stderr log to ensure no segfaults, aborts, or
   "multiple replies" warnings are emitted by libfuse.

Signed-off-by: Nithurshen <nithurshen.dev at gmail.com>
---
 tests/Makefile.am   |  3 ++
 tests/erofs/099     | 76 +++++++++++++++++++++++++++++++++++++++++++++
 tests/erofs/099.out |  2 ++
 3 files changed, 81 insertions(+)
 create mode 100755 tests/erofs/099
 create mode 100644 tests/erofs/099.out

diff --git a/tests/Makefile.am b/tests/Makefile.am
index e376d6a..c0f117c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -122,6 +122,9 @@ TESTS += erofs/027
 # 028 - test inode page cache sharing functionality
 TESTS += erofs/028
 
+# 099 - test fuse error handling on truncated images
+TESTS += erofs/099
+
 EXTRA_DIST = common/rc erofs
 
 clean-local: clean-local-check
diff --git a/tests/erofs/099 b/tests/erofs/099
new file mode 100755
index 0000000..952bdbd
--- /dev/null
+++ b/tests/erofs/099
@@ -0,0 +1,76 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Test FUSE daemon error handling on corrupted inodes (missing return fix)
+#
+seq=`basename $0`
+seqres=$RESULT_DIR/$(echo $0 | awk '{print $((NF-1))"/"$NF}' FS="/")
+
+# get standard environment, filters and checks
+. "${srcdir}/common/rc"
+
+cleanup()
+{
+	cd /
+	rm -rf $tmp.*
+	# Ensure we kill our background daemon if it's still alive
+	[ -n "$fuse_pid" ] && kill -9 $fuse_pid 2>/dev/null
+}
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+echo "QA output created by $seq"
+
+[ -z "$EROFSFUSE_PROG" ] && _notrun "erofsfuse is not available"
+
+if [ -z $SCRATCH_DEV ]; then
+	SCRATCH_DEV=$tmp/erofs_$seq.img
+	rm -f SCRATCH_DEV
+fi
+
+localdir="$tmp/$seq"
+rm -rf $localdir
+mkdir -p $localdir
+
+echo "test data" > $localdir/testfile
+
+_scratch_mkfs $localdir >> $seqres.full 2>&1 || _fail "failed to mkfs"
+
+# Corrupt the root inode to force erofs_read_inode_from_disk to fail.
+dd if=/dev/urandom of=$SCRATCH_DEV bs=1 seek=1152 count=1024 conv=notrunc >> $seqres.full 2>&1
+
+# Bypass _scratch_mount to run erofsfuse in the foreground (-f) 
+# This lets us capture libfuse's internal stderr warnings.
+$EROFSFUSE_PROG -f $SCRATCH_DEV $SCRATCH_MNT > $tmp/fuse_err.log 2>&1 &
+fuse_pid=$!
+
+# Wait for the mount to establish
+sleep 1
+
+# Attempt to stat the root directory.
+timeout 5 stat $SCRATCH_MNT >> $seqres.full 2>&1
+res=$?
+
+# Clean up the mount
+umount $SCRATCH_MNT >> $seqres.full 2>&1
+
+# Wait for the daemon to cleanly exit, or kill it if stuck
+kill $fuse_pid 2>/dev/null
+wait $fuse_pid 2>/dev/null
+
+cat $tmp/fuse_err.log >> $seqres.full
+
+# Evaluate the results based on the captured stderr and timeout
+if [ $res -eq 124 ]; then
+	_fail "stat command timed out (macFUSE daemon hung due to double reply)"
+elif grep -q -i "multiple replies" $tmp/fuse_err.log; then
+	_fail "Bug detected: libfuse reported multiple replies to request"
+elif grep -q -i "segmentation fault\|aborted" $tmp/fuse_err.log; then
+	_fail "Bug detected: FUSE daemon crashed"
+fi
+
+echo Silence is golden
+status=0
+exit 0
\ No newline at end of file
diff --git a/tests/erofs/099.out b/tests/erofs/099.out
new file mode 100644
index 0000000..4f36820
--- /dev/null
+++ b/tests/erofs/099.out
@@ -0,0 +1,2 @@
+QA output created by 099
+Silence is golden
-- 
2.52.0



More information about the Linux-erofs mailing list