Page MenuHomeFreeBSD
Paste P380

PR 244089 investigation 1/n
ActivePublic

Authored by cem on Apr 25 2020, 5:25 AM.
$ fsdb -r ./baddisk.img
> cd a
> ls
slot 2 off 24 ino 4 reclen 488: regular, `c.pdf'
> inode 4
current inode: regular file
I=4 MODE=100770 SIZE=89518
BTIME=Apr 22 04:55:41 2020 [0 nsec]
MTIME=Apr 22 04:55:41 2020 [0 nsec]
CTIME=Apr 22 10:11:52 2020 [904270000 nsec]
ATIME=Apr 22 10:16:09 2020 [826906000 nsec]
OWNER=root GRP=stress2user LINKCNT=1 FLAGS=0 BLKCNT=b8 GEN=1c8ba184
&
$ bg
$ gdb $(which fsdb) $(pgrep fsdb)
...
(gdb) p curinode.dp2.di_extb
$1 = {89, 0}
(gdb) p curinode.dp2.di_extsize
$2 = 192
$ dumpfs ./baddisk.img
...
cg 0:
magic 90255 tell 20000 time Wed Apr 22 10:11:52 2020
cgx 0 ndblk 1032 niblk 640 initiblk 256 unrefs 0
nbfree 114 ndir 2 nifree 635 nffree 14
rotor 0 irotor 4 frotor 88
frsum 1 0 0 0 0 1 1
sum of frsum: 14
clusters 1-3: 0 1 0
clusters size 4 and over: 1
clusters free: 13-14, 17-128
inodes used: 0-4
blks free: 87, 90-95, 97-119, 136-1031
... ^ 89 allocated
0x59 = 89 (di_extb[0]), 0x1000 = 4kB
$ hd < baddisk.img | less
...
*
00059000 30 00 00 00 01 00 29 44 6f 73 53 74 72 65 61 6d |0.....)DosStream|
00059010 2e 63 6f 6d 2e 61 70 70 6c 65 2e 6c 61 73 74 75 |.com.apple.lastu|
00059020 73 65 64 64 61 74 65 23 50 53 3a 24 44 41 54 41 |seddate#PS:$DATA|
00059030 48 00 00 00 01 00 09 44 4f 53 41 54 54 52 49 42 |H......DOSATTRIB|
00059040 30 78 32 30 00 00 03 00 03 00 00 00 11 00 00 00 |0x20............|
00059050 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ...............|
00059060 00 00 00 00 00 00 00 00 80 9c 1d f2 9c 18 d6 01 |................|
00059070 00 00 00 00 00 00 00 00 00 00 00 00 01 04 09 44 |...............D|
00059080 4f 53 41 54 54 52 49 42 30 78 30 00 03 00 03 00 |OSATTRIB0x0.....|
00059090 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000590a0 00 00 00 00 00 00 00 00 00 00 00 00 ca f8 8f f2 |................|
000590b0 9c 18 d6 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000590c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00060000 03 00 00 00 0c 00 04 01 2e 00 00 00 02 00 00 00 |................|
// i_ea_area, struct extattr header
/*
* This structure defines the required fields of an extended-attribute header.
*/
struct extattr {
uint32_t ea_length; /* length of this attribute */
uint8_t ea_namespace; /* name space of this attribute */
uint8_t ea_contentpadlen; /* bytes of padding at end of attribute */
uint8_t ea_namelength; /* length of attribute name */
char ea_name[1]; /* attribute name (NOT nul-terminated) */
/* padding, if any, to align attribute content to 8 byte boundary */
/* extended attribute content follows */
};
/*
* These macros are used to access and manipulate an extended attribute:
*
* EXTATTR_NEXT(eap) returns a pointer to the next extended attribute
* following eap.
* EXTATTR_CONTENT(eap) returns a pointer to the extended attribute
* content referenced by eap.
* EXTATTR_CONTENT_SIZE(eap) returns the size of the extended attribute
* content referenced by eap.
*/
#define EXTATTR_NEXT(eap) \
((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length))
#define EXTATTR_CONTENT(eap) \
(void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap))
#define EXTATTR_CONTENT_SIZE(eap) \
((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
/* -1 below compensates for ea_name[1] */
#define EXTATTR_BASE_LENGTH(eap) \
roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8)
So:
di_extsize == 192 == 0xc0
1st extattr:
00059000 30 00 00 00 01 00 29 44 6f 73 53 74 72 65 61 6d |0.....)DosStream|
|ea_length| ns cp nl | ea_name ...
00059010 2e 63 6f 6d 2e 61 70 70 6c 65 2e 6c 61 73 74 75 |.com.apple.lastu|
00059020 73 65 64 64 61 74 65 23 50 53 3a 24 44 41 54 41 |seddate#PS:$DATA|
... ea_name |
So it's empty and has the name "DosStream.com.apple.lastuseddate#PS:$DATA". So far so good.
2nd extattr:
00059030 48 00 00 00 01 00 09 44 4f 53 41 54 54 52 49 42 |H......DOSATTRIB|
|ea_length| ns cp nl | ea_name ... |
00059040 30 78 32 30 00 00 03 00 03 00 00 00 11 00 00 00 |0x20............|
|^EXTATTR_CONTENT ...
00059050 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ...............|
00059060 00 00 00 00 00 00 00 00 80 9c 1d f2 9c 18 d6 01 |................|
00059070 00 00 00 00 00 00 00 00 |........|
... EXTATTR_CONTENT |
It's named "DOSATTRIB" and has 0x28 bytes of content, including the prefix ASCII string "0x20". Seems fine.
3rd extattr:
00059070 00 00 00 00 01 04 09 44 |.......D|
|ea_length| ns cp nl | ea_name ...
00059080 4f 53 41 54 54 52 49 42 30 78 30 00 03 00 03 00 |OSATTRIB0x0.....|
... ea_name | | ...
00059090 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000590a0 00 00 00 00 00 00 00 00 00 00 00 00 ca f8 8f f2 |................|
000590b0 9c 18 d6 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
... ??? |
The 3rd extattr has a bogus ea_length of zero, which probably causes the infinite
loop during listextattr or findextattr type operations. These loops are generally
of the form:
for (p = 0; p < end; p += p->ea_length)
Obviously that doesn't work well if ea_length is zero.
So: we have a workaround for a corrupt FS image: check for zero ea_length. But
the root problem here seems to be the zero ea_length in the first place.

Event Timeline

cem created this object in space S1 Global.
cem created this object with edit policy "No One".