DragonFlyBSD Kernel Audit
DF-1603 / df1603_fixed.c
← back to finding ↓ download raw
/*
 * DF-1603 - fixed-logic variant of the div-by-zero harness.
 *
 * Applies the same validation the fix.diff introduces to virtio_blk.c:702-705:
 * refuse blk_size < DEV_BSIZE or non-power-of-2 and fall back to 512. With
 * the validation in place, blk_size=0 no longer reaches the division on
 * line 709 and no SIGFPE/#DE is produced.
 *
 * Build:  cc -O2 -o df1603_fixed df1603_fixed.c
 * Run:    ./df1603_fixed   ; exits 0 if NO div-by-zero happens (fix confirmed)
 */
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define DEV_BSIZE 512

static int
powerof2_local(unsigned x) { return x && ((x & (x - 1)) == 0); }

/* Mirror virtio_blk.c:702-712 AFTER the fix.diff is applied. */
static void
vtblk_alloc_disk_fixed(int feature_negotiated, uint64_t capacity,
    uint32_t blk_size, uint64_t *out_blocks, uint32_t *out_bs)
{
	uint32_t sector_size;

	if (feature_negotiated &&
	    blk_size >= DEV_BSIZE &&
	    powerof2_local(blk_size))
		sector_size = blk_size;
	else
		sector_size = DEV_BSIZE;	/* fall back - the fix */

	*out_bs = sector_size;
	*out_blocks = capacity * 512 / sector_size;
}

int
main(void)
{
	uint64_t blocks;
	uint32_t bs;

	/* Same malicious input as the trigger PoC: feature negotiated + 0. */
	vtblk_alloc_disk_fixed(1, 0x100000ULL, 0, &blocks, &bs);
	printf("[fixed] blk_size=0 -> sector_size=%u (fell back to 512), "
	    "blocks=%llu - NO div-by-zero\n", bs, (unsigned long long)blocks);

	if (bs == DEV_BSIZE && blocks == 0x100000ULL) {
		printf("[OK] fix confirmed: blk_size=0 no longer reaches the "
		    "division; kernel would not panic.\n");
		return 0;
	}
	printf("[FAIL] unexpected result.\n");
	return 1;
}