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 360b5452a..c8768ec81 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 a6d4eef27..0da7c55d3 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 ca623e95e..198d6f5bc 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 5bb99bcc0..8bc35a2cc 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 5ad529681..4ea55942f 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 1d4ffb166..7f019a766 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 1e511a3af..91c0bd0cc 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 b84275a51..afe6f95b9 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 87e86d947..113d182eb 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 c47b59b4e..9e6a9753e 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 d6e91947f..2763e6824 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 ea83ad5be..c960c76c3 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 000000000..d901967a8 --- /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 000000000..82d72088b --- /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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 Tza^N5SY@dxp68zPJojG#yDNT7 literal 0 Hc-jL100001 diff --git a/tests/f_h_badroot/name b/tests/f_h_badroot/name new file mode 100644 index 000000000..b2ac7ffa3 --- /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 000000000..9353ec777 --- /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 3024b041a..000000000 --- a/tests/f_h_normal/script~ +++ /dev/null @@ -1,3 +0,0 @@ -if test "$HTREE"x = yx ; then -. $cmd_dir/run_e2fsck -fi -- 2.39.2