From: Matthew Dillon Date: Wed, 18 Aug 2010 20:56:23 +0000 (-0700) Subject: HAMMER UTILITY - Fix seg-fault on corrupt blockmap during recovery X-Git-Tag: v2.9.0~488 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/e0410f2302c1f2793ffcb04d70b240685a98fa2b HAMMER UTILITY - Fix seg-fault on corrupt blockmap during recovery * Fix a seg-fault which occurs when the recover directive hits a bad blockmap entry. Reported-by: "Miro Svetlik" --- diff --git a/sbin/hammer/blockmap.c b/sbin/hammer/blockmap.c index d61bfa5359..82ad0b5db3 100644 --- a/sbin/hammer/blockmap.c +++ b/sbin/hammer/blockmap.c @@ -55,6 +55,11 @@ blockmap_lookup(hammer_off_t zone_offset, int i; int error = 0; + if (save_layer1) + *save_layer1 = NULL; + if (save_layer2) + *save_layer2 = NULL; + zone = HAMMER_ZONE_DECODE(zone_offset); if (AssertOnFailure) { @@ -101,6 +106,9 @@ blockmap_lookup(hammer_off_t zone_offset, /* * The blockmap should match the requested zone (else the volume * header is mashed). + * + * Note that a valid offset can still be returned if AssertOnFailure + * is zero. */ if (AssertOnFailure) { assert(HAMMER_ZONE_DECODE(blockmap->alloc_offset) == zone); @@ -124,8 +132,13 @@ blockmap_lookup(hammer_off_t zone_offset, HAMMER_BLOCKMAP_LAYER1_OFFSET(result_offset); layer1 = get_buffer_data(layer1_offset, &buffer, 0); if (AssertOnFailure) { + assert(layer1); assert(layer1->phys_offset != HAMMER_BLOCKMAP_UNAVAIL); } else { + if (layer1 == NULL) { + error = EDOM; + goto done; + } if (layer1->phys_offset == HAMMER_BLOCKMAP_UNAVAIL) { error = EDOM; goto done; @@ -140,15 +153,22 @@ blockmap_lookup(hammer_off_t zone_offset, layer2_offset = layer1->phys_offset + HAMMER_BLOCKMAP_LAYER2_OFFSET(result_offset); layer2 = get_buffer_data(layer2_offset, &buffer, 0); - if (save_layer2) - *save_layer2 = *layer2; if (AssertOnFailure) { + assert(layer2); assert(layer2->zone == zone); } else { - if (layer2->zone != zone) + if (layer2 == NULL) { error = EDOM; + goto done; + } + if (layer2->zone != zone) { + error = EDOM; + goto done; + } } + if (save_layer2) + *save_layer2 = *layer2; done: if (buffer)