/*
 * DF-4758 — trigger for vinumsize() OOB read via swapon(2) on raw vinum
 * subdisk device nodes.
 *
 * Root cause (sys/dev/raid/vinum/vinum.c:558-572):
 *   vinumsize() does `vol = &VOL[Volno(dev)]` with no DEVTYPE dispatch and
 *   no bounds check. For raw subdisk devices the minor number is
 *   VINUM_SD(sdno) = (VINUM_RAWSD_TYPE<<28) | (sdno & 0xff) | ...
 *   so Volno(dev) == sdno & 0xff — the *subdisk* number is used to index
 *   the *volume* array. vinum_conf.volume has volumes_allocated entries
 *   (4 initially); any subdisk with sdno >= volumes_allocated reads out of
 *   bounds. Even in-bounds indices return the *volume's* size (and only
 *   when that volume happens to be up) instead of the subdisk's size.
 *
 * This program does not itself trigger anything exotic: it just calls
 * swapon(2) on device paths (the kernel then does VOP_OPEN + dev_dpsize()
 * -> vinumsize() exactly as sys/vm/vm_swap.c:296-308 does for any swapon
 * candidate). We do it from C so the exact errno / result is visible.
 *
 * Build:  cc -O -o df4758_swapon df4758_swapon.c
 * Run (root, after vinum config exists):
 *   ./df4758_swapon /dev/vinum/sd/s0   # in-bounds wrong object (volume v0 size)
 *   ./df4758_swapon /dev/vinum/sd/s1   # in-bounds, VOL[1] unallocated -> ENXIO
 *   ./df4758_swapon /dev/vinum/sd/s4   # OOB: VOL[4] past 4-entry array
 *   ./df4758_swapon /dev/vinum/sd/s5   # OOB: VOL[5]
 * then `swapinfo` to see what size was installed.
 */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int
main(int argc, char **argv)
{
	int i;

	if (argc < 2) {
		fprintf(stderr, "usage: %s device...\n", argv[0]);
		return 2;
	}
	for (i = 1; i < argc; i++) {
		errno = 0;
		printf("== swapon(%s): ", argv[i]);
		fflush(stdout);
		if (swapon(argv[i]) == 0)
			printf("OK\n");
		else
			printf("FAILED errno=%d (%s)\n", errno, strerror(errno));
		fflush(stdout);
	}
	printf("== swapinfo now:\n");
	fflush(stdout);
	system("swapinfo");
	return 0;
}
