From patchwork Wed Nov 6 19:47:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231037 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1E0E316B1 for ; Wed, 6 Nov 2019 19:48:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 04831217F5 for ; Wed, 6 Nov 2019 19:48:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731769AbfKFTrm (ORCPT ); Wed, 6 Nov 2019 14:47:42 -0500 Received: from mout.kundenserver.de ([217.72.192.74]:52553 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728979AbfKFTrm (ORCPT ); Wed, 6 Nov 2019 14:47:42 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1Mgek6-1i16o70uBI-00h84C; Wed, 06 Nov 2019 20:47:27 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 1/8] media: documentation: fix video_event description Date: Wed, 6 Nov 2019 20:47:08 +0100 Message-Id: <20191106194715.2238044-2-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:USd+zjGhsVQ171cwgzKSCGkCnuWKIcZHhQMm4T+G6SZpZ8lVk4K xKfhnhjlrTcXJZZz+0hJDMaKeeXqiIVlx8vdGH9QvhsT3LypB7Qruq89EEDFJro5KzjOG5+ ayClBPWJi243PXXXZFuvRN9wsfO1n9koZ+57if+Terf9gd/MnXj5hs3w3K9vQlzUWJnVeAg 4TZfPpNcwzERd4mh4UsBQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:/rV5c7aC60k=:4snmqiZwLZVgaVDcBqJwUq rLcl4nD9asyN0+982ZlyNVGj0Pa1Bp3fR5rzKUBEdPkFgIjMlUUZWI3cRO0leoIZmboya7L9+ kOu9WCrXCG8Y6868sSQeyMZQ480CMj5jgE/j37mI1Vi2ReteUoDMVL25YQ8JI33klf0pCsjFK 3CJhfNc1JhrXLEH1sPFdJdd33DkujOv2ZgokGPqtPwKINrf49KGRgth1ItnH4/ZdKhk1d7E4C +oYcPCTDyKgy8+PU7n6iWeAlznSMj8H+GVatPMY3Cmyqmdtzk8nulI4ERTIehB+L9Gui0EBWk AaN97ZK0VczRMzj0PmYkxuLur5/CAZ6UFT/qaLCDPc8amNqeQ8oG0tGCEg9UI239aO+ZbmwCR ACShg2m7CWA7bYt1LeYF8XqJ01DORGwsprNfDk+PDOZvGPVaEGOy0Hg6eu68Ebpc04bi2TgWj O+OtLRWYpWcyN0pcU8s81wHnRZRDAJE8Nk/YXstD7s3FwZJM2OIqQLTvcGqCoR66ZmYc9vCX3 s3uiSXGm1FIv1eJ6HpVTaBYTE6PKPM5DPwH6GTP2aa5adO93+ijVoCosXqgEt4NCQigZHy7Rp K35jo8gvcds0ZXEdjDbRm/YLjK9Jdg8zSq5gZsSQS0sTcpzNqpaUb+OhErG5Yjx840H/OfLrF YQ6Mk+R2vDhTedIfAqvv08q4JdkqcPOFyQR629EsdHNDVomAq4m8NGbJWCBRf+heH6a0bNVHS tIPOWRughb9KwmHht7OfOLwid8kKaMjCWZGl38of+rZ1wahbs9ZVB6t2A2qqcVBkKX4qDBI7H sxZJLbMKCOOHBGQAr5+lvm3WFh6vp7o56OHKAGdzyLmU38S499tb4O1v0a6GJqPiqrCEt4LJB d+S5cOD4NacuSfNL1+1g== 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 Wed Nov 6 19:47:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231035 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4501516B1 for ; Wed, 6 Nov 2019 19:48:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 18381217F5 for ; Wed, 6 Nov 2019 19:48:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732027AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from mout.kundenserver.de ([217.72.192.75]:60907 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726713AbfKFTrm (ORCPT ); Wed, 6 Nov 2019 14:47:42 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1N336J-1hneOg2SMv-013LtV; Wed, 06 Nov 2019 20:47:27 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 2/8] media: v4l2: abstract timeval handling in v4l2_buffer Date: Wed, 6 Nov 2019 20:47:09 +0100 Message-Id: <20191106194715.2238044-3-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:CI8NmnbaqFJd0bRVPgyIf+IWFn+d4q6tqgGn007CR9gLhlzYLCI HjkxtvO+wNjOT762I+3FNz9mJuZpnZPlmL0GeYugkeXm0ozlFYguwvoAehNoufTv9GnDBfo ZJr36HV1NSX2hxgHX+ZzDQneBUgEpwXG1uzJG4jquVIb+UeMAE2QANk3HWKHOvpt/t8STLa e657Wk7tBBVigZs6fG2Hg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:B9AhFum4mTw=:65r+YIdwLBY8wqzhOXwzkD ghBiimdrddcy/OUz4s0nQXuUTJrLNeHfMp7QupImrnKerfQNVvI7LJAB7sEVqpQ2UlNcb+9Q/ KsQyEiByTejjmuL2MdYrV+WsIWQHKmmpNAl934q1VqBBsNwQ6e1bBr7JcLAYjU6YAJikZdYPD 2lsC1Qa5/jk22fYxtn352YetBA4ORLhB6TguA7AXfYwolb7HoEEjYHbuxp2fGcVDs/uVAAw+J Xt17NxRsg/bRV/LixGkIIPFhEHwx7PrTGNOusyo/IBhAev0p5jCC7NJtGGMKnepSSC5Sq/58S SQBJTvxrkrVuGiN8iZZI6vSuapElXH80WxWymzh2NS3PNHhsAUhouzXTjU7WtbB62ndUHsqjc gnXu3EKyyes6MxkvLjvOLuu/MzptEQmMjfDlQYYdEouX0KoJECBseSxEpnCKwRZ+kOqiO7TfK 4ObfNQnvBqcvA/RKGhKCpw+nuM6FxLkK9phXt16mAkKe7HRXChAzHJAZsniGHcTOlJWNHS9iz ovPVWR2QUl8aLO8XZYekFavcIpPhQ74BDKCzI9dV6LCiwLj2+1ENH7iGV9f3TCzVCmXnWP2Ur CswI8J7UqwhvsAIF63/vTyOfTmwz6ESs38bNNfwBfZG4NjLFvKtU+kXKJyTNvkFJyTNl5pfhV hndZN3YpYdHET5ywtDmTDKGtR4/ktoBToTuYOicG1VFvCRlV1P9Xd0VAQ/MBdDMljJvCvor7O mDAvlHfjTCZlbAcMwXX3CsrTMMuBgh/wdEBO6kCXzF1MuPs4WdSCA+FWgaOLQ9oUHnnv8LIie CKn/2hOVdexbRFmZn+99PhXsItAl96Rc+gtdL12PJ6jV7DCuretfwXAfgKrHAWtYy9EUDXSO2 kHVtY8lix1NhyZnjdmzA== 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 may be userspace code relying on it because it is part of the uapi header. Signed-off-by: Arnd Bergmann --- drivers/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 | 4 ++-- include/linux/videodev2.h | 17 ++++++++++++++++- include/trace/events/v4l2.h | 2 +- include/uapi/linux/videodev2.h | 2 ++ 9 files changed, 30 insertions(+), 13 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..ab650371c151 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -364,7 +364,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 +578,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/linux/videodev2.h b/include/linux/videodev2.h index 16c0ed6c50a7..481ee3013b50 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -56,7 +56,22 @@ #ifndef __LINUX_VIDEODEV2_H #define __LINUX_VIDEODEV2_H -#include /* need struct timeval */ +#include #include +static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) +{ + return buf->timestamp.tv_sec * NSEC_PER_SEC + + 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 /* __LINUX_VIDEODEV2_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 f98bbcced8ff..5de1e37995c0 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 Wed Nov 6 19:47:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231025 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FCFC16B1 for ; Wed, 6 Nov 2019 19:47:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6CFDD21848 for ; Wed, 6 Nov 2019 19:47:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732147AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from mout.kundenserver.de ([217.72.192.75]:33597 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727720AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1MRTEp-1iG9aU48ov-00NOI1; Wed, 06 Nov 2019 20:47:28 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann , stable@vger.kernel.org Subject: [PATCH v3 3/8] media: v4l2-core: ignore native command codes Date: Wed, 6 Nov 2019 20:47:10 +0100 Message-Id: <20191106194715.2238044-4-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:Wjz4+hIcGWg831trgGTz9lydjzlKkTmAxk7jsyabPcLGvW64b+y laQcE/SJ0DWMYAst/2Kp8p7Wd2YwQr1j00fcGPDBySe/8D6MkTVktfoP5Fpp39k0FjXXGJd 1smQJxmvx89Ax7I+zCty1Bx9g7fNmWOB7PbwoV9l+DiGgeF9LzoqEQ1wljxYMmaPoQ1FA2t f5A/q9wf+lsPIhD8m9c9Q== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:plw5zs7+EXg=:NvC+gbDnMiFh56yYUbNsjD h3hIB0FrgTPjOOb6VqdNpVbU7R10OcEYePX6AInUklAw/dTXZAYrsukz7yBFekPzCLfIP//Ty v2EbaSCqorTOKXpqAaBQz/OzRCIT3bHJpCqa2ETwiXAPi3BQtGShdSxfHgT0pJuM8c3I0d2R1 PH03PgDpLy919Rjm/TL4PpFC6/P8NBDe45mFEqKMGRHw0TUuLW/4hnJDkLFlGJS9FiVTBkRqm MIsm/B0I0jVSGW5cD62NyKchStv3o7sOsOC5KWkkX2By5yhVUELEtKzqZg+8ndyw57Z3nd4HO e7D1mVbbbFijfQOQC+Ap9PYlq2gunMAHoZ2TjivfBYOyrZ0dYFMm8JOwrpyF7phdTxQkUz2mg QcYJ4AAWfYM9jXkyvgqrLGLMKGBJsjGQU6SQt3dmwGgtq33A2m+9N/hAaZpMdjvmgirqzTYr7 0IbmMBOQkGLy08eFuqobWtCyfSrAxeUq2mJgYX1W5u9WPpAB4ex2L26IsNYuKakHF/MMpcMZb mFtu1SHZOsbCDY4Dkl+v2Iv6VoqnxzP1td/92c0Xh7ZNCQfB/UoGemLj+YTTzGrWiLaCB9Pax WhwRHJjz0eB9UU1DhOlRbvhyiIaLwiOThg/ZzBgaQkppy17PqXWa8ppUMZ/mrM+UkWN8ikwf8 vC6t5PUBRhgmma2CMqCQcHrK2zabLrdYaTjvP2co4hnmrdeol0nCj6WEtHE8gIdyJXrejg2d/ mJ+hRjX1nne+ivlXO3qduk1NJ/i+tCbCiVwi+6YfGwZzUQrq5pwypzj1W1kHmhhN44FlSyP82 aj74o1XL4UvqZ+zdL/Rby01pkDU3VsU2LMFfa+yXAUPiJhK6cEGMF+1InZFJOE5d9vfEBAmws sh248LnAA4o2PICJtx0w== 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 Wed Nov 6 19:47:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231023 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB91C16B1 for ; Wed, 6 Nov 2019 19:47:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C23B5217F5 for ; Wed, 6 Nov 2019 19:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732277AbfKFTro (ORCPT ); Wed, 6 Nov 2019 14:47:44 -0500 Received: from mout.kundenserver.de ([217.72.192.73]:52407 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732094AbfKFTro (ORCPT ); Wed, 6 Nov 2019 14:47:44 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1N6KMR-1hqxmj1WdF-016fo9; Wed, 06 Nov 2019 20:47:28 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 4/8] media: v4l2-core: split out data copy from video_usercopy Date: Wed, 6 Nov 2019 20:47:11 +0100 Message-Id: <20191106194715.2238044-5-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:MgGhQlMf0sQoX4BwSigDgTPdaQVjvrw+JuXQJm8is4+E1D0ai/K 530O9xJB2RZpYJ2lmJ5LXDAr6OFFhRx/hW44o/bTprnxfxKi616Z6UoZqBcquaecc/XxrPg MeYeI6B7usdOtgEB0lOnPct/7tK+f1Cd8l5HjpxXl/z+qMIeOYFekuZpSkR4iN9hlhjB+EW BD0jjVlbOQt0jnb15+MQw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:gJ+jAHu+iP8=:brf46HfddiyxJLj/6/Rdr4 6SeZYDsG4RpDct51rF8Ffa0RLEWccrnvPCxK4zB/PHILcdXWo+/TzlD+jJsIFDRm2dLadzN0O gqmSOtrzpIT5/trnJViivjYrJT9/tMNYMC9IIpUtXxn4pm3NGEsJAIP4hF2wIeI3lviy0g/64 G7lrpMGuACRWZsKARZxEj9sYmo3WkyWjxhNoFnJs7YKwayUYzKl/+jGpZVocFmK8KnFqPrP9h JSNXbZbOk0X2cMQvkcyC9NG6bl3jiQHNRfx2xzJ9BGBdvVe8Bcwfr/HQIWXidcYd2nepTlMfm 6lVIbMnKR9nFzOeB6CP873lPAVkUdUdaXTwPwiots3Hgt5g8/Pjqv066J8Ohlm7AU17ypBsxN dMhLCXLu79YeBZQZZ3ZjRupIbKCd5D1rNE7h1BSHsVLGzWMEDPV5HIrK+8unDW67f7TNoikBF 6LzGW6z0JAPGXpKxC4SLgtMCzU2xRVInvQeSVgatpm6ZO05Ia122XNs5tfWp01JFXQMsbyeQS hdhsdTtupIzlmxlHsE8G3u14Z5KTab2yRQpXAxnX6Btq1NDPqt3+9f0W5dx6XMjVDzaHjpPjA yUkEL0xFumEJaQxiXj4XSqL230VgWskjbLSGdAfUBiccrizQgJbUvN7xk1Y5glbww9f2ljXGE 7b6PkrlJnOUHi9pVywGGFyBglpn3fFSGTpdFzJ/U6R7o5hV8TSQClARFtryW7YssFiPUnkkDE thfuMBeNPBr9q47lubCKegU2mw72FcDw7HqMhHcXalevKaGdBN4h4SyRkYiqEGC49bEa7tOit 927QSn6u8/RoRgCXSXiQo4h3RU6B0xnVZygYRbUD9TxReuELWTUmPYg7bXTopRtWpmi88yzal xCVYsDnlp/fFqZg/D8+A== 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 315ac12c3e0a..50612b4749d3 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 Wed Nov 6 19:47:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231033 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1AB72139A for ; Wed, 6 Nov 2019 19:48:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EAC6B217D7 for ; Wed, 6 Nov 2019 19:48:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728263AbfKFTsJ (ORCPT ); Wed, 6 Nov 2019 14:48:09 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:33363 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729036AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1MG9c2-1iivwy2y5c-00GcxA; Wed, 06 Nov 2019 20:47:28 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 5/8] media: v4l2-core: fix VIDIOC_DQEVENT for time64 ABI Date: Wed, 6 Nov 2019 20:47:12 +0100 Message-Id: <20191106194715.2238044-6-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:OtsoNIOiObwbn/wM1A3bLuSoKzPwIKJ6+XdchmxPBJonyoIKh5Y 0iR+6eS9zZrh90AnDzxvF3TR5G+jSovPczaGG8/H3YdbOyXPxEvqXm5fH1wZL+KnQ1X9rIU 8s2JdR5hOsieVChp2PbMMlFYXh4gKC80/85ss6vR7IBhbZk7u9tPikBc51yWB0yy/3xbuql 4WG77levMWbgO4PiYcPLg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:ddCe9lWZClk=:s/ArC9s92DlYvQ+Aw3NoM5 9XLptxP2Vgfob7+xuRM0Jtp6vYzKmAl0Kdx3kGBCIRCBaOQiGUoLzxCkhUuMpCtC5GvLSCfSm zEWJfuEoJYkchHpaHEqlUWVM5f7nxVQMAE0ABecSeEROyrAIqEBUlTd0OO9XLBPjIprOmi8Bz gKqLxyxw/99FlxcU4miTxVbXC4QF+EHHxOGuLgoRrRqFIzyioAQJo0Hny51TkLeuQmmE+/+77 xzmxfb+k4f4EnL2EQV7qrSGCyWrZuovg2DBt6SnLiBpZAW58zn6fxomnvIMDBnnPzp0LueQ/A pQrtdqq3pSBi72u/sZLzvZmuJJjdiJsAcCpecMs1IDaXWE3Q1rii83s3DjuhaEoRZH3uu82Ue E3T6SjWqlMJGBq9vbC2VcCHukeKpDQThaMiP5ybqiTjwrD2+BmtA6jYLwWy89K3iE7d/8gmmW 685dGjxhIabPCljFqupw/rkOgf0fMBq0UsTHrw8tuFAR21i6/gDu7Sty3hprNwdux5MzA6lNf aMoO/zUTXDrDtvpWWXD/HEm74S5n+B4icmPvm9Kv063eP7sIscS1FvznjwiIiBQO4e24AT3GP Kb1MlCVZ018Bj0Gnta9Kz8vpAEWXnoFniF/JsQMrnylrqcocibFi5FSSGiVxtAYKqq1TJXMgy wRFck6PyhHgYm4TrzWalcsTGy46EIY5YS71Hc+i+S3Hgh9UijbTn/lHAnGwm04uWTVwS+eedr 4Z06B1UD1n9rMh5nWOBwpwBl8OxsY05FTNiuoWoq9vaaL0i9bi+gu4Gu+Gh6oR5ykIqMy6VUm luYHdSOHIQaZtI0Z5Pg6GhQLdOgNelzdbhVpnA6chbkDeuWAXEtewsBNnB3WUYqHQXgp54nsy 76hqEnWOXgSg+SZpQlhg== 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 | 22 ++++++++++++++++++++ drivers/media/v4l2-core/v4l2-subdev.c | 20 +++++++++++++++++- include/uapi/linux/videodev2.h | 30 +++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 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 50612b4749d3..b8aca0d174bd 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -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,21 @@ 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_time32 ev32; + struct v4l2_event *ev = parg; + + memcpy(&ev32, ev, offsetof(struct v4l2_event, timestamp)); + ev32.timestamp.tv_sec = ev->timestamp.tv_sec; + ev32.timestamp.tv_nsec = ev->timestamp.tv_nsec; + memcpy(&ev32.id, &ev->id, sizeof(*ev) - offsetof(struct v4l2_event, id)); + + 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..77b77807aaca 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,24 @@ 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); + + memcpy(ev32, &ev, offsetof(struct v4l2_event, timestamp)); + ev32->timestamp.tv_sec = ev.timestamp.tv_sec; + ev32->timestamp.tv_nsec = ev.timestamp.tv_nsec; + memcpy(&ev32->id, &ev.id, + sizeof(ev) - offsetof(struct v4l2_event, id)); + + return rval; + } + case VIDIOC_SUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5de1e37995c0..e38afa71a327 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2340,11 +2340,40 @@ struct v4l2_event { } u; __u32 pending; __u32 sequence; +#ifdef __KERNEL__ + struct __kernel_timespec timestamp; +#else struct timespec timestamp; +#endif __u32 id; __u32 reserved[8]; }; +#ifdef __KERNEL__ +/* + * 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]; +}; +#endif + #define V4L2_EVENT_SUB_FL_SEND_INITIAL (1 << 0) #define V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK (1 << 1) @@ -2497,6 +2526,7 @@ struct v4l2_create_buffers { #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) #define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) #define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_DQEVENT_TIME32 _IOR('V', 89, struct v4l2_event_time32) #define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) #define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) From patchwork Wed Nov 6 19:47:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231029 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B12A5139A for ; Wed, 6 Nov 2019 19:48:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8E55F217F5 for ; Wed, 6 Nov 2019 19:48:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727411AbfKFTsD (ORCPT ); Wed, 6 Nov 2019 14:48:03 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:55489 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727785AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1MqrsF-1i6Hk80KxN-00mw1x; Wed, 06 Nov 2019 20:47:29 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 6/8] media: v4l2-core: fix v4l2_buffer handling for time64 ABI Date: Wed, 6 Nov 2019 20:47:13 +0100 Message-Id: <20191106194715.2238044-7-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:sc+E8Llli0i6zWDJ5b6ZUOrnyQIsdXdsefrm3zBU54roXTqyjPG XNSzpdPbZ+bpe78taJr05sGeWRpGJMTCW2n648gYdDimfCbf1fMa4gZn6Q3jciIPyVVy4nj w4o7vweZDVzR5cUnlLK4omjtt2fnuvghU78RfkHGK5SFzL0a1+KQ3YPRzs0zU004e8akSoC 7VO+ug1I1DtWcMm4/LZWQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:TIdFNfQgxDk=:MVGDAmLxNA+o/HHvVXGvJ6 toakWwOYnA9F1EypIlGtOVy7esPODSEDpbbz7YHgPYDK7w66DZJUz5Woz6V3VlM8hlXw5ow7/ 6VAZKVUysVACDNhRmBmM8NMT54SvQTLGH04zsdwkjlnVbNyoSHrLRdVFW04Zu+w13D9azSORe hDTnVzZbf4HdVkxYOV2ZFuV6lg6JXjsXOC4s13Mc73BAl3ClKF+7oIZZn5zcd41SmWUWPizhM mEHeO1H09zmogpThqfoFS+PlFdRQR3I4uQztONdX2OqIkcGEigbb0m0Uf1C9tT53+99FBsySX D2DS4hV47KZezuGHPS7cnYTQGFm5GZZ/4atck9JFgEsFSScJCMs1tlFrtdU8RyomHdh8glZwb 1mneqxH8mamucdW4IvYuxaHEy48/pd6bP0icsHQMhcpE8bi0dahpGVl4q+p+dcO51YsWFRqmq 87jcc1iaE6e/nsmxsiIfXobR1uSBBlHlkMSGE+6+4b/WzuGzVQ1lDaueCDQK6+lONhQuifNyx xw9lnSsC+0jCjxUBDI7gJPK8onm/T2oP/oPdsy96THIpYqHFwl3gPX/P/6T6qMMB7czai6MEz d8qbY7x9H5Om/lUb6+LHdwyndVeMUTsm4RH+3q3IGNNdPRHDO9AUZV3Kpsvzb/AFD2jLIjGar DRnQ1P/xiOh5UzDyhc65ujqvOuV/7M9UTcM15Dbmlncx4hDOiRMzCphZLpWV5DAR6FOnCxxoo hsftf2muhJq6p7B+2fylO+KCCOtao+V4RaSzPs2Mz6RoEXXghlXW/bfu17K4q/GO3RrJMB9Sh w4KREKOAwazxWcR+1ozjp1qLIVMjnop+1n7pOU2Ul0ywgVUpendkJW+Hf0l3hAQlHlR3Zzy2s G9LRmaVJgEdHH0fnFgwQ== 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. Signed-off-by: Arnd Bergmann --- drivers/media/v4l2-core/v4l2-ioctl.c | 57 ++++++++++++++++++++++++++-- include/uapi/linux/videodev2.h | 40 +++++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index b8aca0d174bd..cd9a80960289 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("%02ld:%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,30 @@ 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; + + memcpy(vb, &vb32, offsetof(struct v4l2_buffer, timestamp)); + vb->timestamp.tv_sec = vb32.timestamp.tv_sec; + vb->timestamp.tv_usec = vb32.timestamp.tv_usec; + memcpy(&vb->timecode, &vb32.timecode, + sizeof(*vb) - offsetof(struct v4l2_buffer, timecode)); + + 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, @@ -3095,6 +3127,23 @@ 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_time32 vb32; + struct v4l2_buffer *vb = parg; + + memcpy(&vb32, vb, offsetof(struct v4l2_buffer, timestamp)); + vb32.timestamp.tv_sec = vb->timestamp.tv_sec; + vb32.timestamp.tv_usec = vb->timestamp.tv_usec; + memcpy(&vb32.timecode, &vb->timecode, + sizeof(*vb) - offsetof(struct v4l2_buffer, timecode)); + + if (copy_to_user(arg, &vb32, sizeof(vb32))) + return -EFAULT; + break; + } #endif default: /* Copy results into user buffer */ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index e38afa71a327..4275d6e92dae 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -997,7 +997,42 @@ struct v4l2_buffer { __u32 bytesused; __u32 flags; __u32 field; +#ifdef __KERNEL__ + /* match glibc timeval64 format */ + struct { + long long tv_sec; + long long tv_usec; + } timestamp; +#else struct timeval timestamp; +#endif + 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; + }; +}; + +#ifdef __KERNEL__ +struct v4l2_buffer_time32 { + __u32 index; + __u32 type; + __u32 bytesused; + __u32 flags; + __u32 field; + struct old_timeval32 timestamp; struct v4l2_timecode timecode; __u32 sequence; @@ -1016,6 +1051,7 @@ struct v4l2_buffer { __u32 reserved; }; }; +#endif #ifndef __KERNEL__ /** @@ -2457,12 +2493,15 @@ struct v4l2_create_buffers { #define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format) #define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers) #define VIDIOC_QUERYBUF _IOWR('V', 9, struct v4l2_buffer) +#define VIDIOC_QUERYBUF_TIME32 _IOWR('V', 9, struct v4l2_buffer_time32) #define VIDIOC_G_FBUF _IOR('V', 10, struct v4l2_framebuffer) #define VIDIOC_S_FBUF _IOW('V', 11, struct v4l2_framebuffer) #define VIDIOC_OVERLAY _IOW('V', 14, int) #define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) +#define VIDIOC_QBUF_TIME32 _IOWR('V', 15, struct v4l2_buffer_time32) #define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer) #define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) +#define VIDIOC_DQBUF_TIME32 _IOWR('V', 17, struct v4l2_buffer_time32) #define VIDIOC_STREAMON _IOW('V', 18, int) #define VIDIOC_STREAMOFF _IOW('V', 19, int) #define VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm) @@ -2531,6 +2570,7 @@ struct v4l2_create_buffers { #define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) #define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) +#define VIDIOC_PREPARE_BUF_TIME32 _IOWR('V', 93, struct v4l2_buffer_time32) #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) #define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) #define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) From patchwork Wed Nov 6 19:47:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231031 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CBB66139A for ; Wed, 6 Nov 2019 19:48:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B2A8D217F9 for ; Wed, 6 Nov 2019 19:48:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732087AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from mout.kundenserver.de ([217.72.192.74]:49881 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728725AbfKFTrn (ORCPT ); Wed, 6 Nov 2019 14:47:43 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1MFbeC-1iiNih1jlm-00HBBW; Wed, 06 Nov 2019 20:47:29 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 7/8] media: v4l2-core: fix compat VIDIOC_DQEVENT for time64 ABI Date: Wed, 6 Nov 2019 20:47:14 +0100 Message-Id: <20191106194715.2238044-8-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:qf8MvFpIAOKyu9qPsIzcqWc1FIBAR+EwQnWxqMS7s4sjndSLP9M JhdkZJSu/v8JyrjcjCMLogIrES4kA5sLj5Yo8MRnzjGfvAM9cddJJKwPlICjBorpRV+ZmvA UDh0wdT00NIpt7hTey7e43qQA/ouupbH/tGVrY2f7c+Z1ZzyMSeUZYw/xta+3AhQEqPGeN4 OmzX+a0fMe+kChwLAmGkw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:qUzYAIJVjqk=:Nf2OyloFW8J5+zPjfLzyZj 61I3SyqXJtsMgH+6B48LF/5xpbpsQYgspADWjlO/kQ2KMKKRclw6HHfwHf3DRnPL7dbbI7kwO xR+80YAaLLkjUwhXg/VYj3li5Tq9p02BDka8j5npfcjr/Pyth6sSVtP/vBScDKnyXPOQUnRQE Kp0ZOAPzVJAq1Oy/S81PLszB2G8tFSNHcZ8sMK0YNlU3apIIzNbQrMxaIMv1PiwDRWZKzDWGr Cts2kckHbrirLFkMPrn9rzDMNvDIpvobMH7utL1A0+R3AaSpIMuI24PyvSeUlm/ZNXd5PsNzY 598WB5ZEM1Gb0+ua4kyfzEh5q6anud8rpGfaK1fomD81v0q552kxdexLdUOcL0ZA/o8Ni4nUz dRlLa56Ob2z1AoZSXAJkCdTisfv4/gc+fCExZYVejw2hqBcWQeZTw3Lt1pFyhihmswIE5f7Sc Zy42wtHD1HCrCGw2E55C0VaBNUhcT/dsX7h4nu3cmhn0Y/fkOi3kpdST99TSUYJvHfK5O2Dtx k4qkDkpZh28vIqXVT6OYlN2tJn+yMVFhT2nKUm6NT5T0xUsf4vp9Zozsill79kqHf8TfoeR5c 9TfQ3y7hKJJ309W4z/H9nQ916V6UVmmCvtrzitlI9lB9EzCcPxn1kHc0L2EFU3qdmbs5XzdDR Yv1aZ6+tYKBwDQ8C6sxCFThCa9qYSmEHu7rRCjjlXEFCh6snbJrRRzGq/QJVHlvnXQQOKklMQ mHWakzFHrh8rEfjQkQGjWJsgvMOLIuCVnC2ZeaB08FqyH4Thyn0B/F2l6HMze1WzbL8ZMyucj DeLAvJUgRitDvbNQiESqASD5BDwRR/lu/0TdsE+eaa3G85Dr/EuovzglkFafLS9oSgcOSCuuk IqKwmK3Hc74J5kMsqpmA== 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..aa4bc63dc261 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -1028,7 +1028,29 @@ 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 { + compat_s64 value64; + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct __kernel_timespec timestamp; + __u32 id; + __u32 reserved[8]; +}; + +struct v4l2_event32_time32 { __u32 type; union { compat_s64 value64; @@ -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; - case VIDIOC_DQEVENT32: ncmd = VIDIOC_DQEVENT; break; +#ifdef CONFIG_X86_64 + case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; + case VIDIOC_DQEVENT32_TIME32: cmd = 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 Wed Nov 6 19:47:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 11231021 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2782C139A for ; Wed, 6 Nov 2019 19:47:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EDFFE217F5 for ; Wed, 6 Nov 2019 19:47:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732329AbfKFTrp (ORCPT ); Wed, 6 Nov 2019 14:47:45 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:56765 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731975AbfKFTrp (ORCPT ); Wed, 6 Nov 2019 14:47:45 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue109 [212.227.15.145]) with ESMTPA (Nemesis) id 1MCsLu-1ibCiX3Fvk-008uFk; Wed, 06 Nov 2019 20:47:29 +0100 From: Arnd Bergmann To: Hans Verkuil , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Boris Brezillon , Maxime Ripard , Laurent Pinchart , Tiffany Lin , Daniel Mentz , Arnd Bergmann Subject: [PATCH v3 8/8] media: v4l2-core: fix compat v4l2_buffer handling for time64 ABI Date: Wed, 6 Nov 2019 20:47:15 +0100 Message-Id: <20191106194715.2238044-9-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191106194715.2238044-1-arnd@arndb.de> References: <20191106194715.2238044-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:WXfT7HDk5yJcp+dWiFeNFUSQgxVeRg+G8Csy1pwabm4B8q5WyiE u4Cdk93vLXzjfxwmNg1DptChCJCIcLFMWCkAo4b+XCS/3TH6sHAMzAygshQzDQT4GUu7vuh hU/Qfl6wcjvOL9Rjk87XqYgyCQ8F3DR5U+HdnOPx20YFiaCzmFp9CmMn5okDT/LAS8SLQgF oekZfsFVUrdmIk38PO8Bw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:LydvggMqVMs=:/PPm+o8WJ4qOXliqO0gG+w egfBvtvHMVCszgeZuozOB5z7O2UBoL5QmqyEownm7stuOYY2yBr11VzefVRipEZWK1W/9njrV 5BEfOGcJo5aFCnwAzWb5/VqLQpq1WVI4ZfB2VrinQJtV5tuZwrEm2wuaW8kesAeEaXT/Ox/Ae dZ/lvCkykKT5XyKzC9rc5y7QLxDYnV3LiiBWiDoDT6VrX4I/QdcYTLUwvvUxgy5y4WRAn/Q/U nxHXvBhkw2W4K6+1ebAoqyWALc4VCjM600EHgXeK5VVJIgK7wC1Q9wuBrJobU8NfK45YY54Zg rTpLoG0Wv7T77CsCalS2bS+s06g53HXngREEaI+MUNPBSBtjhz2++QDSHG2ZR+kyzkvWG+NZp 7aaIQShhZB12GOhiaAYPEF0SgbkLUJTrnTA64QD6vN67QzucqTUtbUFU5ebRNF58t1/5EZcXl LWIzrxI6+RYJ5ejskANARV0h9TyAvqcC59NlQbvQi2izEZVDKJ5PVoQgpPH+nMvcupHeZ6JBY 8uo3Ra6Fz20YZLL+yqvyvCsByIMtxuyHqiDhbDET5l3YY6z5b7t7RrR/AKD9li3x0279LaYy6 ParDm8kBMQIX2EeSpwh9m5DhQQrCwTeo5VHbsup6GNOxXfmzCm2jnuPwuq1U+YoZZbk01DCmr dBix8CPexbu7+QmBUfaSdJTO1Eba3mXmoZNdLyqJx+4SoTc7A9XLvAZ4Onw14AIdBiU51DDHW TTC/jLXNuPdmZw0WsHehJ/4Ai4xvOsPpyfgOnvp51FF8dO7cW7WxkHdSdtg3NuGTIbZQyuxB7 VvvptLuk9OMURd7u200OJ7dznwWDuV4X+8fUCn8kb/L2iah874ZOl0Zz0Rt/GeWBJV9UK/5nZ zSWqrtgNDZLpALQdrxsA== 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 | 263 ++++++++++++++++++ 1 file changed, 263 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index aa4bc63dc261..a13e4849df0c 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -469,6 +469,32 @@ struct v4l2_plane32 { }; struct v4l2_buffer32 { + __u32 index; + __u32 type; /* enum v4l2_buf_type */ + __u32 bytesused; + __u32 flags; + __u32 field; /* enum v4l2_field */ + 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; @@ -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;