From 5c9e9eb7a27feb24136c16706f3db8ce7c8bbc47 Mon Sep 17 00:00:00 2001 From: Kirk McKusick <mckusick@FreeBSD.org> Date: Fri, 28 May 2021 19:41:05 -0700 Subject: [PATCH] Fix fsck_ufs segfault when it needs to rerun. The segfault was being hit in the rerun of Pass 1 in ginode() when trying to get an inode that needs to be repaired. When the first run of fsck_ffs finishes it clears the inode cache, but ginode() was failing to check properly and tried to access the deallocated cache entry. Reported by: Peter Holm Reviewed by: Chuck Silvers Tested by: Peter Holm and Chuck Silvers MFC after: 3 days Sponsored by: Netflix --- sbin/fsck_ffs/inode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index d4e5723f559f..ba2d5892238e 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -416,14 +416,14 @@ void ginode(ino_t inumber, struct inode *ip) { ufs2_daddr_t iblk; - static ino_t startinum = -1; if (inumber < UFS_ROOTINO || inumber > maxino) errx(EEXIT, "bad inode number %ju to ginode", (uintmax_t)inumber); ip->i_number = inumber; - if (startinum != -1 && - inumber >= startinum && inumber < startinum + INOPB(&sblock)) { + if (icachebp != NULL && + inumber >= icachebp->b_index && + inumber < icachebp->b_index + INOPB(&sblock)) { /* take an additional reference for the returned inode */ icachebp->b_refcnt++; } else { @@ -433,14 +433,14 @@ ginode(ino_t inumber, struct inode *ip) brelse(icachebp); icachebp = getdatablk(iblk, sblock.fs_bsize, BT_INODES); if (icachebp->b_errs != 0) { + icachebp = NULL; ip->i_bp = NULL; ip->i_dp = &zino; return; } - startinum = rounddown(inumber, INOPB(&sblock)); /* take a cache-hold reference on new icachebp */ icachebp->b_refcnt++; - icachebp->b_index = startinum; + icachebp->b_index = rounddown(inumber, INOPB(&sblock)); } ip->i_bp = icachebp; if (sblock.fs_magic == FS_UFS1_MAGIC) {