Created attachment 242111 [details] ffs image with reachable directory with zero link count causes fsck to deref NULL If a directory inode's link count is zero, then pass1.c's checkinode() doesn't call cacheino() to enter it into inphash[]: if (mode == IFDIR) { if (DIP(dp, di_size) == 0) { inoinfo(inumber)->ino_state = DCLEAR; } else if (DIP(dp, di_nlink) <= 0) { inoinfo(inumber)->ino_state = DZLINK; } else { inoinfo(inumber)->ino_state = DSTATE; cacheino(dp, inumber); Then in pass2check(), if the directory is reachable, the fall-through path from DZLINK calls getinoinfo(), which returns NULL, causing inp->i_parent to crash: case DZLINK: if (inoinfo(idesc->id_number)->ino_state == DFOUND) inoinfo(dirp->d_ino)->ino_state = DFOUND; /* FALLTHROUGH */ case DFOUND: inp = getinoinfo(dirp->d_ino); if (idesc->id_entryno > 2) { if (inp->i_parent == 0) { I've attached a file system image in which i-node 3 (/.snap) has a 0 link count, and which yields this fsck_ffs backtrace: Program received signal SIGSEGV, Segmentation fault. Address not mapped to object. 0x000000000021f412 in pass2check (idesc=0x7fffffffe7b8) at pass2.c:554 554 if (inp->i_parent == 0) { (gdb) where #0 0x000000000021f412 in pass2check (idesc=0x7fffffffe7b8) at pass2.c:554 #1 0x00000000002093e7 in dirscan (idesc=0x7fffffffe7b8) at dir.c:211 #2 0x000000000021318b in ckinode (dp=0x7fffffffe6b8, idesc=0x7fffffffe7b8) at inode.c:126 #3 0x000000000021e130 in pass2 () at pass2.c:202 #4 0x0000000000219a7d in checkfilesys (filesys=0x7fffffffed71 "junk") at main.c:468 #5 0x0000000000218f42 in main (argc=1, argv=0x7fffffffea20) at main.c:210
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=03a8680202ef7d7e68adc70625633c490b4ed637 commit 03a8680202ef7d7e68adc70625633c490b4ed637 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2023-05-27 05:41:57 +0000 Commit: Kirk McKusick <mckusick@FreeBSD.org> CommitDate: 2023-05-27 05:43:21 +0000 Correct two bugs in fsck_ffs(8) triggered by corrupted filesystems. Always create a directory inode structure when a directory inode is found in Pass 1 as it is not known whether it will be saved or removed in later passes. If it is to be saved the directory inode structure is needed to track its status and fsck_ffs(8) will segment fault if it does not exist. Reported-by: Robert Morris PR: 271310 PR: 271354 MFC-after: 1 week Sponsored-by: The FreeBSD Foundation sbin/fsck_ffs/pass1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Fix checked in. Will close when MFC'ed to 13.
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=52f50301aaabddc6e3c1bc8c354101cfd7ea0463 commit 52f50301aaabddc6e3c1bc8c354101cfd7ea0463 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2023-05-27 05:41:57 +0000 Commit: Kirk McKusick <mckusick@FreeBSD.org> CommitDate: 2023-06-07 22:40:35 +0000 Correct two bugs in fsck_ffs(8) triggered by corrupted filesystems. Reported-by: Robert Morris PR: 271310 PR: 271354 Sponsored-by: The FreeBSD Foundation (cherry picked from commit 03a8680202ef7d7e68adc70625633c490b4ed637) sbin/fsck_ffs/pass1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
MFC'ed to 13.