diff --git a/sys/vfs/hammer2/hammer2_strategy.c b/sys/vfs/hammer2/hammer2_strategy.c index 0000000..1111111 100644 --- a/sys/vfs/hammer2/hammer2_strategy.c +++ b/sys/vfs/hammer2/hammer2_strategy.c @@ -448,7 +448,17 @@ if (focus->bref.type == HAMMER2_BREF_TYPE_INODE) { /* * Copy from in-memory inode structure. + * + * Guard against a NULL data pointer (e.g. a corrupted + * bref.data_off of 0 causes chain_load_data to leave + * chain->data NULL without setting an error). */ + if (data == NULL) { + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + bp->b_resid = bp->b_bcount; + return; + } bcopy(((const hammer2_inode_data_t *)data)->u.data, bp->b_data, HAMMER2_EMBEDDED_BYTES); bzero(bp->b_data + HAMMER2_EMBEDDED_BYTES, @@ -482,6 +492,14 @@ bio); /* b_resid set by call */ break; + case HAMMER2_COMP_AUTOZERO: + /* + * Block is logically zero; not stored on media. + */ + bzero(bp->b_data, bp->b_bcount); + bp->b_resid = 0; + bp->b_error = 0; + break; case HAMMER2_COMP_NONE: KKASSERT(focus->bytes <= bp->b_bcount); bcopy(data, bp->b_data, focus->bytes); @@ -493,11 +511,29 @@ bp->b_error = 0; break; default: - panic("hammer2_strategy_read_completion: " - "unknown compression type"); + /* + * Unknown / out-of-range compression method from a + * corrupted or crafted image: report EIO instead of + * panicking the kernel. + */ + kprintf("hammer2_strategy_read_completion: " + "unknown compression type %d\n", + HAMMER2_DEC_COMP(focus->bref.methods)); + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + bp->b_resid = bp->b_bcount; + break; } } else { - panic("hammer2_strategy_read_completion: unknown bref type"); + /* + * Unknown / out-of-range bref type from a corrupted or + * crafted image: report EIO instead of panicking the kernel. + */ + kprintf("hammer2_strategy_read_completion: unknown bref type %d\n", + focus->bref.type); + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + bp->b_resid = bp->b_bcount; } }