fsck this shit
goatshit54108 at national.shitposting.agency
goatshit54108 at national.shitposting.agency
Tue Jun 2 16:38:49 UTC 2020
Once upon a time, the power ran out, and then...
** SU+J Recovering /dev/<...>
** Reading 33554432 byte journal from inode 4.
** Building recovery table.
** Resolving unreferenced inode list.
** Processing journal entries.
fsck: /dev/<...>: Segmentation fault
GAAAY.
OK, let's check the core dump... oh, wait... tough luck. Fortunately, subsequent runs of fsck ended up likewise, so I was able to get a core dump by re-executing fsck while being inside a TMPFS-backed directory. (On the other hand, unfortunately, fsck was never able to replay the journal.) Furthermore, I saved the .sujournal file, but saving the contents of the whole filesystem was beyond my resources. (It would have been adequate to use a tool that collected (only) the blocks that fsck read before segfaulting (thus constructing a small test case), but no such tool was at hand.)
Before running "fsck -y" (because I had no other options) I looked at "fsck -n" to see whether a particular, large file would get idiotically removed as part of "fixing" the filesystem. This routine is prompted by (1) personal experiences of files getting lost or truncated to 0 length, and (2) past reports of disasterous behaviors involving soft updates, such as untouched (read-only) files getting lost; "lost" means not even relinked to /lost+found or anything. And wouldn't ya know it, fsck did ask whether to remove something that had an unambiguously large size (to be exact, IIRC: "DUP ... REMOVE?", whatever that means). That's it, either (a) remove the file, or (b) stay dirty; take it or leave it. It's not like there was some 3rd option to relink the file to /lost+found. After "fsck -y", the file disappeared without a trace. GAAAAAAAAAY.
The fsck_ffs (or fsck_ufs) file was the one distributed with the 12.1-RELEASE, the one with the SHA3-256 checksum of 447592ae05dc7829823901700bb90940968cae006719964d39b1212bb312d164. Let's see the backtrace:
* thread #1, name = 'fsck_ufs', stop reason = signal SIGSEGV
* frame #0: 0x0000000000219d93 fsck_ffs`blk_free(bno=10692928, mask=0, frags=134643471) at suj.c:653:34
frame #1: 0x000000000021a481 fsck_ffs`ino_trunc(ino=5296913, size=134610944) at suj.c:1547:3
frame #2: 0x0000000000216fee fsck_ffs`suj_check [inlined] cg_adj_blk(sc=0x0000000801574540) at suj.c:1788:5
frame #3: 0x0000000000216fc3 fsck_ffs`suj_check [inlined] cg_apply at suj.c:1900
frame #4: 0x0000000000216fa5 fsck_ffs`suj_check(filesys="/dev/<...>") at suj.c:2737
frame #5: 0x000000000020ef54 fsck_ffs`main [inlined] checkfilesys(filesys="/dev/<...>") at main.c:427:9
frame #6: 0x000000000020ef07 fsck_ffs`main(argc=1, argv=0x00007fffffffec48) at main.c:205
frame #7: 0x000000000020810f fsck_ffs`_start(ap=<unavailable>, cleanup=<unavailable>) at crt1.c:76:7
Some analysis:
1. It's obvious that frags=134643471 is absurd.
2. The value of `frags` in frame #0 comes from the value of `frags` in frame #1. Regarding frame #1, which is a state of ino_trunc(): it is very suspicious that `frags` is assigned only in the first loop -- conditionally, even --, but is repeatedly used in the second loop. Is the 134643471 memory garbage? This smells GAAY.
3. In frame #0, we have i == 28262448, which means that relevant loop managed to garble >28 Mb of memory with 1-bits, as can be seen by the following: in frame #1, we have ip->dp2 ==
{
di_mode = 65535
di_nlink = -1
di_uid = 4294967295
di_gid = 4294967295
di_blksize = 4294967295
di_size = 18446744073709551615
di_blocks = 18446744073709551615
di_atime = -1
di_mtime = -1
di_ctime = -1
di_birthtime = -1
di_mtimensec = -1
di_atimensec = -1
di_ctimensec = -1
di_birthnsec = -1
di_gen = 4294967295
di_kernflags = 4294967295
di_flags = 4294967295
di_extsize = 4294967295
di_extb = ([0] = -1, [1] = -1)
di_db = ([0] = -1, [1] = -1, [2] = -1, [3] = -1, [4] = -1, [5] = -1, [6] = -1, [7] = -1, [8] = -1, [9] = -1, [10] = -1, [11] = -1)
di_ib = ([0] = -1, [1] = -1, [2] = -1)
di_modrev = 18446744073709551615
di_freelink = 4294967295
di_spare = ([0] = 4294967295, [1] = 4294967295, [2] = 4294967295)
}.
4. By the way, *fs ==
{
fs_firstfield = 0
fs_unused_1 = 0
fs_sblkno = 24
fs_cblkno = 32
fs_iblkno = 40
fs_dblkno = 5056
fs_old_cgoffset = 0
fs_old_cgmask = 0
fs_old_time = 0
fs_old_size = 0
fs_old_dsize = 0
fs_ncg = 164
fs_bsize = 32768
fs_fsize = 4096
fs_frag = 8
fs_minfree = 0
fs_old_rotdelay = 0
fs_old_rps = 0
fs_bmask = -32768
fs_fmask = -4096
fs_bshift = 15
fs_fshift = 12
fs_maxcontig = 4
fs_maxbpg = 4096
fs_fragshift = 3
fs_fsbtodb = 3
fs_sbsize = 4096
fs_spare1 = ([0] = 0, [1] = 0)
fs_nindir = 4096
fs_inopb = 128
fs_old_nspf = 0
fs_optim = 1
fs_old_npsect = 0
fs_old_interleave = 0
fs_old_trackskew = 0
fs_id = ([0] = 1568391747, [1] = 841092898)
fs_old_csaddr = 0
fs_cssize = 4096
fs_cgsize = 32768
fs_spare2 = 0
fs_old_nsect = 0
fs_old_spc = 0
fs_old_ncyl = 0
fs_old_cpg = 0
fs_ipg = 80256
fs_fpg = 160280
fs_old_cstotal = (cs_ndir = 0, cs_nbfree = 0, cs_nifree = 0, cs_nffree = 0)
fs_fmod = '\0'
fs_clean = '\0'
fs_ronly = '\0'
fs_old_flags = '\x80'
fs_fsmnt = {
[0] = '/'
[1] = '\0'
...
}
fs_volname = {
[0] = '\0'
}
fs_swuid = 0
fs_pad = 0
fs_cgrotor = 91
fs_ocsp = ([0] = 0x0000000000000000, [1] = 0x0000000000000000, [2] = 0x0000000000000000, [3] = 0x0000000000000000, [4] = 0x0000000000000000, [5] = 0x0000000000000000, [6] = 0x0000000000000000, [7] = 0x0000000000000000, [8] = 0x0000000000000000, [9] = 0x0000000000000000, [10] = 0x0000000000000000, [11] = 0x0000000000000000)
fs_contigdirs = 0x0000000800692a90 <no value available>
fs_csp = 0x000000080069e000
fs_maxcluster = 0x0000000800692800
fs_active = 0x0000000000000000
fs_old_cpc = 0
fs_maxbsize = 32768
fs_unrefs = 0
fs_providersize = 26250240
fs_metaspace = 6408
fs_sparecon64 = ([0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0, [8] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0)
fs_sblockactualloc = 65536
fs_sblockloc = 65536
fs_cstotal = {
cs_ndir = 54923
cs_nbfree = 188121
cs_nifree = 12699260
cs_nffree = 59369
cs_numclusters = 0
cs_spare = ([0] = 0, [1] = 0, [2] = 0)
}
fs_time = 1588190343
fs_size = 26250240
fs_dsize = 25424967
fs_csaddr = 5056
fs_pendingblocks = 0
fs_pendinginodes = 0
fs_snapinum = {
[0] = 0
...
}
fs_avgfilesize = 16384
fs_avgfpdir = 64
fs_save_cgsize = 0
fs_mtime = 1588178967
fs_sujfree = 0
fs_sparecon32 = {
[0] = 0
...
}
fs_metackhash = 2
fs_flags = 522
fs_contigsumsize = 4
fs_maxsymlinklen = 120
fs_old_inodefmt = 0
fs_maxfilesize = 2252349704110079
fs_qbmask = 32767
fs_qfmask = 4095
fs_state = 0
fs_old_postblformat = 0
fs_old_nrpos = 0
fs_spare5 = ([0] = 0, [1] = 0)
fs_magic = 424935705
}.
More information about the freebsd-fs
mailing list