Add extra checks for bad symlinks, including zero length symlinks,

too long i_size for slow and fast symlinks, i_size_high set, multiple
blocks for slow symlinks.
bitmap-optimize
Andreas Dilger 2001-08-04 00:51:18 -06:00
parent 0d9ef644d9
commit 67052a8aee
7 changed files with 57 additions and 7 deletions

View 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);

View File

@ -146,6 +146,44 @@ int e2fsck_pass1_check_device_inode(struct ext2_inode *inode)
return 1;
}
/*
* 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;

View 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)) {

View 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 */

View 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
*/

View 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

View 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