โฌข DragonFlyBSD Kernel Audit
DF-4028 / cb_rewrite_sim.c
โ† back to finding โ†“ download raw
/*
 * cb_rewrite_sim.c โ€” host-runnable arithmetic proof for DF-4028.
 *
 * Replicates the exact arithmetic of r600_cs_track_validate_cb()
 * (sys/dev/drm/radeon/r600_cs.c:350-514) for the default-initialized
 * track (r600_cs_track_init, r600_cs.c:300-348) when the user programs
 * CB_COLOR0_INFO / CB_TARGET_MASK / CB_COLOR0_BASE but NEVER writes the
 * CB_COLOR0_SIZE register:
 *
 *   track->cb_color_size[0]     = 0   (default)
 *   track->cb_color_size_idx[0] = 0   (default  <-- the bug)
 *
 * and shows the value the validator stores into ib[cb_color_size_idx[0]]
 * == ib[0] โ€” the first packet header of the (already-validated) IB.
 */
#include <stdio.h>
#include <stdint.h>

int main(void)
{
	unsigned pitch, slice_tile_max, height, array_mode = 0; /* LINEAR_GENERAL */
	unsigned tmp;
	unsigned cb_color_size = 0;        /* register never written */
	unsigned nsamples = 16;            /* track_init default */

	/* r600_cs.c:372-377 */
	pitch = (((cb_color_size) & 0x3FF) + 1) * 8;
	slice_tile_max = (((cb_color_size >> 10) & 0xFFFFF) + 1) * 64;
	height = slice_tile_max / pitch;
	if (height > 8192) height = 8192;

	/* r600_cs.c:413-427 with LINEAR_GENERAL alignments (1,1,1): pass */

	/* r600_cs.c:430-441 size check: skipped for LINEAR_GENERAL (444-450) */

	/* r600_cs.c:462-468: the rewrite */
	tmp = (height * pitch) >> 6;
	if (tmp < slice_tile_max)
		slice_tile_max = tmp;
	tmp = (((pitch / 8) - 1) & 0x3FF) | (((slice_tile_max - 1) & 0xFFFFF) << 10);

	printf("nsamples default       : %u\n", nsamples);
	printf("pitch                  : %u px\n", pitch);
	printf("slice_tile_max (raw)   : %u\n", slice_tile_max + 0);
	printf("height                 : %u\n", height);
	printf("LINEAR_GENERAL checks  : pitch_align=1 height_align=1 base_align=1"
	       " -> PASS; size check SKIPPED (linear hole)\n");
	printf("value written to ib[track->cb_color_size_idx[0]] (= ib[0]): "
	       "0x%08x\n", tmp);
	printf("\nib[0] == 0 is a CP type-0 header, count=0, reg=0:\n"
	       "  GPU consumes ib[0]+ib[1] as one PACKET0 write and re-starts\n"
	       "  command execution at ib[2] โ€” everything the validator saw as\n"
	       "  SET_ALU_CONST payload VALUES now executes as PACKETS.\n");
	return 0;
}