code: plan9front

Download patch

ref: 7359de438cfaac829c4ed8b39fae9bb872fb5eea
parent: ed767b2a182e8297f97602b68d49e018b5e4b129
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Feb 16 21:21:42 EST 2024

ext4srv: fix meta csum producing garbage

A block was never cleared before setting the field.
This would result in garbage and wrong checksums.

Also enable checksum verification now that it actually
works.

--- a/sys/src/cmd/ext4srv/ext4_dir.c
+++ b/sys/src/cmd/ext4srv/ext4_dir.c
@@ -58,14 +58,16 @@
 		t = ext4_dir_get_tail(inode_ref, dirent);
 		if (!t) {
 			/* There is no space to hold the checksum */
+			werrstr("no space for checksum");
 			return false;
 		}
 
 		intptr diff = (char *)t - (char *)dirent;
 		u32int csum = ext4_dir_csum(inode_ref, dirent, diff);
-		if (t->checksum != to_le32(csum))
+		if (t->checksum != to_le32(csum)) {
+			werrstr("checksum does not match");
 			return false;
-
+		}
 	}
 	return true;
 }
@@ -92,8 +94,7 @@
 		}
 
 		intptr diff = (char *)t - (char *)dirent;
-		u32int csum = ext4_dir_csum(inode_ref, dirent, diff);
-		t->checksum = to_le32(csum);
+		t->checksum = to_le32(ext4_dir_csum(inode_ref, dirent, diff));
 	}
 }
 
@@ -305,9 +306,8 @@
 			/* Needed to clear dir index flag if corrupted */
 			ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
 			parent->dirty = true;
-		} else if (r == 0) {
-			return 0;
 		}
+		return r;
 	}
 
 	/* Linear algorithm */
@@ -377,8 +377,7 @@
 		ext4_dir_write_entry(sb, blk_en, el, child, name, name_len);
 		ext4_dir_init_entry_tail(EXT4_DIRENT_TAIL(b.data, block_size));
 	} else {
-		ext4_dir_write_entry(sb, blk_en, block_size, child, name,
-				name_len);
+		ext4_dir_write_entry(sb, blk_en, block_size, child, name, name_len);
 	}
 
 	ext4_dir_set_csum(parent, (void *)b.data);
@@ -408,9 +407,8 @@
 			/* Needed to clear dir index flag if corrupted */
 			ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
 			parent->dirty = true;
-		} else if (r == 0) {
-			return 0;
 		}
+		return r;
 	}
 
 	/* Linear algorithm */
--- a/sys/src/cmd/ext4srv/ext4_dir_idx.c
+++ b/sys/src/cmd/ext4srv/ext4_dir_idx.c
@@ -232,10 +232,6 @@
 	return (struct ext4_dir_idx_climit *)(((char *)dirent) + count_offset);
 }
 
-/*
- * BIG FAT NOTES:
- *       Currently we do not verify the checksum of HTree node.
- */
 static bool ext4_dir_dx_csum_verify(struct ext4_inode_ref *inode_ref,
 				    struct ext4_dir_en *de)
 {
@@ -262,7 +258,7 @@
 
 		u32int c = to_le32(ext4_dir_dx_checksum(inode_ref, de, coff, cnt, t));
 		if (t->checksum != c)
-			return true; // FIXME lwext4 does not set correct checksums sometimes
+			return false;
 	}
 	return true;
 }
@@ -292,8 +288,7 @@
 		}
 
 		t = (void *)(((struct ext4_dir_idx_entry *)climit) + limit);
-		t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent,
-					coff, count, t));
+		t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent, coff, count, t));
 	}
 }
 
@@ -388,6 +383,7 @@
 
 	if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
 		int len = block_size - sizeof(struct ext4_dir_entry_tail);
+		memset(be, 0, len);
 		ext4_dir_en_set_entry_len(be, len);
 		ext4_dir_en_set_name_len(sb, be, 0);
 		ext4_dir_en_set_inode_type(sb, be, EXT4_DE_UNKNOWN);
@@ -1211,6 +1207,8 @@
 			 "Block: %ud\n",
 			 parent->index,
 			 (u32int)0);
+		werrstr("htree root checksum mismatch");
+		return EXT4_ERR_BAD_DX_DIR;
 	}
 
 	/* Initialize hinfo structure (mainly compute hash) */
@@ -1263,6 +1261,9 @@
 				"Block: %ud\n",
 				parent->index,
 				leaf_block_idx);
+		r = -1;
+		werrstr("htree leaf block checksum mismatch");
+		goto release_index;
 	}
 
 	/* Check if insert operation passed */