Whamcloud - gitweb
e2fsck: check extent-mapped directories with really large logical blocks
authorTheodore Ts'o <tytso@mit.edu>
Mon, 29 Jul 2013 00:54:36 +0000 (20:54 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 29 Jul 2013 01:03:00 +0000 (21:03 -0400)
E2fsck was missing a check for directories with logical blocks so
large that i_size > 2GB.  Without this check the test image found in
the new test f_toobig_extent_dir will cause e2fsck to die with a
memory allocation failure:

Error storing directory block information (inode=12, block=0, num=475218819): Memory allocation failed
e2fsck: aborted

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reported-by: Andrey Melnikov <temnota.am@gmail.com>
e2fsck/pass1.c
tests/f_toobig_extent_dir/expect.1 [new file with mode: 0644]
tests/f_toobig_extent_dir/expect.2 [new file with mode: 0644]
tests/f_toobig_extent_dir/image.gz [new file with mode: 0644]
tests/f_toobig_extent_dir/name [new file with mode: 0644]

index af9afe3..8f2f961 100644 (file)
@@ -1797,12 +1797,17 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
                         (extent.e_pblk + extent.e_len) >
                         ext2fs_blocks_count(ctx->fs->super))
                        problem = PR_1_EXTENT_ENDS_BEYOND;
+               else if (is_leaf && is_dir &&
+                        ((extent.e_lblk + extent.e_len) >
+                         (1 << (21 - ctx->fs->super->s_log_block_size))))
+                       problem = PR_1_TOOBIG_DIR;
 
                if (problem) {
 report_problem:
                        pctx->blk = extent.e_pblk;
                        pctx->blk2 = extent.e_lblk;
                        pctx->num = extent.e_len;
+                       pctx->blkcount = extent.e_lblk + extent.e_len;
                        if (fix_problem(ctx, problem, pctx)) {
                                e2fsck_read_bitmaps(ctx);
                                pctx->errcode =
diff --git a/tests/f_toobig_extent_dir/expect.1 b/tests/f_toobig_extent_dir/expect.1
new file mode 100644 (file)
index 0000000..610ca3f
--- /dev/null
@@ -0,0 +1,12 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 is too big.  Truncate? yes
+
+Block #4294967281 (90) causes directory to be too big.  CLEARED.
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/56 files (0.0% non-contiguous), 28/400 blocks
+Exit status is 1
diff --git a/tests/f_toobig_extent_dir/expect.2 b/tests/f_toobig_extent_dir/expect.2
new file mode 100644 (file)
index 0000000..c025645
--- /dev/null
@@ -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: 12/56 files (0.0% non-contiguous), 28/400 blocks
+Exit status is 0
diff --git a/tests/f_toobig_extent_dir/image.gz b/tests/f_toobig_extent_dir/image.gz
new file mode 100644 (file)
index 0000000..622f65a
Binary files /dev/null and b/tests/f_toobig_extent_dir/image.gz differ
diff --git a/tests/f_toobig_extent_dir/name b/tests/f_toobig_extent_dir/name
new file mode 100644 (file)
index 0000000..d7453ad
--- /dev/null
@@ -0,0 +1 @@
+directory with a very large lblk in extent