From 503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 26 Jun 2002 16:52:10 -0400 Subject: [PATCH] Add support for the half-MD4 HTREE hash. Add HTREE root node tests. --- debugfs/ChangeLog | 5 ++ debugfs/htree.c | 42 +++++++++++---- e2fsck/ChangeLog | 20 +++++++ e2fsck/pass1.c | 91 ++++++++++++++++++++++++-------- e2fsck/pass2.c | 7 +-- e2fsck/problem.c | 40 +++++++++++--- e2fsck/problem.h | 15 ++++++ lib/ext2fs/ChangeLog | 7 +++ lib/ext2fs/dirhash.c | 128 +++++++++++++++++++++++++++++++++++++++++++-- lib/ext2fs/ext2_fs.h | 11 +++- lib/ext2fs/ext2fs.h | 4 +- tests/ChangeLog | 4 ++ tests/f_h_badroot/expect.1 | 33 ++++++++++++ tests/f_h_badroot/expect.2 | 7 +++ tests/f_h_badroot/image.gz | Bin 0 -> 35041 bytes tests/f_h_badroot/name | 1 + tests/f_h_badroot/script | 6 +++ tests/f_h_normal/script~ | 3 -- 18 files changed, 376 insertions(+), 48 deletions(-) create mode 100644 tests/f_h_badroot/expect.1 create mode 100644 tests/f_h_badroot/expect.2 create mode 100644 tests/f_h_badroot/image.gz create mode 100644 tests/f_h_badroot/name create mode 100644 tests/f_h_badroot/script delete mode 100644 tests/f_h_normal/script~ diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog index 360b545..c8768ec 100644 --- a/debugfs/ChangeLog +++ b/debugfs/ChangeLog @@ -1,3 +1,8 @@ +2002-06-26 Theodore Ts'o + + * htree.c (do_dx_hash): Use new ext2fs_dirhash function signature. + Add getopt support so user can specify the hash version. + 2002-05-11 * debug_cmds.ct, debugfs.c (do_bmap): Add new command "bmap" which diff --git a/debugfs/htree.c b/debugfs/htree.c index a6d4eef..0da7c55 100644 --- a/debugfs/htree.c +++ b/debugfs/htree.c @@ -31,6 +31,7 @@ static FILE *pager; static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + struct ext2_dx_root_info * root, blk_t blk, char *buf) { errcode_t errcode; @@ -68,7 +69,9 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, (dirent->name_len & 0xFF) : EXT2_NAME_LEN; strncpy(name, dirent->name, thislen); name[thislen] = '\0'; - errcode = ext2fs_dirhash(0, name, thislen, &hash); + errcode = ext2fs_dirhash(root->hash_version, name, thislen, + fs->super->s_hash_seed, + &hash, 0); if (errcode) com_err("htree_dump_leaf_node", errcode, "while calculating hash"); @@ -89,11 +92,13 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + struct ext2_dx_root_info * root, blk_t blk, char *buf, int level); static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + struct ext2_dx_root_info * root, struct ext2_dx_entry *ent, char *buf, int level) { @@ -115,10 +120,10 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, fprintf(pager, "Entry #%d: Hash 0x%08x, block %d\n", i, i ? ent[i].hash : 0, ent[i].block); if (level) - htree_dump_int_block(fs, ino, inode, + htree_dump_int_block(fs, ino, inode, root, ent[i].block, buf, level-1); else - htree_dump_leaf_node(fs, ino, inode, + htree_dump_leaf_node(fs, ino, inode, root, ent[i].block, buf); } @@ -127,6 +132,7 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + struct ext2_dx_root_info * root, blk_t blk, char *buf, int level) { char *cbuf; @@ -153,7 +159,8 @@ static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, return; } - htree_dump_int_node(fs, ino, inode, (struct ext2_dx_entry *) (buf+8), + htree_dump_int_node(fs, ino, inode, root, + (struct ext2_dx_entry *) (buf+8), cbuf, level); free(cbuf); } @@ -241,7 +248,7 @@ void do_htree_dump(int argc, char *argv[]) ent = (struct ext2_dx_entry *) (buf + 24 + root->info_length); limit = (struct ext2_dx_countlimit *) ent; - htree_dump_int_node(current_fs, ino, &inode, ent, + htree_dump_int_node(current_fs, ino, &inode, root, ent, buf + current_fs->blocksize, root->indirect_levels); @@ -256,19 +263,36 @@ errout: */ void do_dx_hash(int argc, char *argv[]) { - ext2_dirhash_t hash; + ext2_dirhash_t hash, minor_hash; errcode_t err; + int c; + int hash_version = 0; + __u32 hash_seed[4]; - if (argc != 2) { + hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; + optind = 0; +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt (argc, argv, "h:")) != EOF) { + switch (c) { + case 'h': + hash_version = atoi(optarg); + break; + } + } + if (optind != argc-1) { com_err(argv[0], 0, "usage: dx_hash filename"); return; } - err = ext2fs_dirhash(0, argv[1], strlen(argv[1]), &hash); + err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), + hash_seed, &hash, &minor_hash); if (err) { com_err(argv[0], err, "while caclulating hash"); return; } - printf("Hash of %s is 0x%0x\n", argv[1], hash); + printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], + hash, minor_hash); } /* diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index ca623e9..198d6f5 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,23 @@ +2002-06-26 Theodore Ts'o + + * pass1.c (check_blocks): Move htree handling to handle_htree(). + Factor out calls to ext2fs_write_inode so that it happens + if dirty_inode is non-zero. + (handle_htree): Add checks for invalid htree root, invalid + hash version, invalid hash version, and htree depth too deep. + + * problem.h, problem.c (PR_1_HTREE_NODIR, PR_1_HTREE_BADROOT, + PR_1_HTREE_HASHV, PR_1_HTREE_INCOMPAT, PR_1_HTREE_DEPTH): + Add new problem codes. + + * pass2.c (parse_int_node): Fix silly typo. + (check_dir_block): Change to use new ext2fs_dirhash() + function prototype. + (pass2): Fixed two minor bugs discovered by the test case: + Don't stop checking dxdir's after clearing a bad inode. + If there is a bad max hash, make sure the bad_dir flag + is set to make sure we try to clear inode. + 2002-06-25 Theodore Ts'o * e2fsck.c (e2fsck_reset_context): Free the dx_dirinfo structure. diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 5bb99bc..8bc35a2 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1132,6 +1132,57 @@ clear_extattr: return 0; } +/* Returns 1 if bad htree, 0 if OK */ +static int handle_htree(e2fsck_t ctx, struct problem_context *pctx, + ext2_ino_t ino, struct ext2_inode *inode, + char *block_buf) +{ + struct ext2_dx_root_info *root; + ext2_filsys fs = ctx->fs; + errcode_t retval; + blk_t blk; + + if ((!LINUX_S_ISDIR(inode->i_mode) && + fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) || + (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && + fix_problem(ctx, PR_1_HTREE_SET, pctx))) + return 1; + + blk = inode->i_block[0]; + if (((blk == 0) || + (blk < fs->super->s_first_data_block) || + (blk >= fs->super->s_blocks_count)) && + fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + + retval = io_channel_read_blk(fs->io, blk, 1, block_buf); + if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + + /* XXX should check that beginning matches a directory */ + root = (struct ext2_dx_root_info *) (block_buf + 24); + + if ((root->reserved_zero || root->info_length < 8) && + fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + + pctx->num = root->hash_version; + if ((root->hash_version != EXT2_HASH_LEGACY) && + (root->hash_version != EXT2_HASH_HALF_MD4) && + fix_problem(ctx, PR_1_HTREE_HASHV, pctx)) + return 1; + + if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) && + fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx)) + return 1; + + pctx->num = root->indirect_levels; + if ((root->indirect_levels > 1) && + fix_problem(ctx, PR_1_HTREE_DEPTH, pctx)) + return 1; + + return 0; +} /* * This subroutine is called on each inode to account for all of the @@ -1145,6 +1196,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, ext2_ino_t ino = pctx->ino; struct ext2_inode *inode = pctx->inode; int bad_size = 0; + int dirty_inode = 0; __u64 size; if (!ext2fs_inode_has_valid_blocks(inode)) @@ -1172,8 +1224,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, else { if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) { inode->i_flags &= ~EXT2_COMPRBLK_FL; - e2fsck_write_inode(ctx, ino, inode, - "check_blocks"); + dirty_inode++; } } } @@ -1182,7 +1233,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.is_dir ? BLOCK_FLAG_HOLE : 0, block_buf, process_block, &pb); if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; + goto out; end_problem_latch(ctx, PR_LATCH_BLOCK); end_problem_latch(ctx, PR_LATCH_TOOBIG); if (pctx->errcode) @@ -1192,11 +1243,10 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, ctx->fs_fragmented++; if (pb.clear) { - e2fsck_read_inode(ctx, ino, inode, "check_blocks"); inode->i_links_count = 0; ext2fs_icount_store(ctx->inode_link_info, ino, 0); inode->i_dtime = time(0); - e2fsck_write_inode(ctx, ino, inode, "check_blocks"); + dirty_inode++; ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); @@ -1206,24 +1256,20 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, * restart the pass 1 scan. */ ctx->flags |= E2F_FLAG_RESTART; - return; + goto out; } if (inode->i_flags & EXT2_INDEX_FL) { - if (fs->super->s_feature_compat & - EXT2_FEATURE_COMPAT_DIR_INDEX) { + if (handle_htree(ctx, pctx, ino, inode, block_buf)) { + inode->i_flags &= ~EXT2_INDEX_FL; + dirty_inode++; + } else { #ifdef ENABLE_HTREE e2fsck_add_dx_dir(ctx, ino, pb.last_block+1); #endif - } else { - if (fix_problem(ctx, PR_1_HTREE_SET, pctx)) { - inode->i_flags &= ~EXT2_INDEX_FL; - e2fsck_write_inode(ctx, ino, inode, - "check_blocks"); - } - } + } } - + if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) pb.num_blocks++; @@ -1238,7 +1284,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, inode->i_links_count = 0; ext2fs_icount_store(ctx->inode_link_info, ino, 0); inode->i_dtime = time(0); - e2fsck_write_inode(ctx, ino, inode, "check_blocks"); + dirty_inode++; ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); @@ -1270,7 +1316,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, inode->i_size = pctx->num; if (LINUX_S_ISREG(inode->i_mode)) inode->i_size_high = pctx->num >> 32; - e2fsck_write_inode(ctx, ino, inode, "check_blocks"); + dirty_inode++; } pctx->num = 0; } @@ -1281,10 +1327,13 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pctx->num = pb.num_blocks; if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { inode->i_blocks = pb.num_blocks; - e2fsck_write_inode(ctx, ino, inode, "check_blocks"); + dirty_inode++; } pctx->num = 0; } +out: + if (dirty_inode) + e2fsck_write_inode(ctx, ino, inode, "check_blocks"); } #if 0 @@ -1422,8 +1471,8 @@ static int process_block(ext2_filsys fs, p->fragmented = 1; } p->previous_block = blk; - - if (p->is_dir && blockcnt > 2*1024*1024/fs->blocksize) + + if (p->is_dir && blockcnt > (1 << (15 - fs->super->s_log_block_size))) problem = PR_1_TOOBIG_DIR; if (p->is_reg && p->num_blocks+1 >= p->max_blocks) problem = PR_1_TOOBIG_REG; diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 5ad5296..4ea5594 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -205,6 +205,7 @@ void e2fsck_pass2(e2fsck_t ctx) pctx.blk2 = dx_db->node_max_hash; code = PR_2_HTREE_MAX_HASH; fix_problem(ctx, code, &pctx); + bad_dir++; } if (!(dx_db->flags & DX_FLAG_REFERENCED)) { code = PR_2_HTREE_NOTREF; @@ -221,7 +222,6 @@ void e2fsck_pass2(e2fsck_t ctx) if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { clear_htree(ctx, dx_dir->ino); dx_dir->ino = 0; - break; } #ifdef ENABLE_HTREE_CLEAR if (dx_dir->ino) { @@ -501,7 +501,7 @@ static void parse_int_node(ext2_filsys fs, /* Check to make sure the block is valid */ if (blk > dx_dir->numblocks) { if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, - cd->pctx)) { + &cd->pctx)) { clear_htree(cd->ctx, cd->pctx.ino); dx_dir->ino = 0; return; @@ -781,7 +781,8 @@ static int check_dir_block(ext2_filsys fs, #ifdef ENABLE_HTREE if (dx_db) { ext2fs_dirhash(dx_dir->hashversion, dirent->name, - (dirent->name_len & 0xFF), &hash); + (dirent->name_len & 0xFF), + fs->super->s_hash_seed, &hash, 0); if (hash < dx_db->min_hash) dx_db->min_hash = hash; if (hash > dx_db->max_hash) diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 1d4ffb1..7f019a7 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -38,7 +38,8 @@ #define PROMPT_DELETE 15 #define PROMPT_SUPPRESS 16 #define PROMPT_UNLINK 17 -#define PROMPT_NULL 18 +#define PROMPT_CLEAR_HTREE 18 +#define PROMPT_NULL 19 /* * These are the prompts which are used to ask the user if they want @@ -63,7 +64,8 @@ static const char *prompt[] = { N_("Delete file"), /* 15 */ N_("Suppress messages"),/* 16 */ N_("Unlink"), /* 17 */ - "", /* 18 */ + N_("Clear HTree index"),/* 18 */ + "", /* 19 */ }; /* @@ -89,7 +91,8 @@ static const char *preen_msg[] = { N_("FILE DELETED"), /* 15 */ N_("SUPPRESSED"), /* 16 */ N_("UNLINKED"), /* 17 */ - "", /* 18 */ + N_("HTREE INDEX CLEARED"),/* 18 */ + "", /* 19 */ }; static const struct e2fsck_problem problem_table[] = { @@ -668,8 +671,33 @@ static const struct e2fsck_problem problem_table[] = { /* INDEX_FL flag set on a non-HTREE filesystem */ { PR_1_HTREE_SET, N_("@i %i has INDEX_FL flag set on @f without htree support.\n"), - PROMPT_CLEAR, 0 }, - + PROMPT_CLEAR_HTREE, 0 }, + + /* INDEX_FL flag set on a non-directory */ + { PR_1_HTREE_NODIR, + N_("@i %i has INDEX_FL flag set but is not a @d.\n"), + PROMPT_CLEAR_HTREE, 0 }, + + /* Invalid root node in HTREE directory */ + { PR_1_HTREE_BADROOT, + N_("@h %i has an invalid root node.\n"), + PROMPT_CLEAR_HTREE, 0 }, + + /* Unsupported hash version in HTREE directory */ + { PR_1_HTREE_HASHV, + N_("@h %i has an unsupported hash version (%N)\n"), + PROMPT_CLEAR_HTREE, 0 }, + + /* Incompatible flag in HTREE root node */ + { PR_1_HTREE_INCOMPAT, + N_("@h %i uses an incompatible htree root node flag.\n"), + PROMPT_CLEAR_HTREE, 0 }, + + /* HTREE too deep */ + { PR_1_HTREE_DEPTH, + N_("@h %i has a tree depth (%N) which is too big\n"), + PROMPT_CLEAR_HTREE, 0 }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ @@ -1021,7 +1049,7 @@ static const struct e2fsck_problem problem_table[] = { /* Bad block in htree interior node */ { PR_2_HTREE_BADBLK, N_("@p @h %d (%q): bad @b number %B.\n"), - PROMPT_CLEAR, 0 }, + PROMPT_CLEAR_HTREE, 0 }, /* Pass 3 errors */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 1e511a3..91c0bd0 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -388,6 +388,21 @@ struct problem_context { /* INDEX_FL flag set on a non-HTREE filesystem */ #define PR_1_HTREE_SET 0x010047 +/* INDEX_FL flag set on a non-directory */ +#define PR_1_HTREE_NODIR 0x010048 + +/* Invalid root node in HTREE directory */ +#define PR_1_HTREE_BADROOT 0x010049 + +/* Unsupported hash version in HTREE directory */ +#define PR_1_HTREE_HASHV 0x01004A + +/* Incompatible flag in HTREE root node */ +#define PR_1_HTREE_INCOMPAT 0x01004B + +/* HTREE too deep */ +#define PR_1_HTREE_DEPTH 0x01004C + /* * Pass 1b errors */ diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index b84275a..afe6f95 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,10 @@ +2002-06-26 Theodore Ts'o + + * dirhash.c (ext2fs_dirhash): Change function signature to support + a hash seed, and to return the minor hash (for 64-bit hash + support). Add support for the half MD4, half MD4 with + seed, and half MD4 with seed and 64 bits. + 2002-06-15 Theodore Ts'o * ext2_fs.h (EXT2_DIRSYNC_FL): Add new file. diff --git a/lib/ext2fs/dirhash.c b/lib/ext2fs/dirhash.c index 87e86d9..113d182 100644 --- a/lib/ext2fs/dirhash.c +++ b/lib/ext2fs/dirhash.c @@ -16,6 +16,78 @@ #include "ext2_fs.h" #include "ext2fs.h" +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The generic round function. The application is so specific that + * we don't bother protecting all the arguments with parens, as is generally + * good macro practice, in favor of extra legibility. + * Rotation is separate from addition to prevent recomputation + */ +#define ROUND(f, a, b, c, d, x, s) \ + (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) +#define K1 0 +#define K2 013240474631UL +#define K3 015666365641UL + +/* + * Basic cut-down MD4 transform. Returns only 32 bits of result. + */ +static __u32 halfMD4Transform (__u32 buf[4], __u32 const in[]) +{ + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + ROUND(F, a, b, c, d, in[0] + K1, 3); + ROUND(F, d, a, b, c, in[1] + K1, 7); + ROUND(F, c, d, a, b, in[2] + K1, 11); + ROUND(F, b, c, d, a, in[3] + K1, 19); + ROUND(F, a, b, c, d, in[4] + K1, 3); + ROUND(F, d, a, b, c, in[5] + K1, 7); + ROUND(F, c, d, a, b, in[6] + K1, 11); + ROUND(F, b, c, d, a, in[7] + K1, 19); + + /* Round 2 */ + ROUND(G, a, b, c, d, in[1] + K2, 3); + ROUND(G, d, a, b, c, in[3] + K2, 5); + ROUND(G, c, d, a, b, in[5] + K2, 9); + ROUND(G, b, c, d, a, in[7] + K2, 13); + ROUND(G, a, b, c, d, in[0] + K2, 3); + ROUND(G, d, a, b, c, in[2] + K2, 5); + ROUND(G, c, d, a, b, in[4] + K2, 9); + ROUND(G, b, c, d, a, in[6] + K2, 13); + + /* Round 3 */ + ROUND(H, a, b, c, d, in[3] + K3, 3); + ROUND(H, d, a, b, c, in[7] + K3, 9); + ROUND(H, c, d, a, b, in[2] + K3, 11); + ROUND(H, b, c, d, a, in[6] + K3, 15); + ROUND(H, a, b, c, d, in[1] + K3, 3); + ROUND(H, d, a, b, c, in[5] + K3, 9); + ROUND(H, c, d, a, b, in[0] + K3, 11); + ROUND(H, b, c, d, a, in[4] + K3, 15); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; + + return buf[1]; /* "most hashed" word */ + /* Alternative: return sum of all words? */ +} + +#undef ROUND +#undef F +#undef G +#undef H +#undef K1 +#undef K2 +#undef K3 + +/* The old legacy hash */ static ext2_dirhash_t dx_hack_hash (const char *name, int len) { __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; @@ -33,19 +105,69 @@ static ext2_dirhash_t dx_hack_hash (const char *name, int len) * Returns the hash of a filename. If len is 0 and name is NULL, then * this function can be used to test whether or not a hash version is * supported. + * + * The seed is an 4 longword (32 bits) "secret" which can be used to + * uniquify a hash. If the seed is all zero's, then some default seed + * may be used. + * + * A particular hash version specifies whether or not the seed is + * represented, and whether or not the returned hash is 32 bits or 64 + * bits. 32 bit hashes will return 0 for the minor hash. */ errcode_t ext2fs_dirhash(int version, const char *name, int len, - ext2_dirhash_t *ret_hash) + const __u32 seed[4], + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash) { __u32 hash; + __u32 minor_hash = 0; + char *p; + int i; - if (version == 0) + /* Check to see if the seed is all zero's */ + for (i=0; i < 4; i++) { + if (seed[i]) + break; + } + + if (version == EXT2_HASH_LEGACY) hash = dx_hack_hash(name, len); - else { + else if ((version == EXT2_HASH_HALF_MD4) || + (version == EXT2_HASH_HALF_MD4_SEED) || + (version == EXT2_HASH_HALF_MD4_64)) { + char in[32]; + __u32 buf[4]; + + if ((i == 4) || (version == EXT2_HASH_HALF_MD4)) { + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + } else + memcpy(buf, in, sizeof(buf)); + while (len) { + if (len < 32) { + memcpy(in, name, len); + memset(in+len, 0, 32-len); + hash = halfMD4Transform(buf, (__u32 *) in); + break; + } + hash = halfMD4Transform(buf, (__u32 *) p); + len -= 32; + p += 32; + } + if (version == EXT2_HASH_HALF_MD4_64) + minor_hash = buf[2]; + } else { *ret_hash = 0; return EXT2_ET_DIRHASH_UNSUPP; } *ret_hash = hash; + if (ret_minor_hash) + *ret_minor_hash = minor_hash; return 0; } + + + diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index c47b59b..9e6a975 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -167,6 +167,13 @@ struct ext2_dx_root_info { __u8 unused_flags; }; +#define EXT2_HASH_LEGACY 0 +#define EXT2_HASH_HALF_MD4 1 +#define EXT2_HASH_HALF_MD4_SEED 2 +#define EXT2_HASH_HALF_MD4_64 3 /* SEED & 64 */ + +#define EXT2_HASH_FLAG_INCOMPAT 0x1 + struct ext2_dx_entry { __u32 hash; __u32 block; @@ -428,8 +435,8 @@ struct ext2_super_block { __u32 s_journal_inum; /* inode number of journal file */ __u32 s_journal_dev; /* device number of journal file */ __u32 s_last_orphan; /* start of list of inodes to delete */ - - __u32 s_reserved[197]; /* Padding to the end of the block */ + __u32 s_hash_seed[4]; /* HTREE hash */ + __u32 s_reserved[193]; /* Padding to the end of the block */ }; /* diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index d6e9194..2763e68 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -612,7 +612,9 @@ extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, /* dirhash.c */ extern errcode_t ext2fs_dirhash(int version, const char *name, int len, - ext2_dirhash_t *ret_hash); + const __u32 seed[4], + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash); /* dir_iterate.c */ diff --git a/tests/ChangeLog b/tests/ChangeLog index ea83ad5..c960c76 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2002-06-26 Theodore Ts'o + + * f_h_badroot: New test cases to test bogus HTREE node values + 2002-06-25 Theodore Ts'o * Makefile.in (test_script): Add pass in the state of diff --git a/tests/f_h_badroot/expect.1 b/tests/f_h_badroot/expect.1 new file mode 100644 index 0000000..d901967 --- /dev/null +++ b/tests/f_h_badroot/expect.1 @@ -0,0 +1,33 @@ +Pass 1: Checking inodes, blocks, and sizes +HTREE directory inode 13345 has an invalid root node. +Clear HTree index? yes + +HTREE directory inode 26689 has an unsupported hash version (240) +Clear HTree index? yes + +HTREE directory inode 40033 has an invalid root node. +Clear HTree index? yes + +HTREE directory inode 53377 has a tree depth (8) which is too big +Clear HTree index? yes + +HTREE directory inode 66721 uses an incompatible htree root node flag. +Clear HTree index? yes + +Pass 2: Checking directory structure +Problem in HTREE directory inode 73393: node (1) has bad min hash +Problem in HTREE directory inode 73393: node (2) has bad max hash +Invalid HTREE directory inode 73393 (/test6). Clear? yes + +Problem in HTREE directory inode 80065: node (2) has bad max hash +Problem in HTREE directory inode 80065: node (7) has bad max hash +Problem in HTREE directory inode 80065: node (21) has bad max hash +Invalid HTREE directory inode 80065 (/test7). Clear? yes + +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 1719/100080 files (0.0% non-contiguous), 12611/15361 blocks +Exit status is 1 diff --git a/tests/f_h_badroot/expect.2 b/tests/f_h_badroot/expect.2 new file mode 100644 index 0000000..82d7208 --- /dev/null +++ b/tests/f_h_badroot/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 1719/100080 files (0.0% non-contiguous), 12611/15361 blocks +Exit status is 0 diff --git a/tests/f_h_badroot/image.gz b/tests/f_h_badroot/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..9038f1a98c11d5f51e8025bc84119a6aa9546c8a GIT binary patch literal 35041 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 CD}GD> literal 0 HcmV?d00001 diff --git a/tests/f_h_badroot/name b/tests/f_h_badroot/name new file mode 100644 index 0000000..b2ac7ff --- /dev/null +++ b/tests/f_h_badroot/name @@ -0,0 +1 @@ +bad htree root nodes diff --git a/tests/f_h_badroot/script b/tests/f_h_badroot/script new file mode 100644 index 0000000..9353ec7 --- /dev/null +++ b/tests/f_h_badroot/script @@ -0,0 +1,6 @@ +if test "$HTREE"x = yx -a "$HTREE_CLR"x = x; then +. $cmd_dir/run_e2fsck +else + rm -f $test_name.ok $test_name.failed + echo "skipped" +fi diff --git a/tests/f_h_normal/script~ b/tests/f_h_normal/script~ deleted file mode 100644 index 3024b04..0000000 --- a/tests/f_h_normal/script~ +++ /dev/null @@ -1,3 +0,0 @@ -if test "$HTREE"x = yx ; then -. $cmd_dir/run_e2fsck -fi -- 1.8.3.1