From dbff534ec685ea0815544746558dbd3e31284912 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Feb 2015 17:44:23 -0500 Subject: [PATCH] e2fsck: suppress bad name checks for encrypted directories Signed-off-by: Theodore Ts'o --- e2fsck/e2fsck.c | 4 ++++ e2fsck/e2fsck.h | 1 + e2fsck/pass1.c | 20 ++++++++++++++++++++ e2fsck/pass2.c | 34 +++++++++++++++++++++++----------- e2fsck/problem.c | 5 +++++ e2fsck/problem.h | 3 +++ 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index fcda7d7..cf43a8c 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -144,6 +144,10 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx) ext2fs_free_mem(&ctx->invalid_inode_table_flag); ctx->invalid_inode_table_flag = 0; } + if (ctx->encrypted_dirs) { + ext2fs_u32_list_free(ctx->encrypted_dirs); + ctx->encrypted_dirs = 0; + } /* Clear statistic counters */ ctx->fs_directory_count = 0; diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 615ad75..b895f1e 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -368,6 +368,7 @@ struct e2fsck_struct { int ext_attr_ver; profile_t profile; int blocks_per_page; + ext2_u32_list encrypted_dirs; /* Reserve blocks for root and l+f re-creation */ blk64_t root_repair_block, lnf_repair_block; diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 2b4aae7..78a4c71 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -68,6 +68,7 @@ static void mark_table_blocks(e2fsck_t ctx); static void alloc_bb_map(e2fsck_t ctx); static void alloc_imagic_map(e2fsck_t ctx); static void mark_inode_bad(e2fsck_t ctx, ino_t ino); +static void add_encrypted_dir(e2fsck_t ctx, ino_t ino); static void handle_fs_bad_blocks(e2fsck_t ctx); static void process_inodes(e2fsck_t ctx, char *block_buf); static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b); @@ -1609,6 +1610,8 @@ void e2fsck_pass1(e2fsck_t ctx) ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino); e2fsck_add_dir_info(ctx, ino, 0); ctx->fs_directory_count++; + if (inode->i_flags & EXT4_ENCRYPT_FL) + add_encrypted_dir(ctx, ino); } else if (LINUX_S_ISREG (inode->i_mode)) { ext2fs_mark_inode_bitmap2(ctx->inode_reg_map, ino); ctx->fs_regular_count++; @@ -1898,6 +1901,23 @@ static void mark_inode_bad(e2fsck_t ctx, ino_t ino) ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino); } +static void add_encrypted_dir(e2fsck_t ctx, ino_t ino) +{ + struct problem_context pctx; + + if (!ctx->encrypted_dirs) { + pctx.errcode = ext2fs_u32_list_create(&ctx->encrypted_dirs, 0); + if (pctx.errcode) + goto error; + } + pctx.errcode = ext2fs_u32_list_add(ctx->encrypted_dirs, ino); + if (pctx.errcode == 0) + return; +error: + fix_problem(ctx, PR_1_ALLOCATE_ENCRYPTED_DIRLIST, &pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; +} /* * This procedure will allocate the inode "bb" (badblock) map table diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 6f9e717..33e4854 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -263,6 +263,10 @@ void e2fsck_pass2(e2fsck_t ctx) ext2fs_free_inode_bitmap(ctx->inode_reg_map); ctx->inode_reg_map = 0; } + if (ctx->encrypted_dirs) { + ext2fs_u32_list_free(ctx->encrypted_dirs); + ctx->encrypted_dirs = 0; + } clear_problem_context(&pctx); if (ctx->large_files) { @@ -459,23 +463,30 @@ static int check_dotdot(e2fsck_t ctx, */ static int check_name(e2fsck_t ctx, struct ext2_dir_entry *dirent, - ext2_ino_t dir_ino EXT2FS_ATTR((unused)), + ext2_ino_t dir_ino, + int *encrypted, struct problem_context *pctx) { int i; int fixup = -1; int ret = 0; + if (*encrypted > 0) + return 0; for ( i = 0; i < ext2fs_dirent_name_len(dirent); i++) { - if (dirent->name[i] == '/' || dirent->name[i] == '\0') { - if (fixup < 0) { - fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); - } - if (fixup) { - dirent->name[i] = '.'; - ret = 1; - } - } + if (dirent->name[i] != '/' && dirent->name[i] != '\0') + continue; + if (*encrypted < 0 && ctx->encrypted_dirs) + *encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs, + dir_ino); + if (*encrypted > 0) + return 0; + if (fixup < 0) + fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); + if (fixup == 0) + return 0; + dirent->name[i] = '.'; + ret = 1; } return ret; } @@ -872,6 +883,7 @@ static int check_dir_block(ext2_filsys fs, int is_leaf = 1; size_t inline_data_size = 0; int filetype = 0; + int encrypted = -1; size_t max_block_size; cd = (struct check_dir_struct *) priv_data; @@ -1345,7 +1357,7 @@ skip_checksum: } } - if (check_name(ctx, dirent, ino, &cd->pctx)) + if (check_name(ctx, dirent, ino, &encrypted, &cd->pctx)) dir_modified++; if (check_filetype(ctx, dirent, ino, &cd->pctx)) diff --git a/e2fsck/problem.c b/e2fsck/problem.c index a63e61c..960fb07 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1101,6 +1101,11 @@ static struct e2fsck_problem problem_table[] = { N_("@i %i has a duplicate @x mapping\n\t(logical @b %c, @n physical @b %b, len %N)\n"), PROMPT_CLEAR, 0 }, + /* Error allocating memory for encrypted directory list */ + { PR_1_ALLOCATE_ENCRYPTED_DIRLIST, + N_("@A memory for encrypted @d list\n"), + PROMPT_NONE, PR_FATAL }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 3c28166..19b2301 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -641,6 +641,9 @@ struct problem_context { /* leaf extent collision */ #define PR_1_EXTENT_COLLISION 0x01007D +/* Error allocating memory for encrypted directory list */ +#define PR_1_ALLOCATE_ENCRYPTED_DIRLIST 0x01007E + /* * Pass 1b errors */ -- 1.8.3.1