⬢ DragonFlyBSD Kernel Audit
DF-4582 / rs690_div0.c
← back to finding ↓ download raw
/*
 * DF-4582 / DF-4583 userland reproduction of the rs690 dfixed_div
 * divide-by-zero.  Compiles the VERBATIM kernel function
 * (rs690_div0_body.h) in userspace and feeds it the attacker-shaped
 * inputs.  Expected: "Floating point exception" (SIGFPE) — the
 * userland twin of the kernel's divide-error (#DE) panic.
 *
 * usage: ./rs690_div0 [0|1|2]     (default: all scenarios in order)
 */
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include "rs690_div0_body.h"

static void run_scenario(int s)
{
	struct df4582_rdev rdev;
	struct df4582_crtc crtc;
	struct rs690_watermark wm;
	volatile u32 sink;

	fprintf(stderr, "== scenario %d: entering rs690_crtc_bandwidth_compute()\n", s);
	df4582_setup(&rdev, &crtc, s);
	fprintf(stderr, "== scenario %d: mode.clock=%d kHz, sideport=%d, pm.sclk=%u\n",
		s, crtc.base.mode.clock, rdev.mc.igp_sideport_enabled,
		rdev.pm.sclk.full >> 12);
	rs690_crtc_bandwidth_compute(&rdev, &crtc, &wm, 0);
	sink = wm.lb_request_fifo_depth;
	fprintf(stderr, "== scenario %d: survived (fifo=%u)\n", s, sink);
	(void)sink;
}

int main(int argc, char **argv)
{
	int first = (argc > 1) ? atoi(argv[1]) : 0;
	int last  = (argc > 1) ? first : 2;
	int s;

	for (s = first; s <= last; s++) {
		pid_t p = fork();
		if (p == 0) {
			run_scenario(s);
			_exit(0);
		} else {
			int st = 0;
			waitpid(p, &st, 0);
			if (WIFSIGNALED(st))
				fprintf(stderr, "== scenario %d: child killed by signal %d (%s)\n\n",
					s, WTERMSIG(st), strsignal(WTERMSIG(st)));
			else
				fprintf(stderr, "== scenario %d: child exited %d\n\n", s, WEXITSTATUS(st));
		}
	}
	return 0;
}