Closed stoeckmann closed 1 year ago
How to reproduce, basically copied from https://github.com/umlaeute/v4l2loopback/pull/493
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
void hax0r_out(char* message, bool success, int err) {
printf("%s: %s\n", message, success ? "\033[1;32msuccess\033[0m" : "\033[1;31mfailed\033[0m");
if(!success) {
printf("ERROR %d: %s\n", err, strerror(err));
exit(1);
}
}
static void loopback_init(int fdwr, int w, int h) {
struct v4l2_capability vid_caps;
struct v4l2_format vid_format;
size_t linewidth = w * 2;
size_t framesize = h * linewidth;
int ret_code;
ret_code = ioctl(fdwr, VIDIOC_QUERYCAP, &vid_caps);
hax0r_out("Querying device capabilities", ret_code >= 0, errno);
memset(&vid_format, 0, sizeof(vid_format));
vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
vid_format.fmt.pix.width = w;
vid_format.fmt.pix.height = h;
vid_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
vid_format.fmt.pix.sizeimage = framesize;
vid_format.fmt.pix.field = V4L2_FIELD_NONE;
vid_format.fmt.pix.bytesperline = linewidth;
vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
ret_code = ioctl(fdwr, VIDIOC_S_FMT, &vid_format);
hax0r_out("Setting frame format", ret_code >= 0, errno);
ret_code = ioctl(fdwr, VIDIOC_STREAMON, &vid_format.type);
hax0r_out("Activate video streaming", ret_code >= 0, errno);
}
static void loopback_free(int fdwr) {
const enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
int ret_code = ioctl(fdwr, VIDIOC_STREAMOFF, &type);
hax0r_out("Deactivate video streaming", ret_code >= 0, errno);
}
int main(int argc, char **argv) {
char *dev;
int fd;
struct v4l2_frmivalenum val = { 0 };
if (argc < 2) {
hax0r_out("Checking arguments", false, EINVAL);
}
dev = argv[1];
hax0r_out("Checking device filename", strlen(dev), EINVAL);
fd = open(dev, O_RDWR | O_CLOEXEC);
hax0r_out("Opening device", fd >= 0, errno);
loopback_init(fd, 800, 600);
/* Here be exploits … */
val.width = 800;
val.height = 600;
hax0r_out("Enumerating frame intervals (1)", ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &val) == 0, EINVAL);
hax0r_out("Enumerating frame intervals (2)", ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &val) == 0, EINVAL);
loopback_free(fd);
hax0r_out("Closing device", close(fd) >= 0, errno);
return 0;
}
thanks for your contribution.
closing as obsolete.
Currently the code allows only one successful ioctl call for VIDIOC_ENUM_FRAMEINTERVALS. This is most likely introduced to stop enumerating loops in userland tools.
The checks should comply with vidioc_enum_framesizes instead, which properly address this through index.