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>] [day] [month] [year] [list]
Message-Id: <20181021135520.31566-1-tytso@mit.edu>
Date:   Sun, 21 Oct 2018 09:55:20 -0400
From:   Theodore Ts'o <tytso@....edu>
To:     Ext4 Developers List <linux-ext4@...r.kernel.org>
Cc:     Theodore Ts'o <tytso@....edu>
Subject: [PATCH] libext2fs: refactor code which fixes up the checksums in an extent tree

The code to recalculate the checksums in an extent tree (which is
needed after an inode is relocated so it has a different inode number)
was duplicated in tune2fs and resize2fs.  In addition, this work could
be done in a much more efficient way inside lib/ext2fs/extent.c.

This commit creates a new library function which corrects the
checksums in an inode's extent tree, named: ext2fs_fix_extents_checksums()

Signed-off-by: Theodore Ts'o <tytso@....edu>
---
 lib/ext2fs/ext2fs.h |  4 ++-
 lib/ext2fs/extent.c | 48 ++++++++++++++++++++++++++++++++++++
 misc/tune2fs.c      | 60 +--------------------------------------------
 resize/resize2fs.c  | 56 ++----------------------------------------
 4 files changed, 54 insertions(+), 114 deletions(-)

diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 185be5df5..a5fc90a9e 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1295,7 +1295,9 @@ extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
 extern errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle,
 				     int leaf_level, blk64_t blk);
 extern errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle);
-size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino,
+					      struct ext2_inode *inode);
 
 /* fallocate.c */
 #define EXT2_FALLOCATE_ZERO_BLOCKS	(0x1)
diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
index a9cdae797..ac3dbfec9 100644
--- a/lib/ext2fs/extent.c
+++ b/lib/ext2fs/extent.c
@@ -1737,6 +1737,54 @@ size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle)
 	return last_result;
 }
 
+errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino,
+				       struct ext2_inode *inode)
+{
+	ext2_extent_handle_t	handle;
+	struct ext2fs_extent	extent;
+	errcode_t		errcode;
+	int    			save_flags = fs->flags;
+
+	if (!ext2fs_has_feature_metadata_csum(fs->super) ||
+	    (inode && !(inode->i_flags & EXT4_EXTENTS_FL)))
+		return 0;
+
+	errcode = ext2fs_extent_open2(fs, ino, inode, &handle);
+	if (errcode) {
+		if (errcode == EXT2_ET_INODE_NOT_EXTENT)
+			errcode = 0;
+		return errcode;
+	}
+
+	fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
+	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
+	if (errcode)
+		goto out;
+
+	do {
+		/* Skip to the end of a block of leaf nodes */
+		if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
+			errcode = ext2fs_extent_get(handle,
+						    EXT2_EXTENT_LAST_SIB,
+						    &extent);
+			if (errcode)
+				break;
+		}
+
+		errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent);
+		if (errcode == EXT2_ET_EXTENT_CSUM_INVALID)
+			errcode = update_path(handle);
+	} while (errcode == 0);
+
+out:
+	/* Ok if we run off the end */
+	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
+		errcode = 0;
+	ext2fs_extent_free(handle);
+	fs->flags = save_flags;
+	return errcode;
+}
+
 #ifdef DEBUG
 /*
  * Override debugfs's prompt
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index a680b461c..616bdc630 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -497,64 +497,6 @@ static void convert_64bit(ext2_filsys fs, int direction)
 		fprintf(stderr, _("' to disable 64-bit mode.\n"));
 }
 
-/* Rewrite extents */
-static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino,
-				 struct ext2_inode *inode)
-{
-	ext2_extent_handle_t	handle;
-	struct ext2fs_extent	extent;
-	errcode_t		errcode;
-	struct ext2_extent_info	info;
-
-	if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
-	    !ext2fs_has_feature_metadata_csum(fs->super))
-		return 0;
-
-	errcode = ext2fs_extent_open(fs, ino, &handle);
-	if (errcode)
-		return errcode;
-
-	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
-	if (errcode)
-		goto out;
-
-	do {
-		errcode = ext2fs_extent_get_info(handle, &info);
-		if (errcode)
-			break;
-
-		/*
-		 * If this is the first extent in an extent block that we
-		 * haven't visited, rewrite the extent to force the ETB
-		 * checksum to be rewritten.
-		 */
-		if (info.curr_entry == 1 && info.curr_level != 0 &&
-		    !(extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)) {
-			errcode = ext2fs_extent_replace(handle, 0, &extent);
-			if (errcode)
-				break;
-		}
-
-		/* Skip to the end of a block of leaf nodes */
-		if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
-			errcode = ext2fs_extent_get(handle,
-						    EXT2_EXTENT_LAST_SIB,
-						    &extent);
-			if (errcode)
-				break;
-		}
-
-		errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent);
-	} while (errcode == 0);
-
-out:
-	/* Ok if we run off the end */
-	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
-		errcode = 0;
-	ext2fs_extent_free(handle);
-	return errcode;
-}
-
 /*
  * Rewrite directory blocks with checksums
  */
@@ -849,7 +791,7 @@ static void rewrite_one_inode(struct rewrite_context *ctx, ext2_ino_t ino,
 	if (retval)
 		fatal_err(retval, "while writing inode");
 
-	retval = rewrite_extents(ctx->fs, ino, inode);
+	retval = ext2fs_fix_extents_checksums(ctx->fs, ino, inode);
 	if (retval)
 		fatal_err(retval, "while rewriting extents");
 
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 38032e5c3..c2e10471b 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -1927,59 +1927,6 @@ out:
 	return err;
 }
 
-/* Rewrite extents */
-static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino)
-{
-	ext2_extent_handle_t	handle;
-	struct ext2fs_extent	extent;
-	errcode_t		errcode;
-	struct ext2_extent_info	info;
-
-	errcode = ext2fs_extent_open(fs, ino, &handle);
-	if (errcode)
-		return errcode;
-
-	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
-	if (errcode)
-		goto out;
-
-	do {
-		errcode = ext2fs_extent_get_info(handle, &info);
-		if (errcode)
-			break;
-
-		/*
-		 * If this is the first extent in an extent block that we
-		 * haven't visited, rewrite the extent to force the ETB
-		 * checksum to be rewritten.
-		 */
-		if (info.curr_entry == 1 && info.curr_level != 0 &&
-		    !(extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)) {
-			errcode = ext2fs_extent_replace(handle, 0, &extent);
-			if (errcode)
-				break;
-		}
-
-		/* Skip to the end of a block of leaf nodes */
-		if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
-			errcode = ext2fs_extent_get(handle,
-						    EXT2_EXTENT_LAST_SIB,
-						    &extent);
-			if (errcode)
-				break;
-		}
-
-		errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent);
-	} while (errcode == 0);
-
-out:
-	/* Ok if we run off the end */
-	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
-		errcode = 0;
-	ext2fs_extent_free(handle);
-	return errcode;
-}
-
 static void quiet_com_err_proc(const char *whoami EXT2FS_ATTR((unused)),
 			       errcode_t code EXT2FS_ATTR((unused)),
 			       const char *fmt EXT2FS_ATTR((unused)),
@@ -2276,7 +2223,8 @@ remap_blocks:
 		/* Fix up extent block checksums with the new inode number */
 		if (ext2fs_has_feature_metadata_csum(rfs->old_fs->super) &&
 		    (inode->i_flags & EXT4_EXTENTS_FL)) {
-			retval = rewrite_extents(rfs->old_fs, new_inode);
+			retval = ext2fs_fix_extents_checksums(rfs->old_fs,
+							      new_inode, NULL);
 			if (retval)
 				goto errout;
 		}
-- 
2.18.0.rc0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ