NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/47681: Suspect code in fsck_ext2fs
>Number: 47681
>Category: bin
>Synopsis: Suspect code in fsck_ext2fs
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Mar 22 08:05:00 +0000 2013
>Originator: Antoine Leca
>Release: NetBSD 6.0
>Organization:
>Environment:
System: NetBSD netbsd6.local 6.0 NetBSD 6.0 (GENERIC) amd64
>Description:
I found what I suspect to be a problem in fsck_ext2fs/dir.c. My understanding
is that in that function dircheck(), returning (1) means all_is_good, while (0)
indicates some problem; also, I understand a non-zero e2d_type in some entry
while either using Rev.0 or with the INCOMPAT_FTYPE unset, is NOT a normal
condition.
Unfortunately due my own bugs (in foreign code) I am not able to confirm
whether it needs to be fixed or not.
While here, I realized that the actual value for e2d_type was not checked in
the case of Rev.1 FS, so I designed another patch (2nd) to add that check. No
doubt it can be better written!
Perhaps related is that, when the function returns(0) while there are dirty
values within the directory entries, then fsck stops on that directory and
proposes to "Salvage" the directory, which I read to be a pretty drastic
operation, dropping all the entries after the faulty one if I understand
correctly (I am all of a newbie to FFS and derivatives, so do not hesitate to
correct me where I am wrong.)
>How-To-Repeat:
Take some (dispensable) ext2fs file system.
Change the e2d_type byte of a directory entry.
Then run fsck_ext2fs -f against that file system.
>Fix:
Obvious fix:
diff --git a/sbin/fsck_ext2fs/dir.c b/sbin/fsck_ext2fs/dir.c
index 8036f52..66d36ec 100644
--- a/sbin/fsck_ext2fs/dir.c
+++ b/sbin/fsck_ext2fs/dir.c
@@ -274,7 +274,7 @@ dircheck(struct inodesc *idesc, struct ext2fs_direct *dp)
if (sblock.e2fs.e2fs_rev < E2FS_REV1 ||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0)
if (dp->e2d_type != 0)
- return (1);
+ return (0);
size = EXT2FS_DIRSIZ(dp->e2d_namlen);
if (reclen < size ||
idesc->id_filesize < size /* ||
Further improvement of the utility:
diff --git a/sbin/fsck_ext2fs/dir.c b/sbin/fsck_ext2fs/dir.c
index 66d36ec..f6327eb 100644
--- a/sbin/fsck_ext2fs/dir.c
+++ b/sbin/fsck_ext2fs/dir.c
@@ -272,9 +272,13 @@ dircheck(struct inodesc *idesc, struct ext2fs_direct *dp)
if (dp->e2d_ino == 0)
return (1);
if (sblock.e2fs.e2fs_rev < E2FS_REV1 ||
- (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0)
+ (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0) {
if (dp->e2d_type != 0)
return (0);
+ } else {
+ if (dp->e2d_type >= EXT2_FT_MAX)
+ return (0);
+ }
size = EXT2FS_DIRSIZ(dp->e2d_namlen);
if (reclen < size ||
idesc->id_filesize < size /* ||
Home |
Main Index |
Thread Index |
Old Index