/*
 * DF-4377 reachability probe — bktr_card.c uninitialized-EEPROM disclosure.
 *
 * The vulnerable path is device-side (probeCard() at attach / at first open
 * after a hw.bt848.card sysctl change).  There is no direct userland trigger
 * for the *uninitialized* read itself: the userland-reachable BT848_REEPROM
 * ioctl (bktr_core.c:2086) drives the same readEEProm() helper but always
 * into a zeroed kernel buffer (mapped_ioctl bzero's IOC_OUT buffers), so the
 * CWE-457 exposure is only via the boot/probe kprintf()s at bktr_card.c:676,
 * :757 and :814.
 *
 * This probe documents attacker reachability of the driver surface from an
 * unprivileged account (device nodes are mode 0444, ioctls allowed on
 * O_RDONLY opens) and reports whether a bktr(4) device is present to observe
 * the console/dmesg output of a failed probe.
 *
 * Expected on real hardware: probe messages appear in dmesg; a card whose
 * EEPROM ACKs the probe but NAKs the sequential read makes probeCard print
 * uninitialized stack bytes ("subsystem 0x%04x 0x%04x" from eeprom[252..255]
 * that readEEProm() never filled).
 *
 * Expected on the audit QEMU guest: /dev/bktr0 does not exist -> exit 2.
 */
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* mirror of sys/dev/video/bktr/ioctl_bt848.h */
struct eeProm {
	short   offset;
	short   count;
	unsigned char bytes[256];
};
#define BT848_REEPROM	_IOWR('x', 51, struct eeProm)

int
main(void)
{
	struct eeProm ee;
	int fd;

	fd = open("/dev/bktr0", O_RDONLY);	/* 0444 node: unpriv open */
	if (fd < 0) {
		printf("DF-4377: /dev/bktr0 not present: %s\n",
		    strerror(errno));
		printf("DF-4377: guest has no bktr(4) hardware; the "
		    "probe-time uninit path cannot be exercised.\n");
		return (2);
	}
	printf("DF-4377: /dev/bktr0 opened unprivileged; issuing benign "
	    "BT848_REEPROM(0,4)\n");
	memset(&ee, 0, sizeof(ee));
	ee.offset = 0;
	ee.count = 4;
	if (ioctl(fd, BT848_REEPROM, &ee) < 0)
		printf("DF-4377: BT848_REEPROM: %s (expected benign path)\n",
		    strerror(errno));
	else
		printf("DF-4377: read %d bytes: %02x %02x\n", ee.count,
		    ee.bytes[0], ee.bytes[1]);
	printf("DF-4377: for the uninit disclosure, watch dmesg during "
	    "attach/open probe of a card whose EEPROM probe-ACKs but "
	    "read-NAKs (bktr_card.c:667/676/757/794/814)\n");
	close(fd);
	return (0);
}
