From patchwork Mon Nov 11 20:38:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 179147 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp7166653ilf; Mon, 11 Nov 2019 12:38:52 -0800 (PST) X-Google-Smtp-Source: APXvYqzJb8yWDr6XzxzM7bbbHFWMcOEwX2dLf+/zSsM7xFUIslCt5K41UVWoqvoOqFlUjro+xDzJ X-Received: by 2002:a17:906:f191:: with SMTP id gs17mr22603537ejb.207.1573504731883; Mon, 11 Nov 2019 12:38:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573504731; cv=none; d=google.com; s=arc-20160816; b=RNG9EJRwyZHDyN3EH2I8kL48spR2OVRI+dj1av2/z+vk9kfomRW2lURbTN41T54WbJ HgGTAbtTpfkaqzep1wQCyBb3Y/oHxwJKPvkCPuNekvPnBfPQ/RVI9M3AWjpTzr5p/o9h HNsZVgi8/7+nyBX//z13G2mmI2pCOA//hsGe6sxY3JqpF6R1hlSk7/1DRAG2T3cFDY3P 5XAgQv54JLLbtQX218FOkjNuduxUruo8pzvbbe7PNsvetHwgRhbH/oQqR7/sgmskrplO EqEvL/ApCmCzK1wsrWkyIrKEUlFJ7WzTAu0+27E27P8EF7glATZOEZOhOlE8tqqQlbmL Dzeg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=hDRBVxzMGMmxe9lv0yTMXA7/54ENwGZuu069oR/KB6Y=; b=Fp7K7iv7GUfvDGtC52KxHhp+SLKetz+9O1bdyp2dO9eH+zvFAQSd4J7GbkBWyVCvSi QfDYeWRWGhZPIwFNPva3P/d1gTBStd5nDtxUY1R16HPXkzciF/qyFwHzyZlGRvjYSFOO gY+1mEyrtt0B9g4IQzYOIJstL++Kz/8l1iABOTHSid7UhO9c9kUSJtCB/FHiwRYlz6Ih Y4oaxdkG7jv0iDInBJlXaUiKXISuqxstTeeIpnVUD+9wb6Mb13vpQKx0n7LkP77NkeS0 pgOfVEH8f1biGFnyKVWKjzMng2kB8+Sdwxhwh5VcLchJsxNtte6ImMWcoPX17kQnlal0 0FuA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f21si11876735edf.277.2019.11.11.12.38.51; Mon, 11 Nov 2019 12:38:51 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727543AbfKKUir (ORCPT + 4 others); Mon, 11 Nov 2019 15:38:47 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:50135 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727170AbfKKUiq (ORCPT ); Mon, 11 Nov 2019 15:38:46 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPA (Nemesis) id 1MlL5x-1i2OQc4Am5-00lqC9; Mon, 11 Nov 2019 21:38:40 +0100 From: Arnd Bergmann To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Hans Verkuil , linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann Subject: [PATCH v4 4/8] media: v4l2-core: split out data copy from video_usercopy Date: Mon, 11 Nov 2019 21:38:31 +0100 Message-Id: <20191111203835.2260382-5-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191111203835.2260382-1-arnd@arndb.de> References: <20191111203835.2260382-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:XYSYE4CP2TXV0A5SoFgD7xC90DDcVn86gtgneJ99KiQ7zVJ2UsL 5d1PhMLzTTi9pJ4MJwArMpXoh5E3LJe1xXvzLtuPEcbxxajp6CjgvYc6nR1geKrcyAVARiw eMfP9R9Jer1sIbQQQ0qZDue60m5rAaQQo9/V+TtRE6czNZPGAfKtv/1qxGxliCkYmywgOMj NlkiM7jdlkkrluJoFjPSw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:WbYCTQEH2I8=:XkR8BsI9YP60yyNEnM2ClU nK+0BFpzUx0clF0GWFYdPaByYz+bzyfp5aXOtWq83abKAdHNBj7y5NueZNSAnGFMNz9pG1P2l TSgX7XWTSoDVMQ5GWHIlr3ZP2hRLB0xJsdwgnWUALTUxUBwVEj1Hk9p26evebkNYJaiqShyH9 VcrNd+0UnEv2Yw4FZ8+znwkkbVbIIbPxQuZBXoEr4/lNET72lj9x3akCG3/p4SDYJiq63NGC6 fGZ3BuLp7v64IwDBntNUsOs/h7ymFG7CTAeGqbZw+NakzX8Tum5qcB27j9d14K7MyJ0DssPJ/ qx+csRUtyK/Lva9PRxXbzO9CGkp/FKfD4taU+PltZNAI4keRnyY3OQ5+KUs324xx/7iYbZ5ki LokA4uZdYqqOg7lhCIZEaJZFBTW76D4EHS+wlqkcRp31FX9Y6NupaSEbmaHnmH7zFWrKLzifO d9aUJc+FhKMLv+iJx77esxSN+32ss+e+fs4t4TgY+8yoGg2jcKpG7La45GdROjQDtOeDC67Cj SPV0oML6LPPRR5uD54hWnQ23JWDa18JV0sGBL59opmnmf+Tn3qkqbeMXUJGulv2bUaXqHkVo+ LxZzVjYgBkYHVtC1DVXy++1r2KD6QAcOS4qv7w8G4uaRnEmN2soLHI9bqLJADWcxskq8uG79N H/U8BI6WwaUE32HZ9YLo6cRbvBfk3Xzpn9o4BO2N+8PRoFZuE5hn5ypz8/zRoJbbRIbwrKwKU 6mXd1WcCj5urjX1kmmORaCXk9/ux5w6X3TT7+VXkIpwlSBs5HLXpo8TjMAFoBZM0a5tjSZBGg 5c31W7QK5Ik6PlUScx1rDk1nhYQSbJY51HfXkr0KAEiZ12dWSWJMZUmocQ9sT6ctAJ62p5Dd/ 5EbDFinEmK2zRUqo20Ig== 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(-) -- 2.20.0 diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 51b912743f0f..693f9eb8e01b 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -3008,8 +3008,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]; @@ -3021,6 +3082,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 */ @@ -3035,37 +3097,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; @@ -3116,15 +3153,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 Mon Nov 11 20:38:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 179152 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp7167004ilf; Mon, 11 Nov 2019 12:39:10 -0800 (PST) X-Google-Smtp-Source: APXvYqzlk+SSBFGI0ds+URefcwV8LONbmbzca5TsghYl5t+TyMzymEq+//djvjUOmY9i6UK2JE9C X-Received: by 2002:a17:906:4913:: with SMTP id b19mr24203014ejq.61.1573504750255; Mon, 11 Nov 2019 12:39:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573504750; cv=none; d=google.com; s=arc-20160816; b=X5WkpScpmw06Sk7f6mb70vju5ySBcEXBfj6thELisaf5yJtRh9hsAYD08fbDIH7BFe mDGEmON+bb4wcViBnyNxvlcLl6GkcMe+0iB58qDQwMS0h6i+SvXSrgPyUl3pwZbjWbgh iJPaPiy3OwC1WPR1Ahm6Oo0RyOlS8e0n5SRVGU0LUYdRw4HQwteEZcWarH5LbReuXO1K jT/4r+3LvD8izJUYvauIcHu5ybQmVeoO+IK/oaYr2lY+tm5WzIeMkYcw2OkhDoXvkiKt JASw0argAiPpV6pnCvtvXv/AWOBylynlrjAtD8Nmd8nDmoXvffN0YfjMGsOHNdB1di4w zc+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=6ykWtBooGki3yv4LeNNQ0XhOjEnU++EjBG7RjvnZINE=; b=gs+ExzLHEKCbaBWpvPlZsqcFXemwfZpQjuoECbyMPCoUq5k/JeRXkQjqhJ1kXLTFCu fj1jqoAChk8wOrwUzuLJENMR+gXkpTaLEBOFG3vdq0i39UoXAgcpcYPRHA4Fb+UXCFMW H4u2UQHKW8G20dfTVWkjwjvpNomqcluIC8QFXRHMW/EC+CUNszC/rjbjPxhDGvt9O+Bs aBEiGT3UNBCM/TwAclS84XVTNsv6jHi7M/BIJy1B0NESHrct/rDUgPsXxw/AiMd1EucS ctJta1qoaGkFumIcPleanH1pUhbc8SiwHbzWDoJpT97FIT1EvoGxisXYsgeOQQIaUSs5 Mtuw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w2si11807038edf.32.2019.11.11.12.39.10; Mon, 11 Nov 2019 12:39:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727324AbfKKUjH (ORCPT + 4 others); Mon, 11 Nov 2019 15:39:07 -0500 Received: from mout.kundenserver.de ([212.227.126.133]:59485 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727200AbfKKUir (ORCPT ); Mon, 11 Nov 2019 15:38:47 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPA (Nemesis) id 1MjxW4-1i1ZUG11Vg-00kT9Q; Mon, 11 Nov 2019 21:38:40 +0100 From: Arnd Bergmann To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Hans Verkuil , linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann Subject: [PATCH v4 5/8] media: v4l2-core: fix VIDIOC_DQEVENT for time64 ABI Date: Mon, 11 Nov 2019 21:38:32 +0100 Message-Id: <20191111203835.2260382-6-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191111203835.2260382-1-arnd@arndb.de> References: <20191111203835.2260382-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:KWZVyns7uI4Ejqxez8Csfv+bM9yXU7W10+mxfa7HGG2fSSNbpzK KAB96lZ+QKg9akmwi+kwjXhEs4E9X8cBiC7DgFzunGts3GCeoyQdNh3t+sranW2ySMormI+ plD0HAD8Gn6+9mvQjsfpDNNuNXAhxdxEXHTmuyJxzQ5mdhj1Mb6Egk4YR/ufYDzDGKTl/iE cXMN0Kw8SAiDDDGDH+kjA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:mqFzTn9t+2A=:RxrvlvdLiTsR/oPT09ho58 UVc2t7maQM94eA3ZKx4mrjOAKQJIonQAjposr7cB+ur7nHasoYpEwzdk439G+/Hez9iw/omuF jX0agnTMD62cDfdJaP5lbU6GrL4qRno66TLgZIjpMeoX/Ud+w+MCfNOP/nZ1i8C8UEq1MSgx+ 9e3XXCthWXu1mjmBOhg1AYk5Uqik4U/IhP2n/y8d4Bf/EB3NP6Xp++LqbyIhDjUnWAHNthnxt LzsnfGH6Slfh3x4vuuZte0QzvjRLcSa1SIumSjUCctJwU5kajdAuOP/YFk3fKT2yNDpKwVWyt GW9SEWxvxjDJPHo0twVRQbgMjPLvO4rL+QX4xBRGJA97bJQcUA8HYYrYesf5UD4ARlyiADTC0 NCs0e8YJfyny5aMykk3oRyGHpDK1Q9Pg9vcz/o8fJgKSLJGAG0i/zpc1NluikiDiA+7bDjFBq AC5fCGaXHZ69y4PS8WFCHaMPL0ECX9mERvjohW4F83PZpfttja7bMZTeIniHWS9Mrs1MwLsPD H+OgzIyw96hhbSy1ID/ch/R5fPK4PBXB6hx34eR2q+QLLn/RWdr2q1VzE/pCgSxxghhlGWEQW JR06VnblEESGrlzbKujqcqJt0HzumIe1XAkG9elj64VWGqzgNv34Dg83ez9jw6tZgQzZrIQh/ KmIv1oQ9ir/X35OzYNUtLSnb28Bh5Bf0r5P0rqLSxNvzbP/TgHlN3YLvu8I4oD6qTKVe8i8pf +aCDwv+FQlYp/7z1IxecPICfPVTdkdzpjSishNJx+CxEERb55rIT/OWNsZlcg9hX+LLWvXVkc K+WiYdBIoiifHRvnEuGE4V/w6vo1VL3dSmShe+X+w0NGSOcDBZ515M9aN+HXk0Iq8JyRb8KRO u5NJp61aZqNk9N81Rx9A== 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 | 24 ++++++++++++++++++++- drivers/media/v4l2-core/v4l2-subdev.c | 20 +++++++++++++++++- include/uapi/linux/videodev2.h | 30 +++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) -- 2.20.0 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 693f9eb8e01b..1de939d11628 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) { @@ -3010,6 +3010,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; } @@ -3059,6 +3066,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 f725cd9b66b9..45454a628e45 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 74d3d522f3db..1d2553d4ed5b 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2329,11 +2329,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) @@ -2486,6 +2515,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 Mon Nov 11 20:38:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 179150 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp7166755ilf; Mon, 11 Nov 2019 12:38:57 -0800 (PST) X-Google-Smtp-Source: APXvYqwt02gpUo/6XU8zldA69XpM2uf+mwEeKAp1aLU2Bp4zdDVcgVHlyiDK9/ooChTD9WyIRDhK X-Received: by 2002:a05:6402:1156:: with SMTP id g22mr29079609edw.233.1573504736925; Mon, 11 Nov 2019 12:38:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573504736; cv=none; d=google.com; s=arc-20160816; b=LEpcyO60p7R8YXphPHTsOhfxRybX5KvWk6KDumitB8A5g35J1QT5kUezjoxocDwwSo VEhgYd4PYgBVc0UNaukM4JElCviZmWdxxaZ4Od3TYomlBRUspc8uT1HgNXkyxRQJZZzw Mq1BGEUYJYlpP0HQE42auvQLofpX0xF1hI4YIgyMQ3STrXw50v6duPYSlnsrTfoM/7RD H1fZfj7rQi6BkRuOgZ2Tu3iLhzbzTLhZB/u7uORsRbXxs2Zo5MO4lqcDy/dGQwK33Ac7 zgo8dc/6V9ikch6FgZ6RIP0eTlHHdIVfXPv/bMhRxPZhOkYNUQpSeHGO//vZdv/V1LtA pGcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=bheb3Pl3koFxVFS1mqzlOn3dp9DrrwaIOVbuSISOTq4=; b=RYG/1WgGjJW6kwn6iL1RiTq8tXik9a03iZl2yydcsvpgBsH8zvdx080Xpk57M2WhmK IddTL/D5JVpycC69CYkSZCSKvfl16T9Ydp4UVwl7pkc/4QiEMzCVjMCjEaKr0oylK/WI xvfLTG3giAjksfVb/mX1CM0E+JHnoUSwgrFdwGRMnol5WbawupRHLfpDlVZb64Y7+FvO EyR5qZk4av0mfU47Dwq4dE6vJu2+53BQtryZO0i7yGRoNb2FHsnrx9jBosa1kcWt6etU oDKNeN3u3KEuFt5+l4UafHtlaiqtlNfXRkDHwaEhAU2G1CVSQ4kiw9Zc6hpF6fR2ot0n lKLA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b17si10204923ejp.326.2019.11.11.12.38.56; Mon, 11 Nov 2019 12:38:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727722AbfKKUiw (ORCPT + 4 others); Mon, 11 Nov 2019 15:38:52 -0500 Received: from mout.kundenserver.de ([212.227.126.130]:52845 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727718AbfKKUiv (ORCPT ); Mon, 11 Nov 2019 15:38:51 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPA (Nemesis) id 1MG90u-1igQ4y2wgu-00Gc36; Mon, 11 Nov 2019 21:38:40 +0100 From: Arnd Bergmann To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Hans Verkuil , linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann Subject: [PATCH v4 7/8] media: v4l2-core: fix compat VIDIOC_DQEVENT for time64 ABI Date: Mon, 11 Nov 2019 21:38:34 +0100 Message-Id: <20191111203835.2260382-8-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191111203835.2260382-1-arnd@arndb.de> References: <20191111203835.2260382-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:dKK7xsILnKx0fQ4qyv2gvUd49B8SRdhukArWLoHaYtCAGNHYgF4 7s2f/9aw5odplOHsmuwHTniyBsDUEulNbO7hbiWtiNh7P4sDbRUAvSK1MJw/ddnM0uXfzdE Esf4w9zJzAn+9NaUiJ5kE6U2ipuGgPzEHxR0pUMfgw/wo8eLtTMhKSgz6X/ZCIshXHLfeRi K23lQR5zzBRA5AZf87eIQ== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:oXaK/44Wfxs=:2IWGOHBaSUHKHIxzZPkEUO Ypqrr6U8XRGBh7hsE5uPxQWvmndZe7kpWbk0rGfV14yrt1uqUqutabklUGBIBgCiZN8SLw9hv zv8asQmuADofatvSZ6WhDaUbWwc1a/+6Fd7ZoCTtT8YIgOQxQ2Qz0fyG3lLSHHCTIH4nOlqD3 YT29y+DLmoDatDI5+CEyouJjLhh92htLYetqr2hO/FE4pmUUyaYl4vxTTyCUr+Tu5Yyx86Aej 9GL8yIcobCn7dK++HXBV35DnQiM55gh7kGMGW2r49hvx0P7T3LFIfZrTl58hznPuM65OO7ckL J7rGGlxeWM1zNHOcUUlVEgyxycisfn++enkCB4QXTdvGGUppNF2PJlubi9e1VLw8kI2LydxOV KBUr/AXGi1zTWmWQKdmpQeUEpnBVxfAkhgxxiaIm9pfpcuyYMOz33EQPyx0mmLPglMtOmXgxZ 2rxHMSLu3QOeWwPiQJBmE5zWHRkiI1PjvKn/F1sOdfN/NHzZMUuqMA8oDQmPkoqYjpWJ+RuTp qFispWjzbysJO+fxm9i/ydPk2IOmq/G2hOLJ0N2/z7KWqShVZaMEsAVvAVanrLPZfH5932lMH ETs0h5R0F4fuDLGmiahR8xD0PXebzrTm5eo8RvdcAAqMipco2FzUaPp7wdzB0ZeoE75pyCg+/ ri66KVQjbvZORpFETsh5IFBNx3rZ07/d2lVEMKyMy8VxyeZN2EF8KohoHDMMRB2JbEQaOLCuc gnESR34GhdZknorp4imLOj1+15ck2FEhPpbFfnIUnruJJ0FD/ABUpp0EVZVB+HCXcHCXirvD7 1MmEVYIMuX1TuCFQ3qXMkSrBIhVw3QD+gTDq9EHXU4uCWihBmVCKw/JSa5MCVYYu+C6AtYql9 Bps4ue7HbnstxAzLdCtA== 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(-) -- 2.20.0 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 Mon Nov 11 20:38:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 179151 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp7166814ilf; Mon, 11 Nov 2019 12:39:00 -0800 (PST) X-Google-Smtp-Source: APXvYqxP7hkTtIK8crQMONmDlSQpqovzaxES9p+DsfOxfqTID2qcgmTIM8jxxqok3/Bmy2yCJkD5 X-Received: by 2002:a50:90a8:: with SMTP id c37mr28539831eda.153.1573504739961; Mon, 11 Nov 2019 12:38:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573504739; cv=none; d=google.com; s=arc-20160816; b=zUHmXRJbUvpJY/m168NccPnJXMvcYDD8rOY6CC92bUWErtspcN/SlRvUe6nxrc47yw uciSl5dyCrhH5whIG+VlaDFLBShJ5Vcjj7N4tAMG2zI6rXnjH7WzxlQPzauXwXD3Nevb DOz0fN/C1aoJsuyVnl7skpMlkTpWN/57mzIYZWUXNzCLCXCqrpXRdhAxfDrexA4AukX8 kmFXJ9Vr7+stzreFSyNXiDMZRb9GUfcHcxKs/9yiz6D0fvOuqHBMLMDXuYXZKMVxo5fL 5K0WWjW5Tno/HfWKwLKf4G44e5Pt6MXWwOuER667SNyKWKsBizcRmJfcKvU86Ld02xrC pB8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=+fGOBCoFeRp1J1DzRcQGlBEQZYgohoEdS6c3oJHQASI=; b=GmHwl9gGDhUrUWfUsNgyp0B58Ts3WF9VRNulpaE6s1CKmQ5ZNknZvFYVzSCecjLAa0 AQb5yBd0UEVHW5SW/UeuQL77OJa/SBXriF6qJwoixgjanp1KST74UixfftaN76us9Ku4 2y+r5G9h4eF+SFuCvMyZDCrayRUIyngoSgD8VzvP5Flgp7AeUjcc2w/76jUxg6T38Ryy gi4tNGO1JMq/EpTxsKFhwMwzAZniGual4V2CeIZqg8WD/XF5CKYNbhVnZgE3MAv6BO8R I5Y+tQVCcZ4TWFzJpF1XkHwrzoVfmObOZ95IsfsgnOQw4N8YUFgmg2OwfquCdgoC0y7m ECNg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b17si10204923ejp.326.2019.11.11.12.38.59; Mon, 11 Nov 2019 12:38:59 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727763AbfKKUi6 (ORCPT + 4 others); Mon, 11 Nov 2019 15:38:58 -0500 Received: from mout.kundenserver.de ([212.227.126.135]:37929 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727511AbfKKUit (ORCPT ); Mon, 11 Nov 2019 15:38:49 -0500 Received: from threadripper.lan ([149.172.19.189]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPA (Nemesis) id 1MBSJT-1icHDb3sxb-00D3PP; Mon, 11 Nov 2019 21:38:40 +0100 From: Arnd Bergmann To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Hans Verkuil , linux-kernel@vger.kernel.org, y2038@lists.linaro.org, Arnd Bergmann Subject: [PATCH v4 8/8] media: v4l2-core: fix compat v4l2_buffer handling for time64 ABI Date: Mon, 11 Nov 2019 21:38:35 +0100 Message-Id: <20191111203835.2260382-9-arnd@arndb.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20191111203835.2260382-1-arnd@arndb.de> References: <20191111203835.2260382-1-arnd@arndb.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:MrzW6KJa1cIaWEauAUsNfILMCmUCCIJRbO7mZrMOYju3SuZ5841 DSEaZeGFnl5tSaUYjEjUAtPeL9ION1/wRfxjAbl05x6JTSkWgkJNXwWyXEpgQ8aaAPybzqi b5QkWuRu0IK3YrsUZEXABBalVsGDu7I0gOXQDrLahldiaE3RwSjTkHFDSkslG1AF6DaJkmE 8Q7o7CrkE8k7sJHgMAXKw== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:VMM2+5IuRSY=:N4bvnr7GejUzA18HYGrMvk XWYNdKkHm7u7Q7ehYul8ZU6Z5BVGp6xmwBFr8oAVScmswWRe11qdmvz915BpG3IYp4M8tvqo4 c4WDeso+potaP8VtaAwRmFx4DW5m4Rx75sOZ3aF4D8Dh9MbpUwQ5BrMgJTxv3+N1VMF80RL/F T1lwjt17rtiDwHDRLwKu0T2wofDUPcnmq8wZW02fNtVN8t8Y5HlUmpN6RTJr9zBS4DjNzBqkA RXWQne3cOWgnGYoWNBSib7LIlizjhr4JJV7Fv0EekEHx8ZNLa/oAGcEZuhqSk09idamB5vIYc 4S8hOfqdFtWMplEGjXw0CSTaWsNt31vCyB743BGGDbv7hcf9NvmnuqeoTASiuoy+GhZ3oARxn Hjj5KKacL97ZiZOC/gmgXsnIV0yiVl6uEPXnbBybMbF6rPdix51p7mGLUL81LpRwUFk/gDU3x 9o3C5eXORkX9ub7/WlXx5/EFY3vui6EidtOg+mHGiSLnGucv+9AwpV5TnF8wkhyPHX7RrUX0F AeBZIeneV8WiE4SLV5doIZA8kX+IJItmKs03dHOPi3ZSV2z+XDfBQhZ9HOYrsS97xhEj3DZ2i sqw2Oobq/AtMShIhqLV0reQ++bHaOX6E1nveDS7nBDoo3y42GlfnJg7vTkTQAhyx85Z3b5GS2 59xgeP0Fm7slw3COpyDYjYeKHtimowStotJvXcIjNoB/jxujw/hYnFmdUOasBKKEigJAwVVL5 Ip59xGUzmgAxdXOK/xfHPsOvYv0L6LymLT5g2196FOz2fUwP9vhYKdNf2VmhcictUtMJVJM0M fMawAoehoN0+HIKx79MAJisZyW9LDK9rmAw3ro/BZx2n74kgzxe58FJlCW/WmHfJ9igTqrsQ2 XigDXyK4L4XOfpR4NXFA== 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(-) -- 2.20.0 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;