Whamcloud - gitweb
Add extra checks for bad symlinks, including zero length symlinks,
authorAndreas Dilger <adilger@clusterfs.com>
Sat, 4 Aug 2001 06:51:18 +0000 (00:51 -0600)
committerAndreas Dilger <adilger@clusterfs.com>
Sat, 4 Aug 2001 06:51:18 +0000 (00:51 -0600)
too long i_size for slow and fast symlinks, i_size_high set, multiple
blocks for slow symlinks.

e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/pass2.c
e2fsck/problem.c
lib/ext2fs/ext2_fs.h
tests/ChangeLog
tests/README

index 2ce49ae..fe2537c 100644 (file)
@@ -316,6 +316,7 @@ extern int e2fsck_run_ext3_journal(e2fsck_t ctx);
 /* pass1.c */
 extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
 extern int e2fsck_pass1_check_device_inode(struct ext2_inode *inode);
+extern int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode);
 
 /* pass2.c */
 extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, ext2_ino_t ino);
index 501f448..a8188ff 100644 (file)
@@ -147,6 +147,44 @@ int e2fsck_pass1_check_device_inode(struct ext2_inode *inode)
 }
 
 /*
+ * Check to make sure a symlink inode is real.  Returns 1 if the symlink
+ * checks out, 0 if not.
+ */
+int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode)
+{
+       if (inode->i_size_high || inode->i_size == 0)
+               return 0;
+
+       if (inode->i_flags & (EXT2_IMMUTABLE_FL |EXT2_APPEND_FL |EXT2_INDEX_FL))
+               return 0;
+
+       if (inode->i_blocks) {
+               int i;
+
+               if (inode->i_blocks > fs->blocksize >> 9)
+                       return 0;
+
+               for (i = 1; i < EXT2_N_BLOCKS; i++)
+                       if (inode->i_block[i])
+                               return 0;
+
+               if (inode->i_size > fs->blocksize)
+                       return 0;
+
+               /* Defer check of i_size until block number validated  */
+       } else {
+               if (inode->i_size > EXT2_LINK_DIR - 1)
+                       return 0;
+
+               if (inode->i_size !=
+                   strnlen((char *)inode->i_block, EXT2_LINK_DIR))
+                       return 0;
+       }
+
+       return 1;
+}
+
+/*
  * If the immutable (or append-only) flag is set on the inode, offer
  * to clear it.
  */
@@ -561,10 +599,9 @@ void e2fsck_pass1(e2fsck_t ctx)
                } else if (LINUX_S_ISLNK (inode.i_mode)) {
                        check_immutable(ctx, &pctx);
                        ctx->fs_symlinks_count++;
+                       if (!e2fsck_pass1_check_symlink(fs, &inode))
+                               mark_inode_bad(ctx, ino);
                        if (!inode.i_blocks) {
-                               if (inode.i_size_high ||
-                                   (inode.i_size > EXT2_N_BLOCKS*4))
-                                       mark_inode_bad(ctx, ino);
                                ctx->fs_fast_symlinks_count++;
                                goto next;
                        }
@@ -1216,12 +1253,16 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                }
                pctx->num = 0;
        }
-       if (!pb.is_dir && (inode->i_size_high || inode->i_size & 0x80000000UL))
+       if (!pb.is_dir &&
+           (inode->i_size_high || inode->i_size & 0x80000000UL) &&
+           !ext2fs_test_inode_bitmap(ctx->inode_bad_map, ino))
                ctx->large_files++;
        if (pb.num_blocks != inode->i_blocks) {
                pctx->num = pb.num_blocks;
                if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
                        inode->i_blocks = pb.num_blocks;
+                       if (LINUX_S_ISLNK(inode->i_mode))
+                               mark_inode_bad(ctx, ino);
                        e2fsck_write_inode(ctx, ino, inode, "check_blocks");
                }
                pctx->num = 0;
index a885f6f..0d27d96 100644 (file)
@@ -699,9 +699,10 @@ extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                 && !e2fsck_pass1_check_device_inode(&inode))
                problem = PR_2_BAD_SOCKET;
        else if (LINUX_S_ISLNK(inode.i_mode)
-                && (inode.i_size_high ||
-                    (inode.i_size > EXT2_N_BLOCKS*4)))
+                && !e2fsck_pass1_check_symlink(fs, &inode)) {
+               pctx.str = inode.i_blocks ? "" : "fast ";
                problem = PR_2_SYMLINK_SIZE;
+       }
 
        if (problem) {
                if (fix_problem(ctx, problem, &pctx)) {
index cee69a9..ebfaab4 100644 (file)
@@ -928,7 +928,7 @@ static const struct e2fsck_problem problem_table[] = {
 
        /* Invalid fast symlink size */
        { PR_2_SYMLINK_SIZE,
-         N_("@i %i (%Q) is a fast symlink with a bad size (%Is)\n"),
+         N_("@i %i (%Q) is a %ssymlink with a bad size (%Is)\n"),
          PROMPT_CLEAR, 0 },
 
        /* i_file_acl (extended attribute block) is bad */
index 0eb7be7..0a773d1 100644 (file)
@@ -169,6 +169,8 @@ struct ext2_group_desc
 #define        EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
 #define        EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
 
+#define EXT2_LINK_DIR                  (EXT2_N_BLOCKS * 4)
+
 /*
  * Inode flags
  */
index 15da8ac..d22b2bf 100644 (file)
@@ -1,3 +1,7 @@
+2001-07-26  Andreas Dilger  <adilger@turbolinux.com>
+
+       * f_symlinks: Add several fast symlink error cases to test.
+
 2001-07-27  Theodore Tso  <tytso@valinux.com>
 
        * f_filetype: Update expect.1 to match changed problem message
index 73e2681..d075db5 100644 (file)
@@ -63,5 +63,6 @@ noroot.img            Filesystem with a deleted root directory
 okgroup.img            Filesystem that's exactly 8193 blocks long 
                                (otherwise OK)
 overfsblks.img         Filesystem with overlapping inode and block bitmaps
+symlinks.img           Filesystem with bad symlink sizes