[PATCH 27/29] xfs: make it possible to disable fsverity

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

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Create an experimental ioctl so that we can turn off fsverity.

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_fs_staging.h |    3 ++
 fs/xfs/xfs_fsverity.c          |   73 ++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_fsverity.h          |    3 ++
 fs/xfs/xfs_ioctl.c             |    6 +++
 4 files changed, 85 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_fs_staging.h b/fs/xfs/libxfs/xfs_fs_staging.h
index 899a56a569d50..4c29167a2b190 100644
--- a/fs/xfs/libxfs/xfs_fs_staging.h
+++ b/fs/xfs/libxfs/xfs_fs_staging.h
@@ -229,4 +229,7 @@ struct xfs_map_freesp {
  */
 #define XFS_IOC_MAP_FREESP	_IOWR('X', 64, struct xfs_map_freesp)
 
+/* Turn off fs-verity */
+#define FS_IOC_DISABLE_VERITY	_IO('f', 133)
+
 #endif /* __XFS_FS_STAGING_H__ */
diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c
index bfa5c70beec24..f57d8acbd858a 100644
--- a/fs/xfs/xfs_fsverity.c
+++ b/fs/xfs/xfs_fsverity.c
@@ -792,3 +792,76 @@ const struct fsverity_operations xfs_fsverity_ops = {
 	.drop_merkle_tree_block		= xfs_fsverity_drop_merkle,
 	.fail_validation		= xfs_fsverity_fail_validation,
 };
+
+/* Turn off fs-verity. */
+int
+xfs_fsverity_disable(
+	struct file		*file)
+{
+	struct inode		*inode = file_inode(file);
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_trans	*tp;
+	u64			merkle_tree_size;
+	unsigned int		merkle_blocksize;
+	int			error;
+
+	BUILD_BUG_ON(FS_IOC_DISABLE_VERITY == FS_IOC_ENABLE_VERITY);
+
+	if (!xfs_has_verity(mp))
+		return -EOPNOTSUPP;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+	if (!IS_VERITY(inode)) {
+		error = 0;
+		goto out_iolock;
+	}
+
+	if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) {
+		error = -EBUSY;
+		goto out_iolock;
+	}
+
+	error = xfs_qm_dqattach(ip);
+	if (error)
+		goto out_iolock;
+
+	error = fsverity_merkle_tree_geometry(inode, &merkle_blocksize,
+			&merkle_tree_size);
+	if (error)
+		goto out_iolock;
+
+	xfs_fsverity_cache_drop(ip);
+
+	/* Clear fsverity inode flag */
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange, 0, 0, false,
+			&tp);
+	if (error)
+		goto out_iolock;
+
+	ip->i_diflags2 &= ~XFS_DIFLAG2_VERITY;
+
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+	xfs_trans_set_sync(tp);
+
+	error = xfs_trans_commit(tp);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	if (error)
+		goto out_iolock;
+
+	inode->i_flags &= ~S_VERITY;
+	fsverity_cleanup_inode(inode);
+
+	/* Remove the fsverity xattrs. */
+	error = xfs_fsverity_delete_metadata(ip, merkle_tree_size,
+			merkle_blocksize);
+	if (error)
+		goto out_iolock;
+
+out_iolock:
+	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+	return error;
+}
diff --git a/fs/xfs/xfs_fsverity.h b/fs/xfs/xfs_fsverity.h
index 21ba0d82f26d8..4b9fff6b0d2c4 100644
--- a/fs/xfs/xfs_fsverity.h
+++ b/fs/xfs/xfs_fsverity.h
@@ -17,6 +17,8 @@ struct xfs_icwalk;
 int xfs_fsverity_scan_inode(struct xfs_inode *ip, struct xfs_icwalk *icw);
 
 extern const struct fsverity_operations xfs_fsverity_ops;
+
+int xfs_fsverity_disable(struct file *file);
 #else
 # define xfs_fsverity_cache_init(ip)		((void)0)
 # define xfs_fsverity_cache_drop(ip)		((void)0)
@@ -24,6 +26,7 @@ extern const struct fsverity_operations xfs_fsverity_ops;
 # define xfs_fsverity_register_shrinker(mp)	(0)
 # define xfs_fsverity_unregister_shrinker(mp)	((void)0)
 # define xfs_fsverity_scan_inode(ip, icw)	(0)
+# define xfs_fsverity_disable(ip)			(-EOPNOTSUPP)
 #endif	/* CONFIG_FS_VERITY */
 
 #endif	/* __XFS_FSVERITY_H__ */
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 0aa0ceb9ec153..24deaaf5eb0f5 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -44,6 +44,7 @@
 #include "xfs_file.h"
 #include "xfs_exchrange.h"
 #include "xfs_rtgroup.h"
+#include "xfs_fsverity.h"
 
 #include <linux/mount.h>
 #include <linux/namei.h>
@@ -2712,6 +2713,11 @@ xfs_file_ioctl(
 	case XFS_IOC_MAP_FREESP:
 		return xfs_ioc_map_freesp(filp, arg);
 
+#ifdef CONFIG_XFS_EXPERIMENTAL_IOCTLS
+	case FS_IOC_DISABLE_VERITY:
+		return xfs_fsverity_disable(filp);
+#endif
+
 	case FS_IOC_ENABLE_VERITY:
 		if (!xfs_has_verity(mp))
 			return -EOPNOTSUPP;





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux