[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.