From b94a052a25d0c524209782e408c31d8ff25a6fe1 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 18 May 2002 13:16:30 -0600 Subject: [PATCH] Add more complete tests for symlinks: nul termination of long links and length Improve the f_badsymlinks test case for these new tests. --- e2fsck/pass1.c | 42 +++++++++++++++++++++++++++++------------- e2fsck/pass2.c | 2 +- e2fsck/problem.c | 10 +++++----- e2fsck/problem.h | 10 +++++----- tests/ChangeLog | 8 ++++++++ tests/f_badsymlinks/expect.1 | 43 +++++++++++++++++++++++++++---------------- tests/f_badsymlinks/expect.2 | 2 +- tests/f_badsymlinks/image.gz | Bin 1659 -> 1767 bytes tests/f_badsymlinks/name | 2 +- tests/f_filetype/expect.1 | 16 ++++++++-------- 10 files changed, 85 insertions(+), 50 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index d252bb7..1d7b3f8 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -173,15 +173,14 @@ static int strnlen(const char * s, int count) */ int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode) { + int len; int i; - if ((inode->i_size_high || inode->i_size == 0) || - (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | - EXT2_INDEX_FL))) + if (inode->i_size_high || inode->i_size == 0) return 0; if (inode->i_blocks) { - if ((inode->i_size > fs->blocksize) || + if ((inode->i_size >= fs->blocksize) || (inode->i_blocks != fs->blocksize >> 9) || (inode->i_block[0] < fs->super->s_first_data_block) || (inode->i_block[0] >= fs->super->s_blocks_count)) @@ -190,14 +189,26 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode) for (i = 1; i < EXT2_N_BLOCKS; i++) if (inode->i_block[i]) return 0; + + {char buf[fs->blocksize]; + + if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf)) + return 0; + + len = strnlen(buf, fs->blocksize); + if (len == fs->blocksize) + return 0; + } } else { - if (inode->i_size > sizeof(inode->i_block) - 1) + if (inode->i_size >= sizeof(inode->i_block)) return 0; - if (inode->i_size != - strnlen((char *)inode->i_block, sizeof(inode->i_block))) + len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); + if (len == sizeof(inode->i_block)) return 0; } + if (len != inode->i_size) + return 0; return 1; } @@ -205,15 +216,16 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode) * If the immutable (or append-only) flag is set on the inode, offer * to clear it. */ +#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL | EXT2_INDEX_FL) static void check_immutable(e2fsck_t ctx, struct problem_context *pctx) { - if (!(pctx->inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL))) + if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS)) return; if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx)) return; - pctx->inode->i_flags &= ~((EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)); + pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS; e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); } @@ -1137,7 +1149,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.fragmented = 0; pb.compressed = 0; pb.previous_block = 0; - pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); + pb.is_dir = LINUX_S_ISDIR(inode->i_mode); pb.inode = inode; pb.pctx = pctx; pb.ctx = ctx; @@ -1218,6 +1230,9 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, fs->super->s_prealloc_dir_blocks) bad_size = 2; } + } else if (!LINUX_S_ISREG(inode->i_mode)) { + if (inode->i_size_high) + bad_size = 5; } else { size = inode->i_size | ((__u64) inode->i_size_high << 32); if ((size < pb.last_block * fs->blocksize)) @@ -1230,13 +1245,14 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pctx->num = (pb.last_block+1) * fs->blocksize; if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { inode->i_size = pctx->num; - if (!pb.is_dir) + if (LINUX_S_ISREG(inode->i_mode)) inode->i_size_high = pctx->num >> 32; e2fsck_write_inode(ctx, ino, inode, "check_blocks"); } pctx->num = 0; } - if (!pb.is_dir && (inode->i_size_high || inode->i_size & 0x80000000UL)) + if (LINUX_S_ISREG(inode->i_mode) && + (inode->i_size_high || inode->i_size & 0x80000000UL)) ctx->large_files++; if (pb.num_blocks != inode->i_blocks) { pctx->num = pb.num_blocks; @@ -1342,7 +1358,7 @@ static int process_block(ext2_filsys fs, perhaps this really is just an illegal block. */ return 0; } - + if (blk == 0) { if (p->is_dir == 0) { /* diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index e424eb5..19a682a 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -675,7 +675,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) if (!ext2fs_inode_has_valid_blocks(&inode)) return; - if (!LINUX_S_ISDIR(inode.i_mode) && + if (LINUX_S_ISREG(inode.i_mode) && (inode.i_size_high || inode.i_size & 0x80000000UL)) ctx->large_files--; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 7f6cc02..126d9d5 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -550,8 +550,8 @@ static const struct e2fsck_problem problem_table[] = { /* Immutable flag set on a device or socket inode */ { PR_1_SET_IMMUTABLE, - N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n" - "or append-only flag set. "), + N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable,\n" + "append-only, or dir index flag set. "), PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK }, /* Compression flag set on an inode when filesystem doesn't support it */ @@ -643,8 +643,8 @@ static const struct e2fsck_problem problem_table[] = { /* Bad extended attribute value */ { PR_1_EA_BAD_VALUE, N_("@a @b %b is corrupt (invalid value). "), - PROMPT_CLEAR, 0}, - + PROMPT_CLEAR, 0}, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ @@ -949,7 +949,7 @@ static const struct e2fsck_problem problem_table[] = { N_("@E has a zero-length name.\n"), PROMPT_CLEAR, 0 }, - /* Invalid fast symlink size */ + /* Invalid symlink size */ { PR_2_SYMLINK_SIZE, N_("Symlink %Q (@i #%i) has an invalid size (%Is).\n"), PROMPT_CLEAR, 0 }, diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 89bd5b4..666b893 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -362,16 +362,16 @@ struct problem_context { /* Error allocating EA region allocation structure */ #define PR_1_EA_ALLOC_REGION 0x01003F - + /* Error EA allocation collision */ #define PR_1_EA_ALLOC_COLLISION 0x010040 - + /* Bad extended attribute name */ #define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute value */ -#define PR_1_EA_BAD_VALUE 0x0100423 - +#define PR_1_EA_BAD_VALUE 0x010042 + /* * Pass 1b errors */ @@ -562,7 +562,7 @@ struct problem_context { /* Directory filename can't be zero-length */ #define PR_2_NULL_NAME 0x020030 -/* Invalid fast symlink size */ +/* Invalid symlink size */ #define PR_2_SYMLINK_SIZE 0x020031 /* i_file_acl (extended attribute) is bad */ diff --git a/tests/ChangeLog b/tests/ChangeLog index deac0d4..717c2bf 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2002-05-18 Andreas Dilger + + * f_badsymlink: Add extra length checks for symlinks + - missing nul termination test (new) + - nul terminated but i_size is wrong + - i_size == maximum size (no space for nul, new) + - too many blocks for long symlink + 2002-03-08 Theodore Tso * Release of E2fsprogs 1.27 diff --git a/tests/f_badsymlinks/expect.1 b/tests/f_badsymlinks/expect.1 index 203d9ae..c9eb717 100644 --- a/tests/f_badsymlinks/expect.1 +++ b/tests/f_badsymlinks/expect.1 @@ -1,53 +1,64 @@ Pass 1: Checking inodes, blocks, and sizes -Special (device/socket/fifo/symlink) file (inode 18) has immutable -or append-only flag set. Clear? yes +Inode 16, i_size is 4294967358, should be 1024. Fix? yes + +Special (device/socket/fifo/symlink) file (inode 18) has immutable, +append-only, or dir index flag set. Clear? yes Inode 19 has illegal block(s). Clear? yes Illegal block #0 (1234567890) in inode 19. CLEARED. Inode 19, i_blocks is 2, should be 0. Fix? yes -Special (device/socket/fifo/symlink) file (inode 20) has immutable -or append-only flag set. Clear? yes +Special (device/socket/fifo/symlink) file (inode 20) has immutable, +append-only, or dir index flag set. Clear? yes Pass 2: Checking directory structure Symlink /empty_link (inode #17) has an invalid size (0). Clear? yes -Symlink /long_fastlink (inode #13) has an invalid size (99). +Symlink /long_fastlink (inode #13) has an invalid size (59). +Clear? yes + +Symlink /long_link (inode #14) has an invalid size (1023). Clear? yes -Symlink /long_link (inode #14) has an invalid size (1234567890). +Symlink /high_fastlink (inode #15) has an invalid size (4294967299). Clear? yes -Symlink /high_link (inode #16) has an invalid size (4294967358). +Symlink /high_link (inode #16) has an invalid size (4294968320). Clear? yes Symlink /empty_fastlink (inode #12) has an invalid size (0). Clear? yes -Symlink /bad_link (inode #19) has an invalid size (62). +Symlink /bad_link_block (inode #19) has an invalid size (62). +Clear? yes + +Symlink /extra_link_block (inode #21) has an invalid size (62). +Clear? yes + +Symlink /bad_link_size (inode #22) has an invalid size (1024). +Clear? yes + +Symlink /bad_fastlink_size (inode #23) has an invalid size (60). Clear? yes Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -Block bitmap differences: -26 -Fix? yes - -Free blocks count wrong for group #0 (997, counted=1001). +Free blocks count wrong for group #0 (995, counted=1001). Fix? yes -Free blocks count wrong (997, counted=1001). +Free blocks count wrong (995, counted=1001). Fix? yes -Free inodes count wrong for group #0 (12, counted=18). +Free inodes count wrong for group #0 (9, counted=19). Fix? yes -Free inodes count wrong (12, counted=18). +Free inodes count wrong (9, counted=19). Fix? yes test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 14/32 files (0.0% non-contiguous), 23/1024 blocks +test_filesys: 13/32 files (7.7% non-contiguous), 23/1024 blocks Exit status is 1 diff --git a/tests/f_badsymlinks/expect.2 b/tests/f_badsymlinks/expect.2 index 6dbd393..1499551 100644 --- a/tests/f_badsymlinks/expect.2 +++ b/tests/f_badsymlinks/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 14/32 files (0.0% non-contiguous), 23/1024 blocks +test_filesys: 13/32 files (0.0% non-contiguous), 23/1024 blocks Exit status is 0 diff --git a/tests/f_badsymlinks/image.gz b/tests/f_badsymlinks/image.gz index 743163fcdcca5a2e8789fdd92572ababd40445f3..4ebacdefe9623b99768ea52fbc087baace39dc0a 100644 GIT binary patch delta 802 zcmV+-1Ks@l4Cf7hABzYGG0o&W0t0hlb^z_zPiz!b90%~X(~@mLpkT#S!4NJONtz~} zbQ=#F`Mj||=9=O4Tlv)Lb30;PEMF((`1_aNeC4w*U;h5%uYY{{*s&L$cjRH~ zjTG%4w&ndlp7$#-96Ft!4s2ok#SXBAE(FH_hEsJT&Yt6|`Y#s%w_YqBK;HY}=FBHo zi>jVXx}QaV#x2!=f8+Wy-Rt_7ghtoA?d9*9kHp#;Ygeq@u_j{eiM2P@qp>DqJ@!wY zzpfP9?E3f1pL5Nu!d<_n4zB*ySl|3+ng7FIbIq)J<);IcVGV> zA7K9vZIGY+2A17-e(%gRv+A|~3$50s^MAcIcF+HRXqJC8Za<3oQ`^#JR=xKBsR8zX z<(vNb)%kZIq|K~);KDr@&UF=lCNoN$<&?KNisE6taT^D_GG!W+CH+- zI=gbRSm(yE`uscZw$INlFRm;VYvD%NSzm6goSI!oSKGyKzCNA|{`ERJSt?`OiUGQaD83-a$6tDi_u=2Iujocy!Zw54Kw-iV*C z=FOg1ZoR!!tk)Z1qCS7FeJ1UCXJ7d}cjm7yuFaQg(eIKy`FQp9)qC(T*|DzwZ;urH z4-AP>hXC|Hp#K5=59ohD{{#9T(Eot`2lPLn|AB`=Iv__7hPVHLVdeS>!+ZaC{6PN) g1Nt8TaQ_Fhp#shWldu8|4EX=}8(mx^g#Z8$0HhAfsQ>@~ delta 689 zcmV;i0#5zs4f_m#ABzYGUMv1jHYAN~s z;L8bzbMtX7=Q}y~h5)px-PMl`Ask4WH~A2{leX>W0lQ;=v!lHS7KXWpelYu9Z|Vln%k%ldEMIe+rO!{g8IKYg|9#EC-(-FaAh`B?s;J+1%lv|fSM zu(b5Lu!iXumw+|Y7u*AAO|?Jb>T`T8{^tSU-O=~}GTdGoDP~c7GO2$S>2y>B{>AF~$Flh^X8B)!8Be28{!$ZO{3id4+}+dF{G&Rh=bv@_az)jDufLrkMx*>gP2~Tu!uj6_G3xUV zXXCatk^k6}mF2$`VlG^mtbjJRyuP+-rJu@|3Kej&`oAzgYo3p-BrE)dxOM1K0 z>wB~O-+y2r{f&;oh0;Viw0Z{LpYMs+)`rc-`3~m03JcTatCd