Whamcloud - gitweb
e2fsck: Fix salvage_directory when the last entry's rec_len is too big
authorKalpak Shah <kalpak@clusterfs.com>
Mon, 9 Jul 2007 17:05:45 +0000 (13:05 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 10 Jul 2007 11:28:35 +0000 (07:28 -0400)
  Recently, one of our customers found this message in pass2 of e2fsck
  while doing some regression testing:

  "Entry '4, 0x695a, 0x81ff, 0x0040, 0x8320, 0xa192, 0x0021' in ??? (136554) has
  rec_len of 14200, should be 26908."

  Both the displayed rec_len and the "should be" value are bogus. The
  reason is that salvage_directory sets a offset beyond blocksize
  leading to bogus messages.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/pass2.c
tests/f_baddir2/expect.1 [new file with mode: 0644]
tests/f_baddir2/expect.2 [new file with mode: 0644]
tests/f_baddir2/image.gz [new file with mode: 0644]
tests/f_baddir2/name [new file with mode: 0644]

index e235348..5e088e2 100644 (file)
@@ -675,11 +675,12 @@ static void salvage_directory(ext2_filsys fs,
                return;
        }
        /*
-        * If the directory entry is a multiple of four, so it is
-        * valid, let the previous directory entry absorb the invalid
-        * one. 
+        * If the record length of the directory entry is a multiple
+        * of four, and not too big, such that it is valid, let the
+        * previous directory entry absorb the invalid one.
         */
-       if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
+       if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0 &&
+           (*offset + dirent->rec_len <= fs->blocksize)) {
                prev->rec_len += dirent->rec_len;
                *offset += dirent->rec_len;
                return;
diff --git a/tests/f_baddir2/expect.1 b/tests/f_baddir2/expect.1
new file mode 100644 (file)
index 0000000..1bfea69
--- /dev/null
@@ -0,0 +1,12 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Directory inode 12, block 0, offset 60: directory corrupted
+Salvage? 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: 15/16 files (0.0% non-contiguous), 23/100 blocks
+Exit status is 1
diff --git a/tests/f_baddir2/expect.2 b/tests/f_baddir2/expect.2
new file mode 100644 (file)
index 0000000..b85bbab
--- /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: 15/16 files (0.0% non-contiguous), 23/100 blocks
+Exit status is 0
diff --git a/tests/f_baddir2/image.gz b/tests/f_baddir2/image.gz
new file mode 100644 (file)
index 0000000..0d9fcdf
Binary files /dev/null and b/tests/f_baddir2/image.gz differ
diff --git a/tests/f_baddir2/name b/tests/f_baddir2/name
new file mode 100644 (file)
index 0000000..568a7c9
--- /dev/null
@@ -0,0 +1 @@
+salvage last directory entry