mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Fix a bug in fsck_ffs(8) triggered by corrupted filesystems.
The last valid inode in the filesystem is maxino - 1, not maxino. Thus validity checks should ino < maxino, not ino <= maxino. Reported-by: Robert Morris PR: 271312 MFC-after: 1 week Sponsored-by: The FreeBSD Foundation
This commit is contained in:
parent
c79a141695
commit
11ce203e05
|
@ -126,7 +126,7 @@ check_dirdepth(struct inoinfo *inp)
|
|||
if (inp->i_depth == 0 && updateasked == 0) {
|
||||
updateasked = 1;
|
||||
if (preen) {
|
||||
pwarn("UPDATING FILESYSTEM TO TRACK DIRECTORY DEPTH");
|
||||
pwarn("UPDATING FILESYSTEM TO TRACK DIRECTORY DEPTH\n");
|
||||
dirdepthupdate = 1;
|
||||
} else {
|
||||
/*
|
||||
|
@ -437,7 +437,7 @@ fileerror(ino_t cwd, ino_t ino, const char *errmesg)
|
|||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
pwarn("%s ", errmesg);
|
||||
if (ino < UFS_ROOTINO || ino > maxino) {
|
||||
if (ino < UFS_ROOTINO || ino >= maxino) {
|
||||
pfatal("out-of-range inode number %ju", (uintmax_t)ino);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ inoinfo(ino_t inum)
|
|||
struct inostatlist *ilp;
|
||||
int iloff;
|
||||
|
||||
if (inum > maxino)
|
||||
if (inum >= maxino)
|
||||
errx(EEXIT, "inoinfo: inumber %ju out of range",
|
||||
(uintmax_t)inum);
|
||||
ilp = &inostathead[inum / sblock.fs_ipg];
|
||||
|
|
|
@ -433,8 +433,9 @@ void
|
|||
ginode(ino_t inumber, struct inode *ip)
|
||||
{
|
||||
ufs2_daddr_t iblk;
|
||||
struct ufs2_dinode *dp;
|
||||
|
||||
if (inumber < UFS_ROOTINO || inumber > maxino)
|
||||
if (inumber < UFS_ROOTINO || inumber >= maxino)
|
||||
errx(EEXIT, "bad inode number %ju to ginode",
|
||||
(uintmax_t)inumber);
|
||||
ip->i_number = inumber;
|
||||
|
@ -473,14 +474,15 @@ ginode(ino_t inumber, struct inode *ip)
|
|||
}
|
||||
ip->i_dp = (union dinode *)
|
||||
&ip->i_bp->b_un.b_dinode2[inumber - ip->i_bp->b_index];
|
||||
if (ffs_verify_dinode_ckhash(&sblock, (struct ufs2_dinode *)ip->i_dp)) {
|
||||
dp = (struct ufs2_dinode *)ip->i_dp;
|
||||
/* Do not check hash of inodes being created */
|
||||
if (dp->di_mode != 0 && ffs_verify_dinode_ckhash(&sblock, dp)) {
|
||||
pwarn("INODE CHECK-HASH FAILED");
|
||||
prtinode(ip);
|
||||
if (preen || reply("FIX") != 0) {
|
||||
if (preen)
|
||||
printf(" (FIXED)\n");
|
||||
ffs_update_dinode_ckhash(&sblock,
|
||||
(struct ufs2_dinode *)ip->i_dp);
|
||||
ffs_update_dinode_ckhash(&sblock, dp);
|
||||
inodirty(ip);
|
||||
}
|
||||
}
|
||||
|
@ -1292,7 +1294,7 @@ findino(struct inodesc *idesc)
|
|||
if (dirp->d_ino == 0)
|
||||
return (KEEPON);
|
||||
if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
|
||||
dirp->d_ino >= UFS_ROOTINO && dirp->d_ino <= maxino) {
|
||||
dirp->d_ino >= UFS_ROOTINO && dirp->d_ino < maxino) {
|
||||
idesc->id_parent = dirp->d_ino;
|
||||
return (STOP|FOUND);
|
||||
}
|
||||
|
@ -1322,7 +1324,7 @@ prtinode(struct inode *ip)
|
|||
|
||||
dp = ip->i_dp;
|
||||
printf(" I=%lu ", (u_long)ip->i_number);
|
||||
if (ip->i_number < UFS_ROOTINO || ip->i_number > maxino)
|
||||
if (ip->i_number < UFS_ROOTINO || ip->i_number >= maxino)
|
||||
return;
|
||||
printf(" OWNER=");
|
||||
if ((pw = getpwuid((int)DIP(dp, di_uid))) != NULL)
|
||||
|
|
|
@ -371,7 +371,7 @@ pass2check(struct inodesc *idesc)
|
|||
dirp->d_reclen = proto.d_reclen;
|
||||
}
|
||||
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
|
||||
if (dirp->d_ino > maxino) {
|
||||
if (dirp->d_ino >= maxino) {
|
||||
direrror(idesc->id_number, "BAD INODE NUMBER FOR '..'");
|
||||
/*
|
||||
* If we know parent set it now, otherwise let it
|
||||
|
@ -471,7 +471,7 @@ pass2check(struct inodesc *idesc)
|
|||
}
|
||||
idesc->id_entryno++;
|
||||
n = 0;
|
||||
if (dirp->d_ino > maxino) {
|
||||
if (dirp->d_ino >= maxino) {
|
||||
fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
|
||||
n = reply("REMOVE");
|
||||
} else if (((dirp->d_ino == UFS_WINO && dirp->d_type != DT_WHT) ||
|
||||
|
|
Loading…
Reference in a new issue