DragonFlyBSD Kernel Audit
DF-2768 / probe_oob_unit.c
← back to finding ↓ download raw
/*
 * DF-2768 probe stage 2: with 1000 ptys held open, characterize the
 * unit-1000 (ptis[1000] OOB) pty that the 1001st clone creates.
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAXPTYS 1000

static void
timeout(int sig __unused)
{
	fprintf(stderr, "ALARM: operation hung\n");
	_exit(9);
}

int
main(void)
{
	int fds[MAXPTYS + 16];
	int n = 0, i, fd;
	struct stat st;

	signal(SIGALRM, timeout);

	for (i = 0; i < MAXPTYS; i++) {
		fd = open("/dev/ptmx", O_RDWR);
		if (fd < 0) {
			printf("pre-fill open #%d failed: %s\n", i, strerror(errno));
			return 1;
		}
		fds[n++] = fd;
	}
	printf("holding %d ptys\n", n);

	/* the OOB clone */
	alarm(10);
	fd = open("/dev/ptmx", O_RDWR);
	alarm(0);
	if (fd < 0)
		printf("open #1001 (OOB unit): FAILED %s(%d)\n", strerror(errno), errno);
	else
		printf("open #1001 (OOB unit): SUCCEEDED fd=%d\n", fd);
	fflush(stdout);

	if (stat("/dev/pts/1000", &st) == 0)
		printf("/dev/pts/1000 exists: %o %d:%d\n", st.st_mode, st.st_uid, st.st_gid);
	else
		printf("/dev/pts/1000 missing: %s\n", strerror(errno));
	fflush(stdout);

	if (stat("/dev/ptm/1000", &st) == 0)
		printf("/dev/ptm/1000 exists\n");
	else
		printf("/dev/ptm/1000 stat: %s\n", strerror(errno));
	fflush(stdout);

	/* next unit must be refused */
	errno = 0;
	alarm(10);
	fd = open("/dev/ptmx", O_RDWR);
	alarm(0);
	if (fd < 0)
		printf("open #1002: refused %s(%d)\n", strerror(errno), errno);
	else
		printf("open #1002: SUCCEEDED fd=%d (further OOB!)\n", fd);
	fflush(stdout);

	/* try to open the OOB slave (NONBLOCK to avoid carrier wait) */
	alarm(10);
	fd = open("/dev/pts/1000", O_RDWR | O_NONBLOCK);
	alarm(0);
	if (fd < 0)
		printf("open /dev/pts/1000: %s(%d)\n", strerror(errno), errno);
	else
		printf("open /dev/pts/1000: SUCCEEDED fd=%d\n", fd);
	fflush(stdout);

	/* try the OOB master by name (hidden by devfs on default rules) */
	alarm(10);
	fd = open("/dev/ptm/1000", O_RDWR | O_NONBLOCK);
	alarm(0);
	if (fd < 0)
		printf("open /dev/ptm/1000: %s(%d)\n", strerror(errno), errno);
	else
		printf("open /dev/ptm/1000: SUCCEEDED fd=%d\n", fd);
	fflush(stdout);

	printf("sleeping 5 with everything held...\n");
	fflush(stdout);
	sleep(5);
	return 0;
}