⬢ DragonFlyBSD Kernel Audit
DF-2655 / fix.diff
← back to finding ↓ download raw
--- sys/vfs/hammer2/hammer2_strategy.c
+++ sys/vfs/hammer2/hammer2_strategy.c
@@ -207,8 +207,20 @@
 		kprintf("READ PATH: Error during decompression."
 			"bio %016jx/%d\n",
 			(intmax_t)bio->bio_offset, bytes);
-		/* make sure it isn't random garbage */
-		bzero(compressed_buffer, bp->b_bufsize);
+		/*
+		 * Fail the buffer (DF-2655): never return fabricated
+		 * data to the caller.  Also return early because result
+		 * is negative here, and the tail zero-fill below would
+		 * otherwise compute bp->b_data + result with a negative
+		 * result, an out-of-bounds zeroing of |result| bytes
+		 * BEFORE bp->b_data.
+		 */
+		objcache_put(cache_buffer_read, compressed_buffer);
+		bp->b_flags |= B_ERROR;
+		bp->b_error = EIO;
+		bp->b_resid = bp->b_bcount;
+		bp->b_flags |= B_AGE;
+		return;
 	}
 	KKASSERT(result <= bp->b_bufsize);
 	bcopy(compressed_buffer, bp->b_data, bp->b_bufsize);
@@ -257,7 +269,17 @@
 	ret = inflate(&strm_decompress, Z_FINISH);
 	if (ret != Z_STREAM_END) {
 		kprintf("HAMMER2 ZLIB: Fatal error during decompression.\n");
-		bzero(compressed_buffer, bp->b_bufsize);
+		/*
+		 * Fail the buffer (DF-2655): never return fabricated
+		 * data to the caller.
+		 */
+		objcache_put(cache_buffer_read, compressed_buffer);
+		inflateEnd(&strm_decompress);
+		bp->b_flags |= B_ERROR;
+		bp->b_error = EIO;
+		bp->b_resid = bp->b_bcount;
+		bp->b_flags |= B_AGE;
+		return;
 	}
 	bcopy(compressed_buffer, bp->b_data, bp->b_bufsize);
 	result = bp->b_bufsize - strm_decompress.avail_out;