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  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Wed, 31 Oct 2007 20:54:13 +0100
From:	Jan Kara <jack@...e.cz>
To:	Theodore Tso <tytso@....edu>
Cc:	linux-ext4@...r.kernel.org
Subject: [PATCH] e2fsprogs: handle rec_len in case of 64KB blocks

  Hi Ted,

  I haven't got any answer from you regarding this patch implementing
hadling of rec_len for 64KB block size. Is it still waiting in your queue
to review or did it just get lost? Since all the kernel changes will be in
2.6.24, we should have tools for that too...  Please write me if there are
any problems with the patch.
								Honza
-- 
Jan Kara <jack@...e.cz>
SUSE Labs, CR
---


Subject: Support for 64KB blocksize in ext2-4 directories.

When block size is 64KB, we have to take care that rec_len does not overflow.
Kernel stores 0xffff in case 0x10000 should be stored - perform appropriate
conversion when reading from / writing to disk.

Signed-off-by: Jan Kara <jack@...e.cz>

diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index fb20fa0..628bf93 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -38,9 +38,9 @@ errcode_t ext2fs_read_dir_block2(ext2_fi
 		dirent = (struct ext2_dir_entry *) p;
 #ifdef WORDS_BIGENDIAN
 		dirent->inode = ext2fs_swab32(dirent->inode);
-		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
 		dirent->name_len = ext2fs_swab16(dirent->name_len);
 #endif
+		dirent->rec_len = ext2fs_rec_len_from_disk(dirent->rec_len);
 		name_len = dirent->name_len;
 #ifdef WORDS_BIGENDIAN
 		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
@@ -68,12 +68,15 @@ errcode_t ext2fs_read_dir_block(ext2_fil
 errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
 				  void *inbuf, int flags EXT2FS_ATTR((unused)))
 {
-#ifdef WORDS_BIGENDIAN
 	errcode_t	retval;
 	char		*p, *end;
 	char		*buf = 0;
 	struct ext2_dir_entry *dirent;
 
+#ifndef WORDS_BIGENDIAN
+	if (fs->blocksize < EXT2_MAX_REC_LEN)
+		goto just_write;
+#endif
 	retval = ext2fs_get_mem(fs->blocksize, &buf);
 	if (retval)
 		return retval;
@@ -89,7 +92,7 @@ errcode_t ext2fs_write_dir_block2(ext2_f
 		}
 		p += dirent->rec_len;
 		dirent->inode = ext2fs_swab32(dirent->inode);
-		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+		dirent->rec_len = ext2fs_rec_len_to_disk(dirent->rec_len);
 		dirent->name_len = ext2fs_swab16(dirent->name_len);
 
 		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
@@ -98,9 +101,8 @@ errcode_t ext2fs_write_dir_block2(ext2_f
  	retval = io_channel_write_blk(fs->io, block, 1, buf);
 	ext2fs_free_mem(&buf);
 	return retval;
-#else
+just_write:
  	return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
-#endif
 }
 
 
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index a316665..2041f0f 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -717,6 +717,32 @@ struct ext2_dir_entry_2 {
 #define EXT2_DIR_ROUND			(EXT2_DIR_PAD - 1)
 #define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
 					 ~EXT2_DIR_ROUND)
+#define EXT2_MAX_REC_LEN		((1<<16)-1)
+
+static inline unsigned ext2fs_rec_len_from_disk(unsigned len)
+{
+#ifdef WORDS_BIGENDIAN
+	len = ext2fs_swab16(dlen);
+#endif
+	if (len == EXT2_MAX_REC_LEN)
+		return 1 << 16;
+	return len;
+}
+
+static inline unsigned ext2fs_rec_len_to_disk(unsigned len)
+{
+	if (len == (1 << 16))
+#ifdef WORDS_BIGENDIAN
+		return ext2fs_swab16(EXT2_MAX_REC_LEN);
+#else
+		return EXT2_MAX_REC_LEN;
+#endif
+#ifdef WORDS_BIGENDIAN
+	return ext2fs_swab_16(len);
+#else
+	return len;
+#endif
+}
 
 /*
  * This structure will be used for multiple mount protection. It will be
diff --git a/misc/e2image.c b/misc/e2image.c
index 1fbb267..4e2c9fb 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -345,10 +345,7 @@ static void scramble_dir_block(ext2_fils
 	end = buf + fs->blocksize;
 	for (p = buf; p < end-8; p += rec_len) {
 		dirent = (struct ext2_dir_entry_2 *) p;
-		rec_len = dirent->rec_len;
-#ifdef WORDS_BIGENDIAN
-		rec_len = ext2fs_swab16(rec_len);
-#endif
+		rec_len = ext2fs_rec_len_from_disk(dirent->rec_len);
 #if 0
 		printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
 #endif
@@ -358,9 +355,7 @@ static void scramble_dir_block(ext2_fils
 			       "bad rec_len (%d)\n", (unsigned long) blk, 
 			       rec_len);
 			rec_len = end - p;
-#ifdef WORDS_BIGENDIAN
-				dirent->rec_len = ext2fs_swab16(rec_len);
-#endif
+			dirent->rec_len = ext2fs_rec_len_to_disk(rec_len);
 			continue;
 		}
 		if (dirent->name_len + 8 > rec_len) {
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists