⬢ DragonFlyBSD Kernel Audit
DF-5106 / trig.c
← back to finding ↓ download raw
/*
 * trig - unprivileged user side of the DF-5106 reproduction.
 *
 * 1. open()s the MIDI cdev (mode 0666, any user can open it)
 * 2. writes MIDI bytes in a loop - each write arms M_TXEN which keeps
 *    the mpu401 callout (m->timer) perpetually re-armed, calling
 *    m->si(m->cookie) with cookie == the driver softc
 * 3. holds the fd open across the admin-side trigger
 *    (sysctl hw.simid.detach=1 for stage A, kldunload for stage B)
 *
 * usage: trig <seconds> [device]
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int
main(int argc, char **argv)
{
	int fd, i, secs = 10;
	const char *dev = "/dev/midi0.0";
	unsigned char note_on[3] = { 0x90, 0x40, 0x40 };

	if (argc > 1)
		secs = atoi(argv[1]);
	if (argc > 2)
		dev = argv[2];

	fd = open(dev, O_RDWR);
	if (fd < 0) {
		printf("trig: open(%s) failed: %s\n", dev, strerror(errno));
		return (1);
	}
	printf("trig: opened %s fd=%d uid=%d\n", dev, fd, getuid());

	for (i = 0; i < secs * 10; i++) {
		if (write(fd, note_on, 3) != 3) {
			printf("trig: write failed at %d: %s\n", i,
			    strerror(errno));
			/* keep the fd open even if writes start failing */
		}
		usleep(100 * 1000);
	}
	printf("trig: done, closing\n");
	close(fd);
	return (0);
}