DragonFlyBSD Kernel Audit
DF-2804 / churn.c
← back to finding ↓ download raw
/*
 * DF-2803 / DF-2804: unprivileged udev event source.
 *
 * Opens+closes ptys via /dev/ptmx (world-writable).  Every posix_openpt()
 * cycle creates two cdevs (ptm master + pts slave) and destroys them again,
 * each of which fires udev_event_attach()/udev_event_detach() on the devfs
 * core thread -> 4 queued udev events per cycle whenever an *initiated*
 * /dev/udev reader exists (kern_udev.c:507).
 *
 * Runs as any unprivileged user.
 */
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
	time_t t0;
	long cycles = 0;
	int sec = 0, ncycles = 0;

	if (argc == 2 && argv[1][0] != '-') {
		sec = atoi(argv[1]);
	} else if (argc == 3 && strcmp(argv[1], "-n") == 0) {
		ncycles = atoi(argv[2]);
	} else {
		fprintf(stderr, "usage: %s -n <cycles> | %s <seconds>\n",
		    argv[0], argv[0]);
		return 2;
	}

	t0 = time(NULL);
	for (;;) {
		int fdm = posix_openpt(O_RDWR | O_NOCTTY);
		if (fdm < 0) {
			if (errno == EAGAIN || errno == ENOMEM) {
				usleep(1000);
			} else {
				perror("churn: posix_openpt");
				break;
			}
		} else {
			close(fdm);
			cycles++;
		}
		if (ncycles) {
			if (cycles >= ncycles)
				break;
		} else if ((int)(time(NULL) - t0) >= sec) {
			break;
		}
	}
	printf("churn: %ld pty cycles in %lds\n", cycles,
	    (long)(time(NULL) - t0));
	return 0;
}