Skip to content

Commit 478c16c

Browse files
committed
scripts: Added better branch cksum checks
If we're fetching branches anyways, we might as well check that the checksums match. This helps protect against infinite loops in B-tree branches. Note this is equivalent to LFS_M_CKFETCHES. This is a bigger issue for dbg scripts since Rbyd.fetch is so forgiving. lfsr_btree_lookupnext is more likely to fail to parse when following an explicit trunk, though this already assumes previous cksum checks (lfsr_mount) failed to notice any issues.
1 parent e3fdc3d commit 478c16c

File tree

4 files changed

+91
-75
lines changed

4 files changed

+91
-75
lines changed

scripts/dbgbmap.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -616,13 +616,13 @@ def addr(self):
616616
self.trunk)
617617

618618
@classmethod
619-
def fetch(cls, f, block_size, blocks, trunk=None):
619+
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
620620
if isinstance(blocks, int):
621621
blocks = (blocks,)
622622

623623
if len(blocks) > 1:
624624
# fetch all blocks
625-
rbyds = [cls.fetch(f, block_size, block, trunk)
625+
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
626626
for block in blocks]
627627
# determine most recent revision
628628
i = 0
@@ -654,9 +654,9 @@ def fetch(cls, f, block_size, blocks, trunk=None):
654654

655655
# fetch the rbyd
656656
rev = fromle32(data[0:4])
657-
cksum = 0
658-
cksum_ = crc32c(data[0:4])
659-
cksum__ = cksum_
657+
cksum_ = 0
658+
cksum__ = crc32c(data[0:4])
659+
cksum___ = cksum__
660660
perturb = False
661661
eoff = 0
662662
eoff_ = None
@@ -670,33 +670,33 @@ def fetch(cls, f, block_size, blocks, trunk=None):
670670
while j_ < len(data) and (not trunk or eoff <= trunk):
671671
# read next tag
672672
v, tag, w, size, d = fromtag(data[j_:])
673-
if v != parity(cksum__):
673+
if v != parity(cksum___):
674674
break
675-
cksum__ ^= 0x00000080 if v else 0
676-
cksum__ = crc32c(data[j_:j_+d], cksum__)
675+
cksum___ ^= 0x00000080 if v else 0
676+
cksum___ = crc32c(data[j_:j_+d], cksum___)
677677
j_ += d
678678
if not tag & TAG_ALT and j_ + size > len(data):
679679
break
680680

681681
# take care of cksums
682682
if not tag & TAG_ALT:
683683
if (tag & 0xff00) != TAG_CKSUM:
684-
cksum__ = crc32c(data[j_:j_+size], cksum__)
684+
cksum___ = crc32c(data[j_:j_+size], cksum___)
685685
# found a cksum?
686686
else:
687687
# check cksum
688-
cksum___ = fromle32(data[j_:j_+4])
689-
if cksum__ != cksum___:
688+
cksum____ = fromle32(data[j_:j_+4])
689+
if cksum___ != cksum____:
690690
break
691691
# commit what we have
692692
eoff = eoff_ if eoff_ else j_ + size
693-
cksum = cksum_
693+
cksum_ = cksum__
694694
trunk_ = trunk__
695695
weight = weight_
696696
# update perturb bit
697697
perturb = tag & TAG_P
698698
# revert to data cksum and perturb
699-
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
699+
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
700700

701701
# evaluate trunks
702702
if (tag & 0xf000) != TAG_CKSUM:
@@ -720,18 +720,22 @@ def fetch(cls, f, block_size, blocks, trunk=None):
720720
if trunk and j_ + size > trunk:
721721
eoff_ = j_ + size
722722
eoff = eoff_
723-
cksum = cksum_
723+
cksum_ = cksum__
724724
trunk_ = trunk__
725725
weight = weight_
726726
trunk___ = 0
727727

728728
# update canonical checksum, xoring out any perturb state
729-
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
729+
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
730730

731731
if not tag & TAG_ALT:
732732
j_ += size
733733

734-
return cls(block, data, rev, eoff, trunk_, weight, cksum)
734+
# cksum mismatch?
735+
if cksum is not None and cksum_ != cksum:
736+
return cls(block, data, rev, 0, 0, 0, cksum_)
737+
738+
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
735739

736740
def lookup(self, rid, tag):
737741
if not self:
@@ -861,7 +865,7 @@ def btree_lookup(self, f, block_size, bid, *,
861865
not depth or depth_ < depth):
862866
tag, j, d, data = branch
863867
block, trunk, cksum = frombranch(data)
864-
rbyd = Rbyd.fetch(f, block_size, block, trunk)
868+
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
865869

866870
# corrupted? bail here so we can keep traversing the tree
867871
if not rbyd:
@@ -878,7 +882,7 @@ def mtree_lookup(self, f, block_size, mbid):
878882
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
879883
if not done and rid == -1 and tag == TAG_MTREE:
880884
w, block, trunk, cksum = frombtree(data)
881-
mtree = Rbyd.fetch(f, block_size, block, trunk)
885+
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
882886
# corrupted?
883887
if not mtree:
884888
return True, -1, 0, None
@@ -1161,7 +1165,7 @@ def main(disk, mroots=None, *,
11611165
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
11621166
if not done and rid == -1 and tag == TAG_MTREE:
11631167
w, block, trunk, cksum = frombtree(data)
1164-
mtree = Rbyd.fetch(f, block_size, block, trunk)
1168+
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
11651169

11661170
# traverse entries
11671171
mbid = -1
@@ -1263,7 +1267,7 @@ def main(disk, mroots=None, *,
12631267
# indirect btree?
12641268
elif tag == TAG_BTREE:
12651269
w, block, trunk, cksum = frombtree(data)
1266-
btree = Rbyd.fetch(f, block_size, block, trunk)
1270+
btree = Rbyd.fetch(f, block_size, block, trunk, cksum)
12671271
shrub = False
12681272

12691273
else:

scripts/dbgbtree.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ def addr(self):
288288
self.trunk)
289289

290290
@classmethod
291-
def fetch(cls, f, block_size, blocks, trunk=None):
291+
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
292292
if isinstance(blocks, int):
293293
blocks = (blocks,)
294294

295295
if len(blocks) > 1:
296296
# fetch all blocks
297-
rbyds = [cls.fetch(f, block_size, block, trunk)
297+
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
298298
for block in blocks]
299299
# determine most recent revision
300300
i = 0
@@ -326,9 +326,9 @@ def fetch(cls, f, block_size, blocks, trunk=None):
326326

327327
# fetch the rbyd
328328
rev = fromle32(data[0:4])
329-
cksum = 0
330-
cksum_ = crc32c(data[0:4])
331-
cksum__ = cksum_
329+
cksum_ = 0
330+
cksum__ = crc32c(data[0:4])
331+
cksum___ = cksum__
332332
perturb = False
333333
eoff = 0
334334
eoff_ = None
@@ -342,33 +342,33 @@ def fetch(cls, f, block_size, blocks, trunk=None):
342342
while j_ < len(data) and (not trunk or eoff <= trunk):
343343
# read next tag
344344
v, tag, w, size, d = fromtag(data[j_:])
345-
if v != parity(cksum__):
345+
if v != parity(cksum___):
346346
break
347-
cksum__ ^= 0x00000080 if v else 0
348-
cksum__ = crc32c(data[j_:j_+d], cksum__)
347+
cksum___ ^= 0x00000080 if v else 0
348+
cksum___ = crc32c(data[j_:j_+d], cksum___)
349349
j_ += d
350350
if not tag & TAG_ALT and j_ + size > len(data):
351351
break
352352

353353
# take care of cksums
354354
if not tag & TAG_ALT:
355355
if (tag & 0xff00) != TAG_CKSUM:
356-
cksum__ = crc32c(data[j_:j_+size], cksum__)
356+
cksum___ = crc32c(data[j_:j_+size], cksum___)
357357
# found a cksum?
358358
else:
359359
# check cksum
360-
cksum___ = fromle32(data[j_:j_+4])
361-
if cksum__ != cksum___:
360+
cksum____ = fromle32(data[j_:j_+4])
361+
if cksum___ != cksum____:
362362
break
363363
# commit what we have
364364
eoff = eoff_ if eoff_ else j_ + size
365-
cksum = cksum_
365+
cksum_ = cksum__
366366
trunk_ = trunk__
367367
weight = weight_
368368
# update perturb bit
369369
perturb = tag & TAG_P
370370
# revert to data cksum and perturb
371-
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
371+
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
372372

373373
# evaluate trunks
374374
if (tag & 0xf000) != TAG_CKSUM:
@@ -392,18 +392,22 @@ def fetch(cls, f, block_size, blocks, trunk=None):
392392
if trunk and j_ + size > trunk:
393393
eoff_ = j_ + size
394394
eoff = eoff_
395-
cksum = cksum_
395+
cksum_ = cksum__
396396
trunk_ = trunk__
397397
weight = weight_
398398
trunk___ = 0
399399

400400
# update canonical checksum, xoring out any perturb state
401-
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
401+
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
402402

403403
if not tag & TAG_ALT:
404404
j_ += size
405405

406-
return cls(block, data, rev, eoff, trunk_, weight, cksum)
406+
# cksum mismatch?
407+
if cksum is not None and cksum_ != cksum:
408+
return cls(block, data, rev, 0, 0, 0, cksum_)
409+
410+
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
407411

408412
def lookup(self, rid, tag):
409413
if not self:
@@ -673,7 +677,7 @@ def btree_lookup(bid, *,
673677
not depth or depth_ < depth):
674678
tag, j, d, data = branch
675679
block, trunk, cksum = frombranch(data)
676-
rbyd = Rbyd.fetch(f, block_size, block, trunk)
680+
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
677681

678682
# corrupted? bail here so we can keep traversing the tree
679683
if not rbyd:

scripts/dbglfs.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -319,13 +319,13 @@ def addr(self):
319319
self.trunk)
320320

321321
@classmethod
322-
def fetch(cls, f, block_size, blocks, trunk=None):
322+
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
323323
if isinstance(blocks, int):
324324
blocks = (blocks,)
325325

326326
if len(blocks) > 1:
327327
# fetch all blocks
328-
rbyds = [cls.fetch(f, block_size, block, trunk)
328+
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
329329
for block in blocks]
330330
# determine most recent revision
331331
i = 0
@@ -357,9 +357,9 @@ def fetch(cls, f, block_size, blocks, trunk=None):
357357

358358
# fetch the rbyd
359359
rev = fromle32(data[0:4])
360-
cksum = 0
361-
cksum_ = crc32c(data[0:4])
362-
cksum__ = cksum_
360+
cksum_ = 0
361+
cksum__ = crc32c(data[0:4])
362+
cksum___ = cksum__
363363
perturb = False
364364
eoff = 0
365365
eoff_ = None
@@ -373,33 +373,33 @@ def fetch(cls, f, block_size, blocks, trunk=None):
373373
while j_ < len(data) and (not trunk or eoff <= trunk):
374374
# read next tag
375375
v, tag, w, size, d = fromtag(data[j_:])
376-
if v != parity(cksum__):
376+
if v != parity(cksum___):
377377
break
378-
cksum__ ^= 0x00000080 if v else 0
379-
cksum__ = crc32c(data[j_:j_+d], cksum__)
378+
cksum___ ^= 0x00000080 if v else 0
379+
cksum___ = crc32c(data[j_:j_+d], cksum___)
380380
j_ += d
381381
if not tag & TAG_ALT and j_ + size > len(data):
382382
break
383383

384384
# take care of cksums
385385
if not tag & TAG_ALT:
386386
if (tag & 0xff00) != TAG_CKSUM:
387-
cksum__ = crc32c(data[j_:j_+size], cksum__)
387+
cksum___ = crc32c(data[j_:j_+size], cksum___)
388388
# found a cksum?
389389
else:
390390
# check cksum
391-
cksum___ = fromle32(data[j_:j_+4])
392-
if cksum__ != cksum___:
391+
cksum____ = fromle32(data[j_:j_+4])
392+
if cksum___ != cksum____:
393393
break
394394
# commit what we have
395395
eoff = eoff_ if eoff_ else j_ + size
396-
cksum = cksum_
396+
cksum_ = cksum__
397397
trunk_ = trunk__
398398
weight = weight_
399399
# update perturb bit
400400
perturb = tag & TAG_P
401401
# revert to data cksum and perturb
402-
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
402+
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
403403

404404
# evaluate trunks
405405
if (tag & 0xf000) != TAG_CKSUM:
@@ -423,18 +423,22 @@ def fetch(cls, f, block_size, blocks, trunk=None):
423423
if trunk and j_ + size > trunk:
424424
eoff_ = j_ + size
425425
eoff = eoff_
426-
cksum = cksum_
426+
cksum_ = cksum__
427427
trunk_ = trunk__
428428
weight = weight_
429429
trunk___ = 0
430430

431431
# update canonical checksum, xoring out any perturb state
432-
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
432+
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
433433

434434
if not tag & TAG_ALT:
435435
j_ += size
436436

437-
return cls(block, data, rev, eoff, trunk_, weight, cksum)
437+
# cksum mismatch?
438+
if cksum is not None and cksum_ != cksum:
439+
return cls(block, data, rev, 0, 0, 0, cksum_)
440+
441+
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
438442

439443
def lookup(self, rid, tag):
440444
if not self:
@@ -666,7 +670,7 @@ def btree_lookup(self, f, block_size, bid, *,
666670
rbyd = Rbyd.fetch(f, block_size, block, trunk)
667671

668672
# corrupted? bail here so we can keep traversing the tree
669-
if not rbyd:
673+
if not rbyd or rbyd.cksum != cksum:
670674
return False, bid + (rid_-rid), w, rbyd, -1, [], path
671675

672676
rid -= (rid_-(w-1))
@@ -879,7 +883,7 @@ def mtree_lookup(self, f, block_size, mbid):
879883
w, block, trunk, cksum = frombtree(data)
880884
mtree = Rbyd.fetch(f, block_size, block, trunk)
881885
# corrupted?
882-
if not mtree:
886+
if not mtree or mtree.cksum != cksum:
883887
return True, -1, 0, None
884888

885889
# lookup our mbid
@@ -979,7 +983,7 @@ def mtree_namelookup(self, f, block_size, did, name):
979983
w, block, trunk, cksum = frombtree(data)
980984
mtree = Rbyd.fetch(f, block_size, block, trunk)
981985
# corrupted?
982-
if not mtree:
986+
if not mtree or mtree.cksum != cksum:
983987
return False, -1, 0, None, -1, 0, 0
984988

985989
# lookup our name in the mtree

0 commit comments

Comments
 (0)