From patchwork Tue Nov 26 16:18:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60406 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYT-006B0M-AF; Tue, 26 Nov 2019 16:19:09 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728806AbfKZQS7 (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:59 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:41601 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728146AbfKZQSl (ORCPT ); Tue, 26 Nov 2019 11:18:41 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MFL8J-1ibaYS3gVd-00Fkok; Tue, 26 Nov 2019 17:18:33 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 1/8] media: documentation: fix video_event description Date: Tue, 26 Nov 2019 17:18:17 +0100 Message-Id: <20191126161824.337724-2-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:O2/jQz6atdIoPkZzpfDsjDAz//w3xantCbjSR3tAaWYdZ8jpOKh ZUgeen38z5h+pLVR5FP6sQ2W/xw/2kHgo6mlLhvRdIMGneVTVk3s0pI6QyXaW2qv2uQPXUI T/l9xx+efbp61Juc/JdHbsPaEnWbrZ/fl2HVAoCdsxfKJHSlU/cfJAgPqaldX5DhucvZrz0 3FGi6Aplfk1ciZMPybeiA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:oum7zHKWCkI=:HupciVegc8wYBWgevpOL1Q o4o4TBM5lxVo017HqjJaX1nkaA9kO8Ofd76KplJuR7e8O6edx6yffyfE/FTMIzdhLA5viYexn kqjbqddnPEoMc2Gnp5kLbZl/Hpl2VN/TgrY0pyw0ZgHy1EkmIV6SjjM38tqsMDwzgUF8yR9Ol oQx9C5a2xnuWjK1LDLj1AU+JG3MNKl2T77E55SjFJ4Hr5wG06k4WwE0ZzwTBEgVl6ybCLx4SM 0r75I56TTtJS+DZpFlR5MaPbTu/XVxmB4C0JQuE2Qo1ihI2kMG9BGYXQL2Hrt63GkvWubtSFL H7ZRUeSRWkEiw6PUxFCrkNj6Thn7FoAsbUMoiHsu/XuIL8R/VUZ8POqH+azuJwvFq1p4RZuWC FB2U9pcIndXbXuY2KmEL8XRnv5wHzzRZ9Tje/T6X6bwmkU0MXJN1vZ0CFiH6RYrYQJILrSUm9 s0TXrz8TP/O8FRJAs+dNsRug3SpSjDYDRZRsoNQKFqxkxOcYlbVWem5JKjn7+7h7UG4BQqbN8 jhmFiX/ZhLBOKe20wp6xkKtWFTZPNCeCxq/8DE2UgYxMkQQm4zu3qRuna0Xdvnm8BJ688b8Up sOvicaprRhlKAwh156sR62zNd8tyKfVI5Y4TsVvStIGAkin9wVFVmHgPXCSqFSW0Uta++dir8 OC0/s7y9M0ezWZbC/kTXOFpGEwWq342RI2ljICfd2S9twkNAwScly90jdCL8XWoWlJZ9/Md/c NTzzOwNOe5SpdV/VcCzTnnRUWDYUw0m05fEy7+Nm2P9KHE7z0eU6UqX9rIXMI7h+4vx/240tG pqDJ0WT7fJf2+tosrVekV/ACcNCvFOglAsWF1Rgkn0hDDHC+S9J+GMo1t6o5sev5lmzS78/fv 9IRMSUwKjichLMLSMapQ== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The type for the timestamp in video_event was changed to 'long' a long time ago, change the documentation to match. Signed-off-by: Arnd Bergmann --- Documentation/media/uapi/dvb/video-get-event.rst | 2 +- Documentation/media/uapi/dvb/video_types.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/media/uapi/dvb/video-get-event.rst b/Documentation/media/uapi/dvb/video-get-event.rst index def6c40db601..7f03fbe3d3b0 100644 --- a/Documentation/media/uapi/dvb/video-get-event.rst +++ b/Documentation/media/uapi/dvb/video-get-event.rst @@ -81,7 +81,7 @@ for this ioctl call. #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 #define VIDEO_EVENT_VSYNC 4 - __kernel_time_t timestamp; + long timestamp; union { video_size_t size; unsigned int frame_rate; /* in frames per 1000sec */ diff --git a/Documentation/media/uapi/dvb/video_types.rst b/Documentation/media/uapi/dvb/video_types.rst index 479942ce6fb8..2697400ccf62 100644 --- a/Documentation/media/uapi/dvb/video_types.rst +++ b/Documentation/media/uapi/dvb/video_types.rst @@ -170,7 +170,7 @@ VIDEO_GET_EVENT call. #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 #define VIDEO_EVENT_VSYNC 4 - __kernel_time_t timestamp; + long timestamp; union { video_size_t size; unsigned int frame_rate; /* in frames per 1000sec */ From patchwork Tue Nov 26 16:18:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60403 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYE-006AzZ-Bm; Tue, 26 Nov 2019 16:18:54 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728735AbfKZQSw (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:52 -0500 Received: from mout.kundenserver.de ([212.227.17.13]:33753 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728475AbfKZQSn (ORCPT ); Tue, 26 Nov 2019 11:18:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1M42Ss-1iZdXu0Z1s-0007db; Tue, 26 Nov 2019 17:18:34 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 2/8] media: v4l2: abstract timeval handling in v4l2_buffer Date: Tue, 26 Nov 2019 17:18:18 +0100 Message-Id: <20191126161824.337724-3-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:wP8O+yAPzuZzdV0bYq+naeEf5uhuxbDAFZYzxUTCT7zjrNZbtVE 7Gk14qvXcSFCbIruEdKTiJjJolhJaNNbtJr9jqsGYnfZgftfOUXSwVjV6CW+43BqLDZ0rXr AOau8EpMjc6XC9R3vVYsEIUrFZ+mwng1EHTwDNnbMXtkuA3xeC+vN+yMb0C/sHMrp1VzN68 PjRIDQWu2bzOYm73Mc54w== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:qpoMj5+utN8=:/R+XZ/zPHFNOIgmygeVXiC tkswV2QHDo9avmOLOM3wQyLXhvEivoyYqn1vDAO0YrunrcF9wayLO0awm7BKsugVXwMMjgw2e VEQ7Exq+ZTaZ3Uz/iw7ylqp978cNWcYkLpcplnAqrTxorpzpQDRsUj7VuQxcxEtgBgw3x2OXq WUweU5SbryibO/ErGNooYOzHBYyo0n1tVkCsQ1uCw27DZMZf1j8AStbt2TD+UoD78sbCC47e6 W3J85xKXK//CC6TDM00DuL/lPRbfSQ1To/Lk7E58LbVYBHZymtecKeIhkinJsTSjX1SgH4ZqM fLu8COh/bH6Tdh8faty2JZ2hq0/MuklJPJIHdlwBrVrym+sNf7Q6nPVVnLhwN+VzKUXSdBLyN Hxt0CxSJyfcme9If/C1g5n+ZzB5bIc3Jgk2fWc2nZ0fqqU1IoLUY6kA/SE0By8G+ejoAqPrMy dBzLtiRN0+g1LwaRhChyYH9r2bWf9JUVI7mwzlc+LY5IpFzKqscaLt/N/ZVJ2BFpPERi/c7X7 deb35DRg7gbxkryMLnW/vFG57pGp4cbVTF4Sg5i0YnV2d360nfzROxSGqtqbjBTBpZHB44Qhd 6J15tXl9IxPBO9dTvK3L3HHgC0Xc3Z7HtLUBe/xu7Rp4cR+ZohgJuVkB4j497Rn4yVTFR4OGm sWcnTatI2J6ipavVXiiCmU1szmU6ksg2YCAm3qicN2iUwhe4dDAMfYjTb5mcrELXd24UHuup6 E0xlbmpe99Zx2dsUcHaZVuT6dyZeYOE2qNbA1n+ulqKTb4XiwmU7/hNTBezPG8fJfEbH3P7bo FUlc4DZzlZhSm++vUCGlXtGGzBaFACEp9USTX+lCULiXROe6aTCusa+w2YlUGQwBuTMd6+dB4 NED+i/pctiRndnKXrNAQ== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org As a preparation for adding 64-bit time_t support in the uapi, change the drivers to no longer care about the format of the timestamp field in struct v4l2_buffer. The v4l2_timeval_to_ns() function is no longer needed in the kernel after this, but there is userspace code relying on it to be part of the uapi header. Signed-off-by: Arnd Bergmann --- .../media/common/videobuf2/videobuf2-v4l2.c | 4 ++-- drivers/media/pci/meye/meye.c | 4 ++-- drivers/media/usb/cpia2/cpia2_v4l.c | 4 ++-- drivers/media/usb/stkwebcam/stk-webcam.c | 2 +- drivers/media/usb/usbvision/usbvision-video.c | 4 ++-- drivers/media/v4l2-core/videobuf-core.c | 5 +++-- include/media/v4l2-common.h | 21 +++++++++++++++++++ include/trace/events/v4l2.h | 2 +- include/uapi/linux/videodev2.h | 2 ++ 9 files changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index e652f4318284..eb5d5db96552 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -146,7 +146,7 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb) * and the timecode field and flag if needed. */ if (q->copy_timestamp) - vb->timestamp = v4l2_timeval_to_ns(&b->timestamp); + vb->timestamp = v4l2_buffer_get_timestamp(b); vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; if (b->flags & V4L2_BUF_FLAG_TIMECODE) vbuf->timecode = b->timecode; @@ -482,7 +482,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->flags = vbuf->flags; b->field = vbuf->field; - b->timestamp = ns_to_timeval(vb->timestamp); + v4l2_buffer_set_timestamp(b, vb->timestamp); b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; b->reserved2 = 0; diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 0e61c81356ef..3a4c29bc0ba5 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1266,7 +1266,7 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_DONE; buf->field = V4L2_FIELD_NONE; - buf->timestamp = ns_to_timeval(meye.grab_buffer[index].ts); + v4l2_buffer_set_timestamp(buf, meye.grab_buffer[index].ts); buf->sequence = meye.grab_buffer[index].sequence; buf->memory = V4L2_MEMORY_MMAP; buf->m.offset = index * gbufsize; @@ -1332,7 +1332,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->bytesused = meye.grab_buffer[reqnr].size; buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; buf->field = V4L2_FIELD_NONE; - buf->timestamp = ns_to_timeval(meye.grab_buffer[reqnr].ts); + v4l2_buffer_set_timestamp(buf, meye.grab_buffer[reqnr].ts); buf->sequence = meye.grab_buffer[reqnr].sequence; buf->memory = V4L2_MEMORY_MMAP; buf->m.offset = reqnr * gbufsize; diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 626264a56517..9d3d05125d7b 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -800,7 +800,7 @@ static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) break; case FRAME_READY: buf->bytesused = cam->buffers[buf->index].length; - buf->timestamp = ns_to_timeval(cam->buffers[buf->index].ts); + v4l2_buffer_set_timestamp(buf, cam->buffers[buf->index].ts); buf->sequence = cam->buffers[buf->index].seq; buf->flags = V4L2_BUF_FLAG_DONE; break; @@ -907,7 +907,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; buf->field = V4L2_FIELD_NONE; - buf->timestamp = ns_to_timeval(cam->buffers[buf->index].ts); + v4l2_buffer_set_timestamp(buf, cam->buffers[buf->index].ts); buf->sequence = cam->buffers[buf->index].seq; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index cfca3c70599b..1b730ac31499 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -1126,7 +1126,7 @@ static int stk_vidioc_dqbuf(struct file *filp, sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; sbuf->v4lbuf.sequence = ++dev->sequence; - sbuf->v4lbuf.timestamp = ns_to_timeval(ktime_get_ns()); + v4l2_buffer_set_timestamp(&sbuf->v4lbuf, ktime_get_ns()); *buf = sbuf->v4lbuf; return 0; diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 93d36aab824f..5ca2c2f35fe2 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -696,7 +696,7 @@ static int vidioc_querybuf(struct file *file, vb->length = usbvision->curwidth * usbvision->curheight * usbvision->palette.bytes_per_pixel; - vb->timestamp = ns_to_timeval(usbvision->frame[vb->index].ts); + v4l2_buffer_set_timestamp(vb, usbvision->frame[vb->index].ts); vb->sequence = usbvision->frame[vb->index].sequence; return 0; } @@ -765,7 +765,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb) V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; vb->index = f->index; vb->sequence = f->sequence; - vb->timestamp = ns_to_timeval(f->ts); + v4l2_buffer_set_timestamp(vb, f->ts); vb->field = V4L2_FIELD_NONE; vb->bytesused = f->scanlength; diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 939fc11cf080..2686f03b322e 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -19,6 +19,7 @@ #include #include +#include #define MAGIC_BUFFER 0x20070728 #define MAGIC_CHECK(is, should) \ @@ -364,7 +365,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, } b->field = vb->field; - b->timestamp = ns_to_timeval(vb->ts); + v4l2_buffer_set_timestamp(b, vb->ts); b->bytesused = vb->size; b->sequence = vb->field_count >> 1; } @@ -578,7 +579,7 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) { buf->size = b->bytesused; buf->field = b->field; - buf->ts = v4l2_timeval_to_ns(&b->timestamp); + buf->ts = v4l2_buffer_get_timestamp(b); } break; case V4L2_MEMORY_USERPTR: diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index d8c29e089000..8d0ac0311c84 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -14,6 +14,7 @@ #ifndef V4L2_COMMON_H_ #define V4L2_COMMON_H_ +#include #include /* Common printk constructs for v4l-i2c drivers. These macros create a unique @@ -518,4 +519,24 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, u32 width, u32 height); +static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) +{ + /* + * When the timestamp comes from 32-bit user space, there may be + * uninitialized data in tv_usec, so cast it to u32. + * Otherwise allow invalid input for backwards compatibility. + */ + return buf->timestamp.tv_sec * NSEC_PER_SEC + + (u32)buf->timestamp.tv_usec * NSEC_PER_USEC; +} + +static inline void v4l2_buffer_set_timestamp(struct v4l2_buffer *buf, + u64 timestamp) +{ + struct timespec64 ts = ns_to_timespec64(timestamp); + + buf->timestamp.tv_sec = ts.tv_sec; + buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; +} + #endif /* V4L2_COMMON_H_ */ diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h index 83860de120e3..248bc09bfc99 100644 --- a/include/trace/events/v4l2.h +++ b/include/trace/events/v4l2.h @@ -130,7 +130,7 @@ DECLARE_EVENT_CLASS(v4l2_event_class, __entry->bytesused = buf->bytesused; __entry->flags = buf->flags; __entry->field = buf->field; - __entry->timestamp = timeval_to_ns(&buf->timestamp); + __entry->timestamp = v4l2_buffer_get_timestamp(buf); __entry->timecode_type = buf->timecode.type; __entry->timecode_flags = buf->timecode.flags; __entry->timecode_frames = buf->timecode.frames; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 04481c717fee..6ef4a5b787a4 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1017,6 +1017,7 @@ struct v4l2_buffer { }; }; +#ifndef __KERNEL__ /** * v4l2_timeval_to_ns - Convert timeval to nanoseconds * @ts: pointer to the timeval variable to be converted @@ -1028,6 +1029,7 @@ static inline __u64 v4l2_timeval_to_ns(const struct timeval *tv) { return (__u64)tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000; } +#endif /* Flags for 'flags' field */ /* Buffer is mapped (flag) */ From patchwork Tue Nov 26 16:18:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60405 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYH-006AzZ-Em; Tue, 26 Nov 2019 16:18:57 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728795AbfKZQS6 (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:58 -0500 Received: from mout.kundenserver.de ([212.227.17.13]:36079 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728482AbfKZQSl (ORCPT ); Tue, 26 Nov 2019 11:18:41 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MXpM2-1iJ6CU1iea-00Y739; Tue, 26 Nov 2019 17:18:34 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann , stable@vger.kernel.org Subject: [PATCH v5 3/8] media: v4l2-core: compat: ignore native command codes Date: Tue, 26 Nov 2019 17:18:19 +0100 Message-Id: <20191126161824.337724-4-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:8TVU09gCY/FDOx2lpPLRMrqStt5USuA8OZ/VNhJVsJd7Gp2m6VG /CCIxU67Re6TN6SAYn+YT/I9ENEI+kNFH8azFfNX8g3VlCFAaio0bk4ceLXZotffLjceA8o +0UAIkt8AM4ad6h0wa+aWlWuF3T3z2Oze0/WR8mnh3McT2/BvwRVuAwru8AgKlqh2OEYs5/ UiH7sZBj+mycLuCRblppQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:3g7yQIiD7f0=:w9zH2Q7cCkdJYLv/T7HEIv Coqr90Cou4tLIM8r88ERA15pv2UlJpp8o4tVGTc3r8ttTGUHTd3Xi2/DHi0c4Uq3rDMjIjacF ULP/r3VTJMYTCNXF94MniIvaQpcTTUvarr2ktYhxqsgFYmhDUzh9YSAgm1UR4p6Ep9ms6jdFU 9TrWcAdGYR2LuCflaLeXr5sRuz6K4p6cqqbKBSL+7ywcZjgpDWeazCE4hGEn7G25OLcbFEBy0 5eoJJPXPzK9NKgM9otoAf0tAqE1XWdM7iDR7nJ3nP1pCIRsoo0+RVshyoLYrjPyYBiAyJfR1H WzKT/pYjVGaZBL/Vfe3JDLicZEjbUE+IL4vQsdwrXpw1yms3YB360P1jO4BMKHt0A/mckKW4t 9RWhvjRxpUYZxKXaOwe993II2bW17ITAQl8RNeDv2oHsXpSULHbhLN4SolADAnrEuGM5UdVxA Dkej/SrNWJJoC0B09dOD3GnbI7FJ09ipow2SwaYtFCgkbEvjR17kxl0XCt4YQQEufZ2iSdDOZ YayhC+g3Mr6X/lYT/k1K39Xdi3RDvoxmzTnj7GJAiV3HOAuSD3mStvgEUoyYSrgRYA6sTBAqp XadhDDLQudcCCrLS5kwyZ7XW2z6qG0D3dwD3Aw3mUX6vxHuJ5S0hsI1iFE4XxskVB0+1gZ16f oxosnRe53BOH0xUHF4SNB3ghjK/23OKWdd6xhjsQIk/feDHcY4xLqxLSam8XNtzrclXZlAskX 3gUbrT2nLAS79D4IWJq36RBzHVauAsg/JuAIMfQjE0UroVCobGWPy3JXeZXpdStSIDOZgCTnc 1m0OvClYAo4quobSsLstKuO9GAkX5/DoAEtDnnC03du8d1gYUXllSYfVTGqaGUHDYijNpRd9t MCqtTKXbThlg0+PpuXyQ== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The do_video_ioctl() compat handler converts the compat command codes into the native ones before processing further, but this causes problems for 32-bit user applications that pass a command code that matches a 64-bit native number, which will then be handled the same way. Specifically, this breaks VIDIOC_DQEVENT_TIME from user space applications with 64-bit time_t, as the structure layout is the same as the native 64-bit layout on many architectures (x86 being the notable exception). Change the handler to use the converted command code only for passing into the native ioctl handler, not for deciding on the conversion, in order to make the compat behavior match the native behavior. Actual support for the 64-bit time_t version of VIDIOC_DQEVENT_TIME and other commands still needs to be added in a separate patch. Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 148 +++++++++--------- 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index e1eaf1135c7f..7ad6db8dd9f6 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -1183,36 +1183,38 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar u32 aux_space; int compatible_arg = 1; long err = 0; + unsigned int ncmd; /* * 1. When struct size is different, converts the command. */ switch (cmd) { - case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; - case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; - case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; - case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; - case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; - case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; - case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; - case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; - case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; - case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; - case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; - case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; - case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; - case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; - case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; - case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; - case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; - case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; - case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; - case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break; - case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; - case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break; - case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break; - case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break; - case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break; + case VIDIOC_G_FMT32: ncmd = VIDIOC_G_FMT; break; + case VIDIOC_S_FMT32: ncmd = VIDIOC_S_FMT; break; + case VIDIOC_QUERYBUF32: ncmd = VIDIOC_QUERYBUF; break; + case VIDIOC_G_FBUF32: ncmd = VIDIOC_G_FBUF; break; + case VIDIOC_S_FBUF32: ncmd = VIDIOC_S_FBUF; break; + case VIDIOC_QBUF32: ncmd = VIDIOC_QBUF; break; + case VIDIOC_DQBUF32: ncmd = VIDIOC_DQBUF; break; + case VIDIOC_ENUMSTD32: ncmd = VIDIOC_ENUMSTD; break; + case VIDIOC_ENUMINPUT32: ncmd = VIDIOC_ENUMINPUT; break; + case VIDIOC_TRY_FMT32: ncmd = VIDIOC_TRY_FMT; break; + case VIDIOC_G_EXT_CTRLS32: ncmd = VIDIOC_G_EXT_CTRLS; break; + case VIDIOC_S_EXT_CTRLS32: ncmd = VIDIOC_S_EXT_CTRLS; break; + case VIDIOC_TRY_EXT_CTRLS32: ncmd = VIDIOC_TRY_EXT_CTRLS; break; + case VIDIOC_DQEVENT32: ncmd = VIDIOC_DQEVENT; break; + case VIDIOC_OVERLAY32: ncmd = VIDIOC_OVERLAY; break; + case VIDIOC_STREAMON32: ncmd = VIDIOC_STREAMON; break; + case VIDIOC_STREAMOFF32: ncmd = VIDIOC_STREAMOFF; break; + case VIDIOC_G_INPUT32: ncmd = VIDIOC_G_INPUT; break; + case VIDIOC_S_INPUT32: ncmd = VIDIOC_S_INPUT; break; + case VIDIOC_G_OUTPUT32: ncmd = VIDIOC_G_OUTPUT; break; + case VIDIOC_S_OUTPUT32: ncmd = VIDIOC_S_OUTPUT; break; + case VIDIOC_CREATE_BUFS32: ncmd = VIDIOC_CREATE_BUFS; break; + case VIDIOC_PREPARE_BUF32: ncmd = VIDIOC_PREPARE_BUF; break; + case VIDIOC_G_EDID32: ncmd = VIDIOC_G_EDID; break; + case VIDIOC_S_EDID32: ncmd = VIDIOC_S_EDID; break; + default: ncmd = cmd; break; } /* @@ -1221,11 +1223,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar * argument into it. */ switch (cmd) { - case VIDIOC_OVERLAY: - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - case VIDIOC_S_INPUT: - case VIDIOC_S_OUTPUT: + case VIDIOC_OVERLAY32: + case VIDIOC_STREAMON32: + case VIDIOC_STREAMOFF32: + case VIDIOC_S_INPUT32: + case VIDIOC_S_OUTPUT32: err = alloc_userspace(sizeof(unsigned int), 0, &new_p64); if (!err && assign_in_user((unsigned int __user *)new_p64, (compat_uint_t __user *)p32)) @@ -1233,23 +1235,23 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_G_INPUT: - case VIDIOC_G_OUTPUT: + case VIDIOC_G_INPUT32: + case VIDIOC_G_OUTPUT32: err = alloc_userspace(sizeof(unsigned int), 0, &new_p64); compatible_arg = 0; break; - case VIDIOC_G_EDID: - case VIDIOC_S_EDID: + case VIDIOC_G_EDID32: + case VIDIOC_S_EDID32: err = alloc_userspace(sizeof(struct v4l2_edid), 0, &new_p64); if (!err) err = get_v4l2_edid32(new_p64, p32); compatible_arg = 0; break; - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_TRY_FMT: + case VIDIOC_G_FMT32: + case VIDIOC_S_FMT32: + case VIDIOC_TRY_FMT32: err = bufsize_v4l2_format(p32, &aux_space); if (!err) err = alloc_userspace(sizeof(struct v4l2_format), @@ -1262,7 +1264,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_CREATE_BUFS: + case VIDIOC_CREATE_BUFS32: err = bufsize_v4l2_create(p32, &aux_space); if (!err) err = alloc_userspace(sizeof(struct v4l2_create_buffers), @@ -1275,10 +1277,10 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_PREPARE_BUF: - case VIDIOC_QUERYBUF: - case VIDIOC_QBUF: - case VIDIOC_DQBUF: + case VIDIOC_PREPARE_BUF32: + case VIDIOC_QUERYBUF32: + case VIDIOC_QBUF32: + case VIDIOC_DQBUF32: err = bufsize_v4l2_buffer(p32, &aux_space); if (!err) err = alloc_userspace(sizeof(struct v4l2_buffer), @@ -1291,7 +1293,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_S_FBUF: + case VIDIOC_S_FBUF32: err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, &new_p64); if (!err) @@ -1299,13 +1301,13 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_G_FBUF: + case VIDIOC_G_FBUF32: err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, &new_p64); compatible_arg = 0; break; - case VIDIOC_ENUMSTD: + case VIDIOC_ENUMSTD32: err = alloc_userspace(sizeof(struct v4l2_standard), 0, &new_p64); if (!err) @@ -1313,16 +1315,16 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; - case VIDIOC_ENUMINPUT: + case VIDIOC_ENUMINPUT32: err = alloc_userspace(sizeof(struct v4l2_input), 0, &new_p64); if (!err) err = get_v4l2_input32(new_p64, p32); compatible_arg = 0; break; - case VIDIOC_G_EXT_CTRLS: - case VIDIOC_S_EXT_CTRLS: - case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_G_EXT_CTRLS32: + case VIDIOC_S_EXT_CTRLS32: + case VIDIOC_TRY_EXT_CTRLS32: err = bufsize_v4l2_ext_controls(p32, &aux_space); if (!err) err = alloc_userspace(sizeof(struct v4l2_ext_controls), @@ -1334,7 +1336,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar } compatible_arg = 0; break; - case VIDIOC_DQEVENT: + case VIDIOC_DQEVENT32: err = alloc_userspace(sizeof(struct v4l2_event), 0, &new_p64); compatible_arg = 0; break; @@ -1352,9 +1354,9 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar * Otherwise, it will pass the newly allocated @new_p64 argument. */ if (compatible_arg) - err = native_ioctl(file, cmd, (unsigned long)p32); + err = native_ioctl(file, ncmd, (unsigned long)p32); else - err = native_ioctl(file, cmd, (unsigned long)new_p64); + err = native_ioctl(file, ncmd, (unsigned long)new_p64); if (err == -ENOTTY) return err; @@ -1370,13 +1372,13 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar * the blocks to maximum allowed value. */ switch (cmd) { - case VIDIOC_G_EXT_CTRLS: - case VIDIOC_S_EXT_CTRLS: - case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_G_EXT_CTRLS32: + case VIDIOC_S_EXT_CTRLS32: + case VIDIOC_TRY_EXT_CTRLS32: if (put_v4l2_ext_controls32(file, new_p64, p32)) err = -EFAULT; break; - case VIDIOC_S_EDID: + case VIDIOC_S_EDID32: if (put_v4l2_edid32(new_p64, p32)) err = -EFAULT; break; @@ -1389,49 +1391,49 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar * the original 32 bits structure. */ switch (cmd) { - case VIDIOC_S_INPUT: - case VIDIOC_S_OUTPUT: - case VIDIOC_G_INPUT: - case VIDIOC_G_OUTPUT: + case VIDIOC_S_INPUT32: + case VIDIOC_S_OUTPUT32: + case VIDIOC_G_INPUT32: + case VIDIOC_G_OUTPUT32: if (assign_in_user((compat_uint_t __user *)p32, ((unsigned int __user *)new_p64))) err = -EFAULT; break; - case VIDIOC_G_FBUF: + case VIDIOC_G_FBUF32: err = put_v4l2_framebuffer32(new_p64, p32); break; - case VIDIOC_DQEVENT: + case VIDIOC_DQEVENT32: err = put_v4l2_event32(new_p64, p32); break; - case VIDIOC_G_EDID: + case VIDIOC_G_EDID32: err = put_v4l2_edid32(new_p64, p32); break; - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_TRY_FMT: + case VIDIOC_G_FMT32: + case VIDIOC_S_FMT32: + case VIDIOC_TRY_FMT32: err = put_v4l2_format32(new_p64, p32); break; - case VIDIOC_CREATE_BUFS: + case VIDIOC_CREATE_BUFS32: err = put_v4l2_create32(new_p64, p32); break; - case VIDIOC_PREPARE_BUF: - case VIDIOC_QUERYBUF: - case VIDIOC_QBUF: - case VIDIOC_DQBUF: + case VIDIOC_PREPARE_BUF32: + case VIDIOC_QUERYBUF32: + case VIDIOC_QBUF32: + case VIDIOC_DQBUF32: err = put_v4l2_buffer32(new_p64, p32); break; - case VIDIOC_ENUMSTD: + case VIDIOC_ENUMSTD32: err = put_v4l2_standard32(new_p64, p32); break; - case VIDIOC_ENUMINPUT: + case VIDIOC_ENUMINPUT32: err = put_v4l2_input32(new_p64, p32); break; } From patchwork Tue Nov 26 16:18:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60404 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYF-006AzZ-CX; Tue, 26 Nov 2019 16:18:55 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728744AbfKZQSn (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:43 -0500 Received: from mout.kundenserver.de ([217.72.192.74]:39427 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728250AbfKZQSk (ORCPT ); Tue, 26 Nov 2019 11:18:40 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MaIKJ-1iL14x2lz3-00WBEs; Tue, 26 Nov 2019 17:18:34 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 4/8] media: v4l2-core: split out data copy from video_usercopy Date: Tue, 26 Nov 2019 17:18:20 +0100 Message-Id: <20191126161824.337724-5-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:r++WgAlr/NGAG5oOEEOa/W39DoBoyYcLns/mRUgxxpoktk06+ym 5xeohg1HW7rYPasW+z9VUJajRk+OLnFxeuCVTax2GwEsOcY4rGelk560Ro/n/jyS+lkXDPq Ilx8QVYx72Tz5qAK/RizIX+8hLDvqfNIZho0SByxH2KR02Wd7eeVxVOK9ZGMKK+gU/0GGhy GZkKeyy9I+NH8FS/hJe6w== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:wWBfceJaoWk=:WQemL2H/yF3X7qE+DDrrJj bCsQ//nqLfGQ6m/CYqhbqGF1XoM4xYMEteIjS/v4dfhx4V2I9Y5+C20EsKMr7qxMTKqauKO+/ O9SDc3AVJKKS0FlPrLptoObqW69ooCl6VCglGBHE3ZttrUJuN+TAf7buuwN/XJgr5Icvz3ekT s6EmEC6Y340iWOipAPTrlJgozryk0xpKDLF9k+wWaIbMP7YkNKq3oQ/t7ILft/aihtv98M3QP lRJZqq6ZLi3HgscdShxdvuBZxkGXOhsQWAghoJFlVvDNRYJevKQx4a75Cp/C3AN1O/zOleQVQ HgNuSxAMZY24BdFiGrvXBTIes7W8ZZLeDX65emvtm1B+5Pdj82g0RYYrNsJ5H/jeKNVOA5bBV xkVeazjhgBWzfHU78esr8+5OUEPyJt/Rh1tT5CR54AUpG9M3W9u92PLFcYl5dlLF3mCll9KXO OoFjfwfBKg4RWYM3qLe5RsMyt7akBVpETHcxE3Mj8b7f8IggrqaYfUgcWcQo7Q09EMtqIf0XL 7KTXeFcne9Vi2kah7VolsPnWWPHOs+ED+cIw/uFSyd944qn8qQ07RkavH9gsiFm25NNWG6hxC HnITohetp+AJuQ/2GCBLDfLH4ntTMbd2UBYK1dsd89gY7hSrzo0Ds9squxv4BLd80V8wROl4/ dc6NzuQdIbGKM8W9rarKd7Gx27zQpYNu+Zed5TWzcMobIzcs0GSwrBGXdTiJbYknv7gHefK7h rD9vncTnmPVucLn+Fwcv1L62Qvoqk6sBR+TuW/g+xoyrNTgFb9lc7r5Q3D1zOi8S7nspZJWXM U+HbZyIDAUdDU3IX1c7uwgtoE3ltsT9frlT254gsZE5rIHNUiIB7UuDdz9zZwByl2CbQ/0b3D +uaDnWrP756v6gNDPNAg== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The copy-in/out portions of video_usercopy() are about to get more complex, so turn then into separate functions as a cleanup first. Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-ioctl.c | 107 +++++++++++++++++---------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 4e700583659b..2ce91f88369b 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -3023,8 +3023,69 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, return ret; } +static unsigned int video_translate_cmd(unsigned int cmd) +{ + return cmd; +} + +static int video_get_user(void __user *arg, void *parg, unsigned int cmd, + bool *always_copy) +{ + unsigned int n = _IOC_SIZE(cmd); + + if (!(_IOC_DIR(cmd) & _IOC_WRITE)) { + /* read-only ioctl */ + memset(parg, 0, n); + return 0; + } + + switch (cmd) { + default: + /* + * In some cases, only a few fields are used as input, + * i.e. when the app sets "index" and then the driver + * fills in the rest of the structure for the thing + * with that index. We only need to copy up the first + * non-input field. + */ + if (v4l2_is_known_ioctl(cmd)) { + u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; + + if (flags & INFO_FL_CLEAR_MASK) + n = (flags & INFO_FL_CLEAR_MASK) >> 16; + *always_copy = flags & INFO_FL_ALWAYS_COPY; + } + + if (copy_from_user(parg, (void __user *)arg, n)) + return -EFAULT; + + /* zero out anything we don't copy from userspace */ + if (n < _IOC_SIZE(cmd)) + memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); + break; + } + + return 0; +} + +static int video_put_user(void __user *arg, void *parg, unsigned int cmd) +{ + if (!(_IOC_DIR(cmd) & _IOC_READ)) + return 0; + + switch (cmd) { + default: + /* Copy results into user buffer */ + if (copy_to_user(arg, parg, _IOC_SIZE(cmd))) + return -EFAULT; + break; + } + + return 0; +} + long -video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, +video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg, v4l2_kioctl func) { char sbuf[128]; @@ -3036,6 +3097,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, size_t array_size = 0; void __user *user_ptr = NULL; void **kernel_ptr = NULL; + unsigned int cmd = video_translate_cmd(orig_cmd); const size_t ioc_size = _IOC_SIZE(cmd); /* Copy arguments into temp kernel buffer */ @@ -3050,37 +3112,12 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, parg = mbuf; } - err = -EFAULT; - if (_IOC_DIR(cmd) & _IOC_WRITE) { - unsigned int n = ioc_size; - - /* - * In some cases, only a few fields are used as input, - * i.e. when the app sets "index" and then the driver - * fills in the rest of the structure for the thing - * with that index. We only need to copy up the first - * non-input field. - */ - if (v4l2_is_known_ioctl(cmd)) { - u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; - - if (flags & INFO_FL_CLEAR_MASK) - n = (flags & INFO_FL_CLEAR_MASK) >> 16; - always_copy = flags & INFO_FL_ALWAYS_COPY; - } - - if (copy_from_user(parg, (void __user *)arg, n)) - goto out; - - /* zero out anything we don't copy from userspace */ - if (n < ioc_size) - memset((u8 *)parg + n, 0, ioc_size - n); - } else { - /* read-only ioctl */ - memset(parg, 0, ioc_size); - } } + err = video_get_user((void __user *)arg, parg, orig_cmd, &always_copy); + if (err) + goto out; + err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr); if (err < 0) goto out; @@ -3131,15 +3168,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, goto out; out_array_args: - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, ioc_size)) - err = -EFAULT; - break; - } - + err = video_put_user((void __user *)arg, parg, orig_cmd); out: kvfree(mbuf); return err; From patchwork Tue Nov 26 16:18:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60408 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYW-006B0s-Pp; Tue, 26 Nov 2019 16:19:13 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728789AbfKZQS6 (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:58 -0500 Received: from mout.kundenserver.de ([212.227.17.10]:49401 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728736AbfKZQSm (ORCPT ); Tue, 26 Nov 2019 11:18:42 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MkpvV-1i6P0X3prb-00mMHc; Tue, 26 Nov 2019 17:18:34 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 5/8] media: v4l2-core: fix VIDIOC_DQEVENT for time64 ABI Date: Tue, 26 Nov 2019 17:18:21 +0100 Message-Id: <20191126161824.337724-6-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:wkgRxtQA2JMregiwL6hSMY9oukvaH+tLG6uRYJ+QQU6deycwLFW OJkb9MDnuw3lm4y4OMQT0gltJ26h4xHU2/atWaqRkpUhq3Shp0Piwov4qNrsCIKWAa2G9AS JGEf2pt0n2hjrG5nTBWrwSX5k8ZLXV9MTWeDig2zzwiKG1IFrICbX5o/feNIBJhz179YuLg LER7vA16ObgXZRxwC++LA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:ZmXBWwy9Psg=:6JoRMFo9SGexQszH7tkr7p UMBj2wK63k6e50z0+PSmRtDl7s4naauXpJdMV8vef7iNzB5wy5VkFdp82yBF8baaUkXsmXL2Y L/lkuXGRFzjBvgNpKKXGaOX+vYYGN1P/maw8dnaTaamwpXyyMLeAjYMliioX3Z1lLEwVR43zg oJp5nzzZqyAB13hl25/lePGZDGRTKaSVgv7UVtk4xkOA5UWyj6T88X8z6GCvgjFbJEUDd9lHI ESgzkUT8tvc2FeIvzyPZGBAkSLDHeKibMsd7R1vSGm60Ch2uib6HCgj40EZdO90JBZoxMyWgi cPlEdjfxqCoff9vAqHJW2NSIhKH3tUbSjc9wgb0NAFw7dU3UqtyUviQXhwUgpaKdSo1ORbq6Q L5/4qavSweE8K31bOc2OWNzwQBdZoGquqhhspHoRGd4f976JAuzPpb3bOHXOezZNbXte/uN0c PnuVNMGOIXxaUhx1eits6evu8hesTDBP0YZVh6GGVGP58QviiXQSGrsNSOnn3bYF//hpybxoo tFcDM5oAchj22Slm9wpBeTrtnyVElj2SYVNKpFCETQU7V19h7ZAy/C5+vkOG0sdbT7ITQpQpP k+nqJMOAdyrwITTh9Zs1oOneDi31Rt3DHmOBd74tOmfUgQ7kuf2FU/WxxnUCbFsEyWtdmSOwz PdJsublY7CkeV3uCtJCMG9sTSRPHf/ui2Ko6nbZmcPNfyW0TS/gpu8RrYtbyVyrjeyNALEfwH E0+wnAehXqqoxrdeIHg+bzFNzZ+lz/03tE/X09M16kx8yTQqrhLS4IEsKGW6n873wegFAM0Zi Z6Df1DRGhoeD5xMPtMO7ag02DKFLnZSters6GDn9WUDve1qFBgPARj9AEFFHaHdHOwkS6NTCz Iv4teznMneinnT6P9QbQ== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The v4l2_event structure contains a 'struct timespec' member that is defined by the user space C library, creating an ABI incompatibility when that gets updated to a 64-bit time_t. While passing a 32-bit time_t here would be sufficient for CLOCK_MONOTONIC timestamps, simply redefining the structure to use the kernel's __kernel_old_timespec would not work for any library that uses a copy of the linux/videodev2.h header file rather than including the copy from the latest kernel headers. This means the kernel has to be changed to handle both versions of the structure layout on a 32-bit architecture. The easiest way to do this is during the copy from/to user space. Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-event.c | 5 ++++- drivers/media/v4l2-core/v4l2-ioctl.c | 29 ++++++++++++++++++++++++++- drivers/media/v4l2-core/v4l2-subdev.c | 26 +++++++++++++++++++++++- include/media/v4l2-ioctl.h | 25 +++++++++++++++++++++++ include/uapi/linux/videodev2.h | 4 ++++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index 9d673d113d7a..290c6b213179 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -27,6 +27,7 @@ static unsigned sev_pos(const struct v4l2_subscribed_event *sev, unsigned idx) static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) { struct v4l2_kevent *kev; + struct timespec64 ts; unsigned long flags; spin_lock_irqsave(&fh->vdev->fh_lock, flags); @@ -44,7 +45,9 @@ static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) kev->event.pending = fh->navailable; *event = kev->event; - event->timestamp = ns_to_timespec(kev->ts); + ts = ns_to_timespec64(kev->ts); + event->timestamp.tv_sec = ts.tv_sec; + event->timestamp.tv_nsec = ts.tv_nsec; kev->sev->first = sev_pos(kev->sev, 1); kev->sev->in_use--; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 2ce91f88369b..96aafb659783 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -821,7 +821,7 @@ static void v4l_print_event(const void *arg, bool write_only) const struct v4l2_event *p = arg; const struct v4l2_event_ctrl *c; - pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%lu.%9.9lu\n", + pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%llu.%9.9llu\n", p->type, p->pending, p->sequence, p->id, p->timestamp.tv_sec, p->timestamp.tv_nsec); switch (p->type) { @@ -3025,6 +3025,13 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, static unsigned int video_translate_cmd(unsigned int cmd) { + switch (cmd) { +#ifdef CONFIG_COMPAT_32BIT_TIME + case VIDIOC_DQEVENT_TIME32: + return VIDIOC_DQEVENT; +#endif + } + return cmd; } @@ -3074,6 +3081,26 @@ static int video_put_user(void __user *arg, void *parg, unsigned int cmd) return 0; switch (cmd) { +#ifdef CONFIG_COMPAT_32BIT_TIME + case VIDIOC_DQEVENT_TIME32: { + struct v4l2_event *ev = parg; + struct v4l2_event_time32 ev32 = { + .type = ev->type, + .pending = ev->pending, + .sequence = ev->sequence, + .timestamp.tv_sec = ev->timestamp.tv_sec, + .timestamp.tv_nsec = ev->timestamp.tv_nsec, + .id = ev->id, + }; + + memcpy(&ev32.u, &ev->u, sizeof(ev->u)); + memcpy(&ev32.reserved, &ev->reserved, sizeof(ev->reserved)); + + if (copy_to_user(arg, &ev32, sizeof(ev32))) + return -EFAULT; + break; + } +#endif default: /* Copy results into user buffer */ if (copy_to_user(arg, parg, _IOC_SIZE(cmd))) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 9e987c0f840e..de926e311348 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -331,8 +331,8 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_fh *vfh = file->private_data; #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); - int rval; #endif + int rval; switch (cmd) { case VIDIOC_QUERYCTRL: @@ -392,6 +392,30 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); + case VIDIOC_DQEVENT_TIME32: { + struct v4l2_event_time32 *ev32 = arg; + struct v4l2_event ev; + + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) + return -ENOIOCTLCMD; + + rval = v4l2_event_dequeue(vfh, &ev, file->f_flags & O_NONBLOCK); + + *ev32 = (struct v4l2_event_time32) { + .type = ev.type, + .pending = ev.pending, + .sequence = ev.sequence, + .timestamp.tv_sec = ev.timestamp.tv_sec, + .timestamp.tv_nsec = ev.timestamp.tv_nsec, + .id = ev.id, + }; + + memcpy(&ev32->u, &ev.u, sizeof(ev.u)); + memcpy(&ev32->reserved, &ev.reserved, sizeof(ev.reserved)); + + return rval; + } + case VIDIOC_SUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 4bba65a59d46..05c1ec93a911 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -724,4 +724,29 @@ long int video_usercopy(struct file *file, unsigned int cmd, long int video_ioctl2(struct file *file, unsigned int cmd, unsigned long int arg); +/* + * The user space interpretation of the 'v4l2_event' differs + * based on the 'time_t' definition on 32-bit architectures, so + * the kernel has to handle both. + * This is the old version for 32-bit architectures. + */ +struct v4l2_event_time32 { + __u32 type; + union { + struct v4l2_event_vsync vsync; + struct v4l2_event_ctrl ctrl; + struct v4l2_event_frame_sync frame_sync; + struct v4l2_event_src_change src_change; + struct v4l2_event_motion_det motion_det; + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct old_timespec32 timestamp; + __u32 id; + __u32 reserved[8]; +}; + +#define VIDIOC_DQEVENT_TIME32 _IOR('V', 89, struct v4l2_event_time32) + #endif /* _V4L2_IOCTL_H */ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 6ef4a5b787a4..caf156d45842 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2341,7 +2341,11 @@ struct v4l2_event { } u; __u32 pending; __u32 sequence; +#ifdef __KERNEL__ + struct __kernel_timespec timestamp; +#else struct timespec timestamp; +#endif __u32 id; __u32 reserved[8]; }; From patchwork Tue Nov 26 16:18:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60407 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdYV-006B0g-8C; Tue, 26 Nov 2019 16:19:11 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728799AbfKZQS7 (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:59 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:42103 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728740AbfKZQSm (ORCPT ); Tue, 26 Nov 2019 11:18:42 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1N3sNa-1hrk8h0iXo-00zkhP; Tue, 26 Nov 2019 17:18:35 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 6/8] media: v4l2-core: fix v4l2_buffer handling for time64 ABI Date: Tue, 26 Nov 2019 17:18:22 +0100 Message-Id: <20191126161824.337724-7-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:MpJL5kq5Qh38TN+TsyjI3Z9+stjWek1mdImDxxdOkH2BzJv0ttG 8hXy4piwfh/1vPwu+yQY7GWmJlARXmO5DcpZH2I2ROW6QITtkUAgjyjwVnT3HndHrhRJoKM oGHKTQHs1u4sefpkkEnbjqiVrRXasBcJ7Vy9czGcYRNdHFdAOFAclvQfZMhJNxhxL771Jc3 nmeNl/q1+UKvt4/5gEUMQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:SSPchkp55RM=:CsLc8nmSzW3sXLHk8pL4yX ENNj6dJZx5/U0PjWlxrNjl/wjk4UFzP06dM0a9cqsO4N50megIk83AnhPv9w37Vc8E2LRr527 MmHmhINHGU+p/ztef4MJ9FinEeiI+727lHcni0CRN1zsaw/G6eeeAdndeODOvxHHBjBuAo6wq DfeSjJAk7RbRRhlaGRlW3GJLwCFSYSNwfJ68BzuHmNCF/U9dlm/LBzU5KbBxH6CY4BrB/Sk0U NWjBU1rNAxnIz9lCXpi5EHrJ7TeBce2U2Z0uY3eII6ecJbncfCc739OxvSeDZw8zaYlpQBcDY iKTL9F5AswkS8THKnrQ2FBnuZmVW1RQeHdXqz/hOCU7phD0L2u2rGK7JVMQKLS+NBXcCogB/T pvRWXbyPbp4ecHEKtgAr3g/aYTg4YQ/e/Uos9PFpyyKLHdHqzZG2qwQjgAR3t1SN8J2Mo3T4V UUQpQuIl7EcOGOlpz51dAhjaiYP7ad2+K16UVdSTpTnDNVUKY49nBLSbZ9qNOZhu2Rj18sNif ynopbU72Y2TyOocyMs3ltJBdRbvMdybWyk7jEGZn4hjJdaMi0no1uqkVM+TieR8wx99Sdku+W sknBL11AU/KV++7DOId7OBbp0yFwcLUS+BuMHVXWt4BLEeWlv/UQ1fgkBGAp2lVJAAZ7jh711 M1M3TlW6YHLC/Vmtx92fJD/uyiEULlQzYYl2VkLpQvCW36X4hXiq7+SOd+T/20zatTBMyMZjV 7cKuhYZ/40cuUd5Gj19dwqTX40uTfeBS/Px6LnYTOqcy3BFg9XL2Y7OuJhnyPk0bjn1Ah5xVa O8jeOIY5cKzgk54ehhgcMNL4C8C56ViJlMnWIFXV9aXrtiG2oIq/dJ+Qw8mVyvnRNvEEXc/BM ZEE5PSE+0ijk9aL24a9A== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The v4l2_buffer structure contains a 'struct timeval' member that is defined by the user space C library, creating an ABI incompatibility when that gets updated to a 64-bit time_t. As in v4l2_event, handle this with a special case in video_put_user() and video_get_user() to replace the memcpy there. Since the structure also contains a pointer, there are now two native versions (on 32-bit systems) as well as two compat versions (on 64-bit systems), which unfortunately complicates the compat handler quite a bit. Duplicating the existing handlers for the new types is a safe conversion for now, but unfortunately this may turn into a maintenance burden later. A larger-scale rework of the compat code might be a better alternative, but is out of scope of the y2038 work. Sparc64 needs a special case because of their special suseconds_t definition. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-ioctl.c | 73 ++++++++++++++++++++++++++-- include/media/v4l2-ioctl.h | 30 ++++++++++++ include/uapi/linux/videodev2.h | 23 +++++++++ 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 96aafb659783..4d611a847462 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -474,10 +474,10 @@ static void v4l_print_buffer(const void *arg, bool write_only) const struct v4l2_plane *plane; int i; - pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request_fd=%d, flags=0x%08x, field=%s, sequence=%d, memory=%s", - p->timestamp.tv_sec / 3600, - (int)(p->timestamp.tv_sec / 60) % 60, - (int)(p->timestamp.tv_sec % 60), + pr_cont("%02d:%02d:%02d.%09ld index=%d, type=%s, request_fd=%d, flags=0x%08x, field=%s, sequence=%d, memory=%s", + (int)p->timestamp.tv_sec / 3600, + ((int)p->timestamp.tv_sec / 60) % 60, + ((int)p->timestamp.tv_sec % 60), (long)p->timestamp.tv_usec, p->index, prt_names(p->type, v4l2_type_names), p->request_fd, @@ -3029,6 +3029,14 @@ static unsigned int video_translate_cmd(unsigned int cmd) #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_DQEVENT_TIME32: return VIDIOC_DQEVENT; + case VIDIOC_QUERYBUF_TIME32: + return VIDIOC_QUERYBUF; + case VIDIOC_QBUF_TIME32: + return VIDIOC_QBUF; + case VIDIOC_DQBUF_TIME32: + return VIDIOC_DQBUF; + case VIDIOC_PREPARE_BUF_TIME32: + return VIDIOC_PREPARE_BUF; #endif } @@ -3047,6 +3055,39 @@ static int video_get_user(void __user *arg, void *parg, unsigned int cmd, } switch (cmd) { +#ifdef COMPAT_32BIT_TIME + case VIDIOC_QUERYBUF_TIME32: + case VIDIOC_QBUF_TIME32: + case VIDIOC_DQBUF_TIME32: + case VIDIOC_PREPARE_BUF_TIME32: { + struct v4l2_buffer_time32 vb32; + struct v4l2_buffer *vb = parg; + + if (copy_from_user(&vb32, arg, sizeof(vb32))) + return -EFAULT; + + *vb = (struct v4l2_buffer) { + .index = vb32.index, + .type = vb32.type, + .bytesused = vb32.bytesused, + .flags = vb32.flags, + .field = vb32.field, + .timestamp.tv_sec = vb32.timestamp.tv_sec, + .timestamp.tv_usec = vb32.timestamp.tv_usec, + .timecode = vb32.timecode, + .memory = vb32.memory, + .m.userptr = vb32.m.usercopy, + .length = vb32.length, + .request_fd = vb32.request_fd, + }; + + if (cmd == VIDIOC_QUERYBUF_TIME32) + memset(&vb->length, 0, sizeof(*vb) - + offsetof(struct v4l2_buffer, length)); + + break; + } +#endif default: /* * In some cases, only a few fields are used as input, @@ -3100,6 +3141,30 @@ static int video_put_user(void __user *arg, void *parg, unsigned int cmd) return -EFAULT; break; } + case VIDIOC_QUERYBUF_TIME32: + case VIDIOC_QBUF_TIME32: + case VIDIOC_DQBUF_TIME32: + case VIDIOC_PREPARE_BUF_TIME32: { + struct v4l2_buffer *vb = parg; + struct v4l2_buffer_time32 vb32 = { + .index = vb->index, + .type = vb->type, + .bytesused = vb->bytesused, + .flags = vb->flags, + .field = vb->field, + .timestamp.tv_sec = vb->timestamp.tv_sec, + .timestamp.tv_usec = vb->timestamp.tv_usec, + .timecode = vb->timecode, + .memory = vb->memory, + .m.userptr = vb->m.userptr, + .length = vb->length, + .request_fd = vb->request_fd, + }; + + if (copy_to_user(arg, &vb32, sizeof(vb32))) + return -EFAULT; + break; + } #endif default: /* Copy results into user buffer */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 05c1ec93a911..86878fba332b 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -749,4 +749,34 @@ struct v4l2_event_time32 { #define VIDIOC_DQEVENT_TIME32 _IOR('V', 89, struct v4l2_event_time32) +struct v4l2_buffer_time32 { + __u32 index; + __u32 type; + __u32 bytesused; + __u32 flags; + __u32 field; + struct old_timeval32 timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + __u32 memory; + union { + __u32 offset; + unsigned long userptr; + struct v4l2_plane *planes; + __s32 fd; + } m; + __u32 length; + __u32 reserved2; + union { + __s32 request_fd; + __u32 reserved; + }; +}; +#define VIDIOC_QUERYBUF_TIME32 _IOWR('V', 9, struct v4l2_buffer_time32) +#define VIDIOC_QBUF_TIME32 _IOWR('V', 15, struct v4l2_buffer_time32) +#define VIDIOC_DQBUF_TIME32 _IOWR('V', 17, struct v4l2_buffer_time32) +#define VIDIOC_PREPARE_BUF_TIME32 _IOWR('V', 93, struct v4l2_buffer_time32) + #endif /* _V4L2_IOCTL_H */ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index caf156d45842..5f9357dcb060 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -912,6 +912,25 @@ struct v4l2_jpegcompression { /* * M E M O R Y - M A P P I N G B U F F E R S */ + +#ifdef __KERNEL__ +/* + * This corresponds to the user space version of timeval + * for 64-bit time_t. sparc64 is different from everyone + * else, using the microseconds in the wrong half of the + * second 64-bit word. + */ +struct __kernel_v4l2_timeval { + long long tv_sec; +#if defined(__sparc__) && defined(__arch64__) + int tv_usec; + int __pad; +#else + long long tv_usec; +#endif +}; +#endif + struct v4l2_requestbuffers { __u32 count; __u32 type; /* enum v4l2_buf_type */ @@ -997,7 +1016,11 @@ struct v4l2_buffer { __u32 bytesused; __u32 flags; __u32 field; +#ifdef __KERNEL__ + struct __kernel_v4l2_timeval timestamp; +#else struct timeval timestamp; +#endif struct v4l2_timecode timecode; __u32 sequence; From patchwork Tue Nov 26 16:18:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60401 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdY3-006Az2-AU; Tue, 26 Nov 2019 16:18:43 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728753AbfKZQSo (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:44 -0500 Received: from mout.kundenserver.de ([217.72.192.73]:41867 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728739AbfKZQSn (ORCPT ); Tue, 26 Nov 2019 11:18:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MVMNF-1iPzA41o6p-00SLUS; Tue, 26 Nov 2019 17:18:35 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 7/8] media: v4l2-core: fix compat VIDIOC_DQEVENT for time64 ABI Date: Tue, 26 Nov 2019 17:18:23 +0100 Message-Id: <20191126161824.337724-8-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:qkDInfKyka/nqbgHNepwaYQ0KDWIvFoJWlOVAt4iyAlq2n+FRmC 3goPaARuNQpQYprSzLsXcU78Bqo3gcxjS4Iq7goI8U5UI1tMUPjmdX1clWUVcXL753XbkSY csi3EZbLwzIvX3Ewnqkc5gqN2swEPngz/8xUlCafiGm1ELmS8OAmdNf+c5sgMWD15jhTgpe QkOdDft5VnhyLoTLb/a6Q== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:NYj2HxuPskE=:pM5Nhr0wV29QHPqIlb/6Qt ebRbzJcqUzPK+7sbk9wMJAIonh0Xyqx0fW6bWSLRGEAzyPlXZ7BY8hGLw7RiyIqpj2myltoof Y4sLxgnhmPGYD/q/y2O3mwji/922PegvbPJ6aUfREV3ZOy0ztFYVElf04C5QfgybUgm8ih0+I 3TkgegXuPVw2w5L1mtxN2MkouRsCb1WJffLqigzQvlW4GMWc+9Bj4ha3jy9/beh8xqZj//Lk/ bmlURffFuuSU7f9Hw0xExtQu4UNPhi3/uLWhvsd5pbWr0M/4snMQkI6V+do7iBz53Z5R0GyCD RCQM5AZc0F7yR6OTxkYznYaXSfl+ClpN8JU2zqPVqStjBDMAr5JIFRXFk+o5DAtRYIsN7GuWX +msswJSw0I8w7VmdDsSGS8KLbHkiWufvLfRXN50vIYC9t0EkJ9v7o3CNUx3Cd3QCocfEtq2d7 9/Hbus6WgqhMCtc9le5ggdLjX8su1YMgKKU1nNaapD9DckmZJqzKuJqdielk9dW/vDGlWcm9q IPVthK+1LYE1O5kJMt03zFah8Wyo/Hi9dGyr89nXnj/6famNt8PU25hP5npj8zd+ME9rL7tEB gsyZFlmk8aNXMZvcQLM5p53ZoRvl7bmg5Ziwd5v/F09czDy23s/O0efhVYzdLb5x7/NlO/EJa 059VlnJPm5trCRIjSTddBH/EfzjlRMJya1elBvbAZAGyKcejyQxkDudj5QE4vF2mU2Q2NlEzZ nDPuob0bQdlPjCRXXcaK/AL5HTQ992z0d+4dKpjmM4TpniSkgknnCt40IlsM749UfgNwVoN8T WnEq6Ya8oR7QXXkfnCRuPGqg/CepQegXlwoa802TPXQUKB+bVytLpE4zuWaXUoaaXEYSgfGyt RiznNV+cbpyMYSXQsAkw== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The native code supports the variant of struct v4l2_event for 64-bit time_t, so add the compat version as well. Here, a new incompatibility arises: while almost all 32-bit architectures now use the same layout as 64-bit architectures and the commands can simply be passed through, on x86 the internal alignment of v4l2_event is different because of the 64-bit member in v4l2_event_ctrl. To handle all architectures, this now requires defining four different versions of the structure to cover all possible combinations. The compat handling for VIDIOC_DQEVENT32 and VIDIOC_DQEVENT32_TIME32 is now inside of an #ifdef so it does not get used on architectures other than x86. Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 7ad6db8dd9f6..46cd84879c1f 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -1028,6 +1028,15 @@ static int put_v4l2_ext_controls32(struct file *file, return 0; } +#ifdef CONFIG_X86_64 +/* + * x86 is the only compat architecture with different struct alignment + * between 32-bit and 64-bit tasks. + * + * On all other architectures, v4l2_event32 and v4l2_event32_time32 are + * the same as v4l2_event and v4l2_event_time32, so we can use the native + * handlers, converting v4l2_event to v4l2_event_time32 if necessary. + */ struct v4l2_event32 { __u32 type; union { @@ -1036,7 +1045,20 @@ struct v4l2_event32 { } u; __u32 pending; __u32 sequence; - struct compat_timespec timestamp; + struct __kernel_timespec timestamp; + __u32 id; + __u32 reserved[8]; +}; + +struct v4l2_event32_time32 { + __u32 type; + union { + compat_s64 value64; + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct old_timespec32 timestamp; __u32 id; __u32 reserved[8]; }; @@ -1057,6 +1079,23 @@ static int put_v4l2_event32(struct v4l2_event __user *p64, return 0; } +static int put_v4l2_event32_time32(struct v4l2_event_time32 __user *p64, + struct v4l2_event32_time32 __user *p32) +{ + if (!access_ok(p32, sizeof(*p32)) || + assign_in_user(&p32->type, &p64->type) || + copy_in_user(&p32->u, &p64->u, sizeof(p64->u)) || + assign_in_user(&p32->pending, &p64->pending) || + assign_in_user(&p32->sequence, &p64->sequence) || + assign_in_user(&p32->timestamp.tv_sec, &p64->timestamp.tv_sec) || + assign_in_user(&p32->timestamp.tv_nsec, &p64->timestamp.tv_nsec) || + assign_in_user(&p32->id, &p64->id) || + copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) + return -EFAULT; + return 0; +} +#endif + struct v4l2_edid32 { __u32 pad; __u32 start_block; @@ -1121,6 +1160,7 @@ static int put_v4l2_edid32(struct v4l2_edid __user *p64, #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) +#define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) @@ -1202,7 +1242,10 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_G_EXT_CTRLS32: ncmd = VIDIOC_G_EXT_CTRLS; break; case VIDIOC_S_EXT_CTRLS32: ncmd = VIDIOC_S_EXT_CTRLS; break; case VIDIOC_TRY_EXT_CTRLS32: ncmd = VIDIOC_TRY_EXT_CTRLS; break; +#ifdef CONFIG_X86_64 case VIDIOC_DQEVENT32: ncmd = VIDIOC_DQEVENT; break; + case VIDIOC_DQEVENT32_TIME32: ncmd = VIDIOC_DQEVENT_TIME32; break; +#endif case VIDIOC_OVERLAY32: ncmd = VIDIOC_OVERLAY; break; case VIDIOC_STREAMON32: ncmd = VIDIOC_STREAMON; break; case VIDIOC_STREAMOFF32: ncmd = VIDIOC_STREAMOFF; break; @@ -1336,10 +1379,16 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar } compatible_arg = 0; break; +#ifdef CONFIG_X86_64 case VIDIOC_DQEVENT32: err = alloc_userspace(sizeof(struct v4l2_event), 0, &new_p64); compatible_arg = 0; break; + case VIDIOC_DQEVENT32_TIME32: + err = alloc_userspace(sizeof(struct v4l2_event_time32), 0, &new_p64); + compatible_arg = 0; + break; +#endif } if (err) return err; @@ -1404,10 +1453,16 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar err = put_v4l2_framebuffer32(new_p64, p32); break; +#ifdef CONFIG_X86_64 case VIDIOC_DQEVENT32: err = put_v4l2_event32(new_p64, p32); break; + case VIDIOC_DQEVENT32_TIME32: + err = put_v4l2_event32_time32(new_p64, p32); + break; +#endif + case VIDIOC_G_EDID32: err = put_v4l2_edid32(new_p64, p32); break; From patchwork Tue Nov 26 16:18:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 60402 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([209.132.180.67]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1iZdY9-006AzL-At; Tue, 26 Nov 2019 16:18:49 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728767AbfKZQSr (ORCPT + 1 other); Tue, 26 Nov 2019 11:18:47 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:58733 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728735AbfKZQSo (ORCPT ); Tue, 26 Nov 2019 11:18:44 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue106 [212.227.15.145]) with ESMTPA (Nemesis) id 1MVMNF-1iPzA42qVb-00SLUS; Tue, 26 Nov 2019 17:18:35 +0100 From: Arnd Bergmann To: linux-media@vger.kernel.org, Hans Verkuil , Mauro Carvalho Chehab Cc: y2038@lists.linaro.org, linux-kernel@vger.kernel.org, Arnd Bergmann Subject: [PATCH v5 8/8] media: v4l2-core: fix compat v4l2_buffer handling for time64 ABI Date: Tue, 26 Nov 2019 17:18:24 +0100 Message-Id: <20191126161824.337724-9-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191126161824.337724-1-arnd@arndb.de> References: <20191126161824.337724-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:ofc3LBlLnAXmLOHye02+cN3SmFYYxNpVcm8agn8K5QILs6B6KuH 6aKUQNQNCjHk7MVC6+IUlMb73FzMCSBs2thRamSob5WCBBUlFqkFRhRsPpiPe7Z5jF1WpRP jSiUpCsa1KquhEgCmZU7aIDxMLjuVhY2z1CuBEBliLK5iKZEbvhuPuPqm7hclW/Sh4y9TTo IcHGiGzbaVEumQUM0chSw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:+J3m8TRCMvk=:yH0W4wNS2PNXNprBQR1WrB 3nKAEzPTRNm67b7V91GpH9u24/2gndde8ISXPcY85XLWZVKUIbkMwJRrLIzXAuwSuAyiQCDxX 6eXB9hq/obCfrxCkZLSmei6yM5jRuP6NIu6AECCB9ODwlWV+pw5CQoDMN7DgiyyT+0gMYmzB1 1RUM+RsTnRJMlVM3ATAQN1PB7O0/ySvKyD4Rshyjx/b7IGr2500nsRGGeEBx206ccV1UUSZxU dic5dZ6CjIlzJCMVnZzHFibcGLUWcSFy+ML4rXLtPdEHARSwRWjxQZ2VHMGn3/34yQmV/T/75 0NVkSZh1t9Pi0Ix2SALlJUcBVmiVbie/NSmKrrioRcXirTp3LhBf+FpSxgx3jj/qBpTqq7ywA vqlOlWo6laMU6HbcPH+x6PuPkLKPPlChDy9d7Hikx49PcD9iSA1kfTYY7sRsPOHcFUtlj+45X MsS6gP+ucv7gFA0xEyinQBiAWGJWGK+6BQb6FyVCatO4iDKxBwDf++A8kF/7U3jWp/vs21TKw bvyaR02TMKs40KNP2nzzQ1l9LWYZOtBD3S37YvF/qOL/0OMNm7pWXKu+oz5f002Q3aQTB3pRT OEldUClEjSC7d5vaY6yWqXAY/yNHjAZYHMGbKTF3n+d9Q/lS+Lsqwpnqgd64IS2UmntIoWFGu QQZ7rNizajhTIFoh8g7bEE+Fx5xzTSbfB282FI6a2jDVBZcItDdlvRUxT+UkqDz7SSOvqG/RG J6Evf/NTjrZg0pKh0PZqAlPPcIfpYL1g++tqoHOEADmAabKtZIou4cXVb3cbUpYWr+DP2BHI0 ed8zYo4VK/aKH0NFfCuFCpGfEoD1jJfK8VgUIDgaBGYgOmoGVrMIYuHm8HGVOL2j8BHLujylr VM9SptToxYVybVzAxPbA== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support for the four new variants of ioctl commands for 64-bit time_t in v4l2_buffer. The existing v4l2_buffer32 structure for the traditional format gets changed to match the new v4l2_buffer format, and the old layout is now called v4l2_buffer32_time32. Neither of these matches the native 64-bit architecture format of v4l2_buffer, so both require special handling in compat code. Duplicating the existing handlers for the new types is a safe conversion for now, but unfortunately this may turn into a maintenance burden later. A larger-scale rework of the compat code might be a better alternative, but is out of scope of the y2038 work. Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 265 +++++++++++++++++- 1 file changed, 264 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 46cd84879c1f..3bbf47d950e0 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -474,7 +474,33 @@ struct v4l2_buffer32 { __u32 bytesused; __u32 flags; __u32 field; /* enum v4l2_field */ - struct compat_timeval timestamp; + struct { + long long tv_sec; + long long tv_usec; + } timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + __u32 memory; /* enum v4l2_memory */ + union { + __u32 offset; + compat_long_t userptr; + compat_caddr_t planes; + __s32 fd; + } m; + __u32 length; + __u32 reserved2; + __s32 request_fd; +}; + +struct v4l2_buffer32_time32 { + __u32 index; + __u32 type; /* enum v4l2_buf_type */ + __u32 bytesused; + __u32 flags; + __u32 field; /* enum v4l2_field */ + struct old_timeval32 timestamp; struct v4l2_timecode timecode; __u32 sequence; @@ -581,6 +607,31 @@ static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *p32, u32 *size) return 0; } +static int bufsize_v4l2_buffer_time32(struct v4l2_buffer32_time32 __user *p32, u32 *size) +{ + u32 type; + u32 length; + + if (!access_ok(p32, sizeof(*p32)) || + get_user(type, &p32->type) || + get_user(length, &p32->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + if (length > VIDEO_MAX_PLANES) + return -EINVAL; + + /* + * We don't really care if userspace decides to kill itself + * by passing a very big length value + */ + *size = length * sizeof(struct v4l2_plane); + } else { + *size = 0; + } + return 0; +} + static int get_v4l2_buffer32(struct v4l2_buffer __user *p64, struct v4l2_buffer32 __user *p32, void __user *aux_buf, u32 aux_space) @@ -681,6 +732,106 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *p64, return 0; } +static int get_v4l2_buffer32_time32(struct v4l2_buffer_time32 __user *p64, + struct v4l2_buffer32_time32 __user *p32, + void __user *aux_buf, u32 aux_space) +{ + u32 type; + u32 length; + s32 request_fd; + enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane __user *uplane; + compat_caddr_t p; + int ret; + + if (!access_ok(p32, sizeof(*p32)) || + assign_in_user(&p64->index, &p32->index) || + get_user(type, &p32->type) || + put_user(type, &p64->type) || + assign_in_user(&p64->flags, &p32->flags) || + get_user(memory, &p32->memory) || + put_user(memory, &p64->memory) || + get_user(length, &p32->length) || + put_user(length, &p64->length) || + get_user(request_fd, &p32->request_fd) || + put_user(request_fd, &p64->request_fd)) + return -EFAULT; + + if (V4L2_TYPE_IS_OUTPUT(type)) + if (assign_in_user(&p64->bytesused, &p32->bytesused) || + assign_in_user(&p64->field, &p32->field) || + assign_in_user(&p64->timestamp.tv_sec, + &p32->timestamp.tv_sec) || + assign_in_user(&p64->timestamp.tv_usec, + &p32->timestamp.tv_usec)) + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + u32 num_planes = length; + + if (num_planes == 0) { + /* + * num_planes == 0 is legal, e.g. when userspace doesn't + * need planes array on DQBUF + */ + return put_user(NULL, &p64->m.planes); + } + if (num_planes > VIDEO_MAX_PLANES) + return -EINVAL; + + if (get_user(p, &p32->m.planes)) + return -EFAULT; + + uplane32 = compat_ptr(p); + if (!access_ok(uplane32, + num_planes * sizeof(*uplane32))) + return -EFAULT; + + /* + * We don't really care if userspace decides to kill itself + * by passing a very big num_planes value + */ + if (aux_space < num_planes * sizeof(*uplane)) + return -EFAULT; + + uplane = aux_buf; + if (put_user_force(uplane, &p64->m.planes)) + return -EFAULT; + + while (num_planes--) { + ret = get_v4l2_plane32(uplane, uplane32, memory); + if (ret) + return ret; + uplane++; + uplane32++; + } + } else { + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: + if (assign_in_user(&p64->m.offset, &p32->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: { + compat_ulong_t userptr; + + if (get_user(userptr, &p32->m.userptr) || + put_user((unsigned long)compat_ptr(userptr), + &p64->m.userptr)) + return -EFAULT; + break; + } + case V4L2_MEMORY_DMABUF: + if (assign_in_user(&p64->m.fd, &p32->m.fd)) + return -EFAULT; + break; + } + } + + return 0; +} + static int put_v4l2_buffer32(struct v4l2_buffer __user *p64, struct v4l2_buffer32 __user *p32) { @@ -761,6 +912,87 @@ static int put_v4l2_buffer32(struct v4l2_buffer __user *p64, return 0; } + +static int put_v4l2_buffer32_time32(struct v4l2_buffer_time32 __user *p64, + struct v4l2_buffer32_time32 __user *p32) +{ + u32 type; + u32 length; + enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane *uplane; + compat_caddr_t p; + int ret; + + if (!access_ok(p32, sizeof(*p32)) || + assign_in_user(&p32->index, &p64->index) || + get_user(type, &p64->type) || + put_user(type, &p32->type) || + assign_in_user(&p32->flags, &p64->flags) || + get_user(memory, &p64->memory) || + put_user(memory, &p32->memory)) + return -EFAULT; + + if (assign_in_user(&p32->bytesused, &p64->bytesused) || + assign_in_user(&p32->field, &p64->field) || + assign_in_user(&p32->timestamp.tv_sec, &p64->timestamp.tv_sec) || + assign_in_user(&p32->timestamp.tv_usec, &p64->timestamp.tv_usec) || + copy_in_user(&p32->timecode, &p64->timecode, sizeof(p64->timecode)) || + assign_in_user(&p32->sequence, &p64->sequence) || + assign_in_user(&p32->reserved2, &p64->reserved2) || + assign_in_user(&p32->request_fd, &p64->request_fd) || + get_user(length, &p64->length) || + put_user(length, &p32->length)) + return -EFAULT; + + if (V4L2_TYPE_IS_MULTIPLANAR(type)) { + u32 num_planes = length; + + if (num_planes == 0) + return 0; + /* We need to define uplane without __user, even though + * it does point to data in userspace here. The reason is + * that v4l2-ioctl.c copies it from userspace to kernelspace, + * so its definition in videodev2.h doesn't have a + * __user markup. Defining uplane with __user causes + * smatch warnings, so instead declare it without __user + * and cast it as a userspace pointer to put_v4l2_plane32(). + */ + if (get_user(uplane, &p64->m.planes)) + return -EFAULT; + if (get_user(p, &p32->m.planes)) + return -EFAULT; + uplane32 = compat_ptr(p); + + while (num_planes--) { + ret = put_v4l2_plane32((void __user *)uplane, + uplane32, memory); + if (ret) + return ret; + ++uplane; + ++uplane32; + } + } else { + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: + if (assign_in_user(&p32->m.offset, &p64->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: + if (assign_in_user(&p32->m.userptr, &p64->m.userptr)) + return -EFAULT; + break; + case V4L2_MEMORY_DMABUF: + if (assign_in_user(&p32->m.fd, &p64->m.fd)) + return -EFAULT; + break; + } + } + + return 0; +} + struct v4l2_framebuffer32 { __u32 capability; __u32 flags; @@ -1147,10 +1379,13 @@ static int put_v4l2_edid32(struct v4l2_edid __user *p64, #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) +#define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) +#define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) +#define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) @@ -1163,6 +1398,7 @@ static int put_v4l2_edid32(struct v4l2_edid __user *p64, #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) +#define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) @@ -1232,10 +1468,13 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_G_FMT32: ncmd = VIDIOC_G_FMT; break; case VIDIOC_S_FMT32: ncmd = VIDIOC_S_FMT; break; case VIDIOC_QUERYBUF32: ncmd = VIDIOC_QUERYBUF; break; + case VIDIOC_QUERYBUF32_TIME32: ncmd = VIDIOC_QUERYBUF_TIME32; break; case VIDIOC_G_FBUF32: ncmd = VIDIOC_G_FBUF; break; case VIDIOC_S_FBUF32: ncmd = VIDIOC_S_FBUF; break; case VIDIOC_QBUF32: ncmd = VIDIOC_QBUF; break; + case VIDIOC_QBUF32_TIME32: ncmd = VIDIOC_QBUF_TIME32; break; case VIDIOC_DQBUF32: ncmd = VIDIOC_DQBUF; break; + case VIDIOC_DQBUF32_TIME32: ncmd = VIDIOC_DQBUF_TIME32; break; case VIDIOC_ENUMSTD32: ncmd = VIDIOC_ENUMSTD; break; case VIDIOC_ENUMINPUT32: ncmd = VIDIOC_ENUMINPUT; break; case VIDIOC_TRY_FMT32: ncmd = VIDIOC_TRY_FMT; break; @@ -1255,6 +1494,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_S_OUTPUT32: ncmd = VIDIOC_S_OUTPUT; break; case VIDIOC_CREATE_BUFS32: ncmd = VIDIOC_CREATE_BUFS; break; case VIDIOC_PREPARE_BUF32: ncmd = VIDIOC_PREPARE_BUF; break; + case VIDIOC_PREPARE_BUF32_TIME32: ncmd = VIDIOC_PREPARE_BUF_TIME32; break; case VIDIOC_G_EDID32: ncmd = VIDIOC_G_EDID; break; case VIDIOC_S_EDID32: ncmd = VIDIOC_S_EDID; break; default: ncmd = cmd; break; @@ -1336,6 +1576,22 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; + case VIDIOC_PREPARE_BUF32_TIME32: + case VIDIOC_QUERYBUF32_TIME32: + case VIDIOC_QBUF32_TIME32: + case VIDIOC_DQBUF32_TIME32: + err = bufsize_v4l2_buffer_time32(p32, &aux_space); + if (!err) + err = alloc_userspace(sizeof(struct v4l2_buffer), + aux_space, &new_p64); + if (!err) { + aux_buf = new_p64 + sizeof(struct v4l2_buffer); + err = get_v4l2_buffer32_time32(new_p64, p32, + aux_buf, aux_space); + } + compatible_arg = 0; + break; + case VIDIOC_S_FBUF32: err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, &new_p64); @@ -1484,6 +1740,13 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar err = put_v4l2_buffer32(new_p64, p32); break; + case VIDIOC_PREPARE_BUF32_TIME32: + case VIDIOC_QUERYBUF32_TIME32: + case VIDIOC_QBUF32_TIME32: + case VIDIOC_DQBUF32_TIME32: + err = put_v4l2_buffer32_time32(new_p64, p32); + break; + case VIDIOC_ENUMSTD32: err = put_v4l2_standard32(new_p64, p32); break;