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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <174553065195.1160461.15575039465292160279.stgit@frogsfrogsfrogs>
Date: Thu, 24 Apr 2025 14:44:41 -0700
From: "Darrick J. Wong" <djwong@...nel.org>
To: tytso@....edu
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 15/16] fuse2fs: fix FITRIM validation

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

Fix the validation here to match the kernel, and report the number of
blocks trimmed.

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


diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 420fbfd5db5969..5a6b607ead9b4b 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -3206,17 +3206,27 @@ static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
 {
 	ext2_filsys fs = ff->fs;
 	struct fstrim_range *fr = data;
-	blk64_t start, end, max_blocks, b, cleared;
+	blk64_t start, end, max_blocks, b, cleared, minlen;
+	blk64_t max_blks = ext2fs_blocks_count(fs->super);
 	errcode_t err = 0;
 
+	if (!fs_writeable(fs))
+		return -EROFS;
+
 	start = fr->start / fs->blocksize;
 	end = (fr->start + fr->len - 1) / fs->blocksize;
-	dbg_printf(ff, "%s: start=%llu end=%llu\n", __func__, start, end);
+	minlen = fr->minlen / fs->blocksize;
+
+	if (EXT2FS_NUM_B2C(fs, minlen) > EXT2_CLUSTERS_PER_GROUP(fs->super) ||
+	    start >= max_blks ||
+	    fr->len < fs->blocksize)
+		return -EINVAL;
+
+	dbg_printf(ff, "%s: start=%llu end=%llu minlen=%llu\n", __func__,
+		   start, end, minlen);
 
 	if (start < fs->super->s_first_data_block)
 		start = fs->super->s_first_data_block;
-	if (start >= ext2fs_blocks_count(fs->super))
-		start = ext2fs_blocks_count(fs->super) - 1;
 
 	if (end < fs->super->s_first_data_block)
 		end = fs->super->s_first_data_block;
@@ -3230,17 +3240,23 @@ static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
 	while (start <= end) {
 		err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
 							   start, end, &start);
-		if (err == ENOENT)
-			return 0;
-		else if (err)
+		switch (err) {
+		case 0:
+			break;
+		case ENOENT:
+			/* no free blocks found, so we're done */
+			err = 0;
+			goto out;
+		default:
 			return translate_error(fs, fh->ino, err);
+		}
 
 		b = start + max_blocks < end ? start + max_blocks : end;
 		err =  ext2fs_find_first_set_block_bitmap2(fs->block_map,
 							   start, b, &b);
 		if (err && err != ENOENT)
 			return translate_error(fs, fh->ino, err);
-		if (b - start >= fr->minlen) {
+		if (b - start >= minlen) {
 			err = io_channel_discard(fs->io, start, b - start);
 			if (err)
 				return translate_error(fs, fh->ino, err);
@@ -3250,6 +3266,8 @@ static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
 		start = b + 1;
 	}
 
+out:
+	fr->len = cleared;
 	return err;
 }
 #endif /* FITRIM */


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ