lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <176246795104.2863930.12963756725107811944.stgit@frogsfrogsfrogs>
Date: Thu, 06 Nov 2025 14:41:59 -0800
From: "Darrick J. Wong" <djwong@...nel.org>
To: tytso@....edu
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 3/3] fuse2fs: enable the shutdown ioctl

From: Darrick J. Wong <djwong@...nel.org>

Implement a bastardized version of EXT4_IOC_SHUTDOWN, because the people
who invented the ioctl got the direction wrong, so we can't actually
read the flags.  So all we do is flush the filesystem, clear the
writable flags, and hope that's what the user wanted.

Since we change __FUSE2FS_CHECK_CONTEXT to return an error code on a
shut down filesystem, remove FUSE2FS_CHECK_CONTEXT_RETURN so that
op_destroy always tears everything down and logs the unmount message.
Later on in the iomap patchset this will become critical because we need
to try to close the block device before unmount completes to avoid
problems with fstests.

Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
 misc/fuse2fs.c |   45 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 41 insertions(+), 4 deletions(-)


diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 8d5b705280b72f..51e6b3b1969d62 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -222,6 +222,7 @@ struct fuse2fs_file_handle {
 enum fuse2fs_opstate {
 	F2OP_READONLY,
 	F2OP_WRITABLE,
+	F2OP_SHUTDOWN,
 };
 
 /* Main program context */
@@ -280,7 +281,7 @@ struct fuse2fs {
 		} \
 	} while (0)
 
-#define __FUSE2FS_CHECK_CONTEXT(ff, retcode) \
+#define __FUSE2FS_CHECK_CONTEXT(ff, retcode, shutcode) \
 	do { \
 		if ((ff) == NULL || (ff)->magic != FUSE2FS_MAGIC) { \
 			fprintf(stderr, \
@@ -289,14 +290,17 @@ struct fuse2fs {
 			fflush(stderr); \
 			retcode; \
 		} \
+		if ((ff)->opstate == F2OP_SHUTDOWN) { \
+			shutcode; \
+		} \
 	} while (0)
 
 #define FUSE2FS_CHECK_CONTEXT(ff) \
-	__FUSE2FS_CHECK_CONTEXT((ff), return -EUCLEAN)
+	__FUSE2FS_CHECK_CONTEXT((ff), return -EUCLEAN, return -EIO)
 #define FUSE2FS_CHECK_CONTEXT_DESTROY(ff) \
-	__FUSE2FS_CHECK_CONTEXT((ff), return)
+	__FUSE2FS_CHECK_CONTEXT((ff), return, /* do not return */)
 #define FUSE2FS_CHECK_CONTEXT_INIT(ff) \
-	__FUSE2FS_CHECK_CONTEXT((ff), abort())
+	__FUSE2FS_CHECK_CONTEXT((ff), abort(), abort())
 
 static int __translate_error(ext2_filsys fs, ext2_ino_t ino, errcode_t err,
 			     const char *func, int line);
@@ -4863,6 +4867,36 @@ static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
 }
 #endif /* FITRIM */
 
+#ifndef EXT4_IOC_SHUTDOWN
+# define EXT4_IOC_SHUTDOWN	_IOR('X', 125, __u32)
+#endif
+
+static int ioctl_shutdown(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
+			  void *data)
+{
+	struct fuse_context *ctxt = fuse_get_context();
+	ext2_filsys fs = ff->fs;
+
+	if (!is_superuser(ff, ctxt))
+		return -EPERM;
+
+	err_printf(ff, "%s.\n", _("shut down requested"));
+
+	fuse2fs_mmp_cancel(ff);
+
+	/*
+	 * EXT4_IOC_SHUTDOWN inherited the inverted polarity on the ioctl
+	 * direction from XFS.  Unfortunately, that means we can't implement
+	 * any of the flags.  Flush whatever is dirty and shut down.
+	 */
+	if (ff->opstate == F2OP_WRITABLE)
+		ext2fs_flush2(fs, 0);
+	ff->opstate = F2OP_SHUTDOWN;
+	fs->flags &= ~EXT2_FLAG_RW;
+
+	return 0;
+}
+
 #if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
 static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
@@ -4909,6 +4943,9 @@ static int op_ioctl(const char *path EXT2FS_ATTR((unused)),
 		ret = ioctl_fitrim(ff, fh, data);
 		break;
 #endif
+	case EXT4_IOC_SHUTDOWN:
+		ret = ioctl_shutdown(ff, fh, data);
+		break;
 	default:
 		dbg_printf(ff, "%s: Unknown ioctl %d\n", __func__, cmd);
 		ret = -ENOTTY;


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ