diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index f4913f6a..2e9a90d4 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -494,6 +494,20 @@ static int check_name(e2fsck_t ctx, return ret; } +static int encrypted_check_name(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + struct problem_context *pctx) +{ + if (ext2fs_dirent_name_len(dirent) < EXT4_CRYPTO_BLOCK_SIZE) { + if (fix_problem(ctx, PR_2_BAD_ENCRYPTED_NAME, pctx)) { + dirent->inode = 0; + return 1; + } + ext2fs_unmark_valid(ctx->fs); + } + return 0; +} + /* * Check the directory filetype (if present) */ @@ -1383,6 +1397,12 @@ skip_checksum: if (!encrypted && check_name(ctx, dirent, &cd->pctx)) dir_modified++; + if (encrypted && (dot_state) > 1 && + encrypted_check_name(ctx, dirent, &cd->pctx)) { + dir_modified++; + goto next; + } + if (check_filetype(ctx, dirent, ino, &cd->pctx)) dir_modified++; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 084131ab..9ef689a2 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1613,6 +1613,11 @@ static struct e2fsck_problem problem_table[] = { N_("Fixing size of inline @d @i %i failed.\n"), PROMPT_TRUNCATE, 0 }, + /* Encrypted directory entry is too short */ + { PR_2_BAD_ENCRYPTED_NAME, + N_("Encrypted @E is too short.\n"), + PROMPT_CLEAR, 0 }, + /* Pass 3 errors */ /* Pass 3: Checking directory connectivity */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 5af3edf0..2ff0f5ef 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -963,6 +963,9 @@ struct problem_context { /* fixing inline dir size failed */ #define PR_2_FIX_INLINE_DIR_FAILED 0x02004F +/* Encrypted directory entry is too short */ +#define PR_2_BAD_ENCRYPTED_NAME 0x020050 + /* * Pass 3 errors */ diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 918ae707..cfeaa050 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -579,6 +579,7 @@ struct ext2_inode_large { #define EXT4_MAX_KEY_SIZE 64 #define EXT4_KEY_DESCRIPTOR_SIZE 8 +#define EXT4_CRYPTO_BLOCK_SIZE 16 /* Password derivation constants */ #define EXT4_MAX_PASSPHRASE_SIZE 1024 diff --git a/tests/f_short_encrypted_dirent/expect.1 b/tests/f_short_encrypted_dirent/expect.1 new file mode 100644 index 00000000..bc649222 --- /dev/null +++ b/tests/f_short_encrypted_dirent/expect.1 @@ -0,0 +1,17 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Encrypted entry 'motd' in /get_shorty (12) is too short. +Clear? yes + +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Unattached inode 13 +Connect to /lost+found? yes + +Inode 13 ref count is 2, should be 1. Fix? yes + +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 13/16 files (0.0% non-contiguous), 23/100 blocks +Exit status is 1 diff --git a/tests/f_short_encrypted_dirent/expect.2 b/tests/f_short_encrypted_dirent/expect.2 new file mode 100644 index 00000000..636c6e9e --- /dev/null +++ b/tests/f_short_encrypted_dirent/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: 13/16 files (0.0% non-contiguous), 23/100 blocks +Exit status is 0 diff --git a/tests/f_short_encrypted_dirent/image.gz b/tests/f_short_encrypted_dirent/image.gz new file mode 100644 index 00000000..a35bfb23 Binary files /dev/null and b/tests/f_short_encrypted_dirent/image.gz differ diff --git a/tests/f_short_encrypted_dirent/name b/tests/f_short_encrypted_dirent/name new file mode 100644 index 00000000..a35028af --- /dev/null +++ b/tests/f_short_encrypted_dirent/name @@ -0,0 +1 @@ +short encrypted directory entry