mirror of https://github.com/vitalif/e2fsprogs
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
parent
0d9ef644d9
commit
67052a8aee
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue