git: 9350e9236242 - main - fusefs: fix a panic in vop_close with a CTL consumer
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 15 Jun 2025 15:35:47 UTC
The branch main has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=9350e9236242f51c88b3e5c19ceeae7869b9cf83
commit 9350e9236242f51c88b3e5c19ceeae7869b9cf83
Author: Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-12-18 18:02:34 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2025-06-15 15:35:39 +0000
fusefs: fix a panic in vop_close with a CTL consumer
Kernel consumers like CTL may lack ucred objects. That led to a panic
when CTL closed a fuse file, if atime was enabled on the mountpoint.
Fix it by checking the ucred during close.
PR: 283402
MFC after: 2 weeks
Sponsored by: ConnectWise
Differential Revision: https://reviews.freebsd.org/D48165
---
sys/fs/fuse/fuse_vnops.c | 3 ++
tests/sys/cam/ctl/ctl.subr | 18 ++++++++++--
tests/sys/fs/fusefs/Makefile | 5 ++++
tests/sys/fs/fusefs/ctl.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index d09d86e4f3a1..107e6db299e0 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -796,6 +796,9 @@ fuse_vnop_close(struct vop_close_args *ap)
if (fflag & IO_NDELAY)
return 0;
+ if (cred == NULL)
+ cred = td->td_ucred;
+
err = fuse_flush(vp, cred, pid, fflag);
if (err == 0 && (fvdat->flag & FN_ATIMECHANGE) && !vfs_isrdonly(mp)) {
struct vattr vap;
diff --git a/tests/sys/cam/ctl/ctl.subr b/tests/sys/cam/ctl/ctl.subr
index 868b1c809571..5da441b806f0 100644
--- a/tests/sys/cam/ctl/ctl.subr
+++ b/tests/sys/cam/ctl/ctl.subr
@@ -80,7 +80,20 @@ find_device() {
done
}
-# Create a CTL LUN
+# Create a CTL LUN backed by a file
+create_block() {
+ EXTRA_ARGS=$*
+
+ atf_check -o save:lun-create.txt ctladm create -b block $EXTRA_ARGS
+ atf_check egrep -q "LUN created successfully" lun-create.txt
+ LUN=`awk '/LUN ID:/ {print $NF}' lun-create.txt`
+ if [ -z "$LUN" ]; then
+ atf_fail "Could not find LUN id"
+ fi
+ find_device $LUN
+}
+
+# Create a CTL LUN backed by RAM
create_ramdisk() {
EXTRA_ARGS=$*
@@ -95,7 +108,8 @@ create_ramdisk() {
cleanup() {
if [ -e "lun-create.txt" ]; then
+ backend=`awk '/backend:/ {print $NF}' lun-create.txt`
lun_id=`awk '/LUN ID:/ {print $NF}' lun-create.txt`
- ctladm remove -b ramdisk -l $lun_id > /dev/null
+ ctladm remove -b $backend -l $lun_id > /dev/null
fi
}
diff --git a/tests/sys/fs/fusefs/Makefile b/tests/sys/fs/fusefs/Makefile
index b1ac704ab4f6..b11f11bdfa98 100644
--- a/tests/sys/fs/fusefs/Makefile
+++ b/tests/sys/fs/fusefs/Makefile
@@ -4,6 +4,8 @@ PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sys/fs/fusefs
+ATF_TESTS_SH+= ctl
+
# We could simply link all of these files into a single executable. But since
# Kyua treats googletest programs as plain tests, it's better to separate them
# out, so we get more granular reporting.
@@ -64,6 +66,9 @@ TEST_METADATA.default_permissions+= required_user="unprivileged"
TEST_METADATA.default_permissions_privileged+= required_user="root"
TEST_METADATA.mknod+= required_user="root"
TEST_METADATA.nfs+= required_user="root"
+# ctl must be exclusive because it disables/enables camsim
+TEST_METADATA.ctl+= is_exclusive="true"
+TEST_METADATA.ctl+= required_user="root"
TEST_METADATA+= timeout=10
diff --git a/tests/sys/fs/fusefs/ctl.sh b/tests/sys/fs/fusefs/ctl.sh
new file mode 100644
index 000000000000..7d2e7593cbdc
--- /dev/null
+++ b/tests/sys/fs/fusefs/ctl.sh
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 ConnectWise
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+. $(atf_get_srcdir)/../../cam/ctl/ctl.subr
+
+# Regression test for https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283402
+#
+# Almost any fuse file system would work, but this tests uses fusefs-ext2
+# because it's simple and its download is very small.
+atf_test_case remove_lun_with_atime cleanup
+remove_lun_with_atime_head()
+{
+ atf_set "descr" "Remove a fuse-backed CTL LUN when atime is enabled"
+ atf_set "require.user" "root"
+ atf_set "require.progs" "fuse-ext2 mkfs.ext2"
+}
+remove_lun_with_atime_body()
+{
+ MOUNTPOINT=$PWD/mnt
+ atf_check mkdir $MOUNTPOINT
+ atf_check truncate -s 1g ext2.img
+ atf_check mkfs.ext2 -q ext2.img
+ # Note: both default_permissions and atime must be enabled
+ atf_check fuse-ext2 -o default_permissions,allow_other,rw+ ext2.img \
+ $MOUNTPOINT
+
+ atf_check truncate -s 1m $MOUNTPOINT/file
+ create_block -o file=$MOUNTPOINT/file
+
+ # Force fusefs to open the file, and dirty its atime
+ atf_check dd if=/dev/$dev of=/dev/null count=1 status=none
+
+ # Finally, remove the LUN. Hopefully it won't panic.
+ atf_check -o ignore ctladm remove -b block -l $LUN
+
+ rm lun-create.txt # So we don't try to remove the LUN twice
+}
+remove_lun_with_atime_cleanup()
+{
+ cleanup
+ umount $PWD/mnt
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case remove_lun_with_atime
+}