[Bug 271310] potential NULL dereference in fsck_ffs's changeino()
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 271310] potential NULL dereference in fsck_ffs's changeino()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 271310] potential NULL dereference in fsck_ffs's changeino()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 271310] potential NULL dereference in fsck_ffs's changeino()"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 271310] potential NULL dereference in fsck_ffs's changeino()"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 08 May 2023 08:55:23 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271310 Bug ID: 271310 Summary: potential NULL dereference in fsck_ffs's changeino() Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: bin Assignee: bugs@FreeBSD.org Reporter: rtm@lcs.mit.edu Created attachment 242049 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=242049&action=edit a broken FS image that causes a NULL dereference in fsck's changeino() Running fsck_ffs -y on the attached image causes this line in sbin/fsck_ffs/dir.c changeino() to dereference NULL: getinoinfo(dir)->i_depth = depth; I think the reason is that the link count of the i-node in question (i-number 3, a directory) has its high bit set, so that it looks negative in di_nlink (which is int16_t) in this code in checkinode() in pass1.c: 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); countdirs++; } As a result, ino_state is set to DZLINK, and cacheino() is not called, which is why getinoinfo() eventually returns NULL. Later, in pass4(), I think the expectation is that ino_linkcnt will be zero, and clri() will be called. But in fact ino_linkcnt is not zero (it's negative), so adjust() is called, which effectively expects cacheino() to have been called. case DZLINK: if (inoinfo(inumber)->ino_linkcnt == 0) { clri(&idesc, "UNREF", 1); break; } /* fall through */ case FSTATE: case DFOUND: n = inoinfo(inumber)->ino_linkcnt; if (n) { adjust(&idesc, (short)n); A backtrace from fsck_ffs -y fsck13a.img : Program received signal SIGSEGV, Segmentation fault. Address not mapped to object. 0x000000000020b165 in changeino (dir=3, name=0x201ecf "..", newnum=4, depth=2) at dir.c:712 712 getinoinfo(dir)->i_depth = depth; (gdb) where #0 0x000000000020b165 in changeino (dir=3, name=0x201ecf "..", newnum=4, depth=2) at dir.c:712 #1 0x000000000020a553 in linkup (orphan=3, parentdir=0, name=0x0) at dir.c:664 #2 0x0000000000209acd in adjust (idesc=0x7fffffffe7d0, lcnt=-32765) at dir.c:470 #3 0x000000000022025e in pass4 () at pass4.c:94 #4 0x0000000000219ae9 in checkfilesys (filesys=0x7fffffffed79 "junk") at main.c:484 #5 0x0000000000218f42 in main (argc=1, argv=0x7fffffffea28) at main.c:210 -- You are receiving this mail because: You are the assignee for the bug.