2019-05-19 12:08:55 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2006-01-09 17:24:59 +00:00
|
|
|
/*
|
|
|
|
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
|
|
|
|
* Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
|
|
|
|
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
|
|
|
|
* Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
|
2010-07-18 12:27:13 +00:00
|
|
|
* Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
|
2006-01-09 17:24:59 +00:00
|
|
|
* Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
|
2008-12-21 13:35:25 +00:00
|
|
|
* Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
|
2006-01-09 17:24:59 +00:00
|
|
|
*
|
|
|
|
* These routines maintain argument size conversion between 32bit and 64bit
|
|
|
|
* ioctls.
|
|
|
|
*/
|
|
|
|
|
2006-01-09 17:24:57 +00:00
|
|
|
#include <linux/compat.h>
|
2006-01-09 17:24:58 +00:00
|
|
|
#include <linux/module.h>
|
2011-12-18 23:41:19 +00:00
|
|
|
#include <linux/videodev2.h>
|
2012-08-10 09:07:12 +00:00
|
|
|
#include <linux/v4l2-subdev.h>
|
2011-12-18 23:41:19 +00:00
|
|
|
#include <media/v4l2-dev.h>
|
2018-01-24 10:30:59 +00:00
|
|
|
#include <media/v4l2-fh.h>
|
|
|
|
#include <media/v4l2-ctrls.h>
|
2008-07-20 23:26:54 +00:00
|
|
|
#include <media/v4l2-ioctl.h>
|
2006-01-09 17:24:57 +00:00
|
|
|
|
2018-04-19 16:28:07 +00:00
|
|
|
/*
|
|
|
|
* Per-ioctl data copy handlers.
|
|
|
|
*
|
|
|
|
* Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
|
|
|
|
* where "v4l2_foo" is the name of the V4L2 struct.
|
|
|
|
*
|
|
|
|
* They basically get two __user pointers, one with a 32-bits struct that
|
|
|
|
* came from the userspace call and a 64-bits struct, also allocated as
|
|
|
|
* userspace, but filled internally by do_video_ioctl().
|
|
|
|
*
|
|
|
|
* For ioctls that have pointers inside it, the functions will also
|
|
|
|
* receive an ancillary buffer with extra space, used to pass extra
|
|
|
|
* data to the routine.
|
|
|
|
*/
|
|
|
|
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_clip32 {
|
2006-01-09 17:24:59 +00:00
|
|
|
struct v4l2_rect c;
|
2018-01-04 18:08:56 +00:00
|
|
|
compat_caddr_t next;
|
2006-01-09 17:24:59 +00:00
|
|
|
};
|
|
|
|
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_window32 {
|
2006-01-09 17:24:59 +00:00
|
|
|
struct v4l2_rect w;
|
2018-01-04 11:47:28 +00:00
|
|
|
__u32 field; /* enum v4l2_field */
|
2006-01-09 17:24:59 +00:00
|
|
|
__u32 chromakey;
|
|
|
|
compat_caddr_t clips; /* actually struct v4l2_clip32 * */
|
|
|
|
__u32 clipcount;
|
|
|
|
compat_caddr_t bitmap;
|
2017-08-03 22:03:10 +00:00
|
|
|
__u8 global_alpha;
|
2006-01-09 17:24:59 +00:00
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int get_v4l2_window32(struct v4l2_window *p64,
|
|
|
|
struct v4l2_window32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
struct v4l2_window32 w32;
|
2018-01-24 11:03:08 +00:00
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
if (copy_from_user(&w32, p32, sizeof(w32)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2006-01-09 17:24:59 +00:00
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
*p64 = (struct v4l2_window) {
|
|
|
|
.w = w32.w,
|
|
|
|
.field = w32.field,
|
|
|
|
.chromakey = w32.chromakey,
|
|
|
|
.clips = (void __force *)compat_ptr(w32.clips),
|
|
|
|
.clipcount = w32.clipcount,
|
|
|
|
.bitmap = compat_ptr(w32.bitmap),
|
|
|
|
.global_alpha = w32.global_alpha,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (p64->clipcount > 2048)
|
|
|
|
return -EINVAL;
|
|
|
|
if (!p64->clipcount)
|
|
|
|
p64->clips = NULL;
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
|
2006-01-09 17:24:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int put_v4l2_window32(struct v4l2_window *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_window32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
struct v4l2_window32 w32;
|
|
|
|
|
|
|
|
memset(&w32, 0, sizeof(w32));
|
|
|
|
w32 = (struct v4l2_window32) {
|
|
|
|
.w = p64->w,
|
|
|
|
.field = p64->field,
|
|
|
|
.chromakey = p64->chromakey,
|
|
|
|
.clips = (uintptr_t)p64->clips,
|
|
|
|
.clipcount = p64->clipcount,
|
|
|
|
.bitmap = ptr_to_compat(p64->bitmap),
|
|
|
|
.global_alpha = p64->global_alpha,
|
|
|
|
};
|
2018-01-24 11:03:08 +00:00
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
/* copy everything except the clips pointer */
|
|
|
|
if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
|
|
|
|
copy_to_user(&p32->clipcount, &w32.clipcount,
|
|
|
|
sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
|
2018-01-24 11:03:08 +00:00
|
|
|
return -EFAULT;
|
2020-10-30 16:55:27 +00:00
|
|
|
|
2006-01-09 17:24:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_format32 {
|
2012-05-10 05:02:07 +00:00
|
|
|
__u32 type; /* enum v4l2_buf_type */
|
2008-10-22 03:04:45 +00:00
|
|
|
union {
|
2008-12-21 13:35:25 +00:00
|
|
|
struct v4l2_pix_format pix;
|
2010-07-29 17:56:47 +00:00
|
|
|
struct v4l2_pix_format_mplane pix_mp;
|
2008-12-21 13:35:25 +00:00
|
|
|
struct v4l2_window32 win;
|
|
|
|
struct v4l2_vbi_format vbi;
|
|
|
|
struct v4l2_sliced_vbi_format sliced;
|
2015-09-17 09:46:04 +00:00
|
|
|
struct v4l2_sdr_format sdr;
|
2016-04-12 22:40:46 +00:00
|
|
|
struct v4l2_meta_format meta;
|
2008-10-22 03:04:45 +00:00
|
|
|
__u8 raw_data[200]; /* user-defined */
|
2006-01-09 17:24:59 +00:00
|
|
|
} fmt;
|
|
|
|
};
|
|
|
|
|
2011-09-07 21:07:23 +00:00
|
|
|
/**
|
|
|
|
* struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
|
|
|
|
* @index: on return, index of the first created buffer
|
|
|
|
* @count: entry: number of requested buffers,
|
|
|
|
* return: number of created buffers
|
|
|
|
* @memory: buffer memory type
|
|
|
|
* @format: frame format, for which buffers are requested
|
2018-09-14 09:57:51 +00:00
|
|
|
* @capabilities: capabilities of this buffer type.
|
2021-09-09 11:24:29 +00:00
|
|
|
* @flags: additional buffer management attributes (ignored unless the
|
|
|
|
* queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
|
|
|
|
* configured for MMAP streaming I/O).
|
2011-09-07 21:07:23 +00:00
|
|
|
* @reserved: future extensions
|
|
|
|
*/
|
2011-09-28 14:34:06 +00:00
|
|
|
struct v4l2_create_buffers32 {
|
2011-09-07 21:07:23 +00:00
|
|
|
__u32 index;
|
2011-09-28 14:34:06 +00:00
|
|
|
__u32 count;
|
2012-05-10 05:02:07 +00:00
|
|
|
__u32 memory; /* enum v4l2_memory */
|
2011-09-07 21:07:23 +00:00
|
|
|
struct v4l2_format32 format;
|
2018-08-23 14:18:35 +00:00
|
|
|
__u32 capabilities;
|
2021-09-09 11:24:29 +00:00
|
|
|
__u32 flags;
|
|
|
|
__u32 reserved[6];
|
2011-09-28 14:34:06 +00:00
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int get_v4l2_format32(struct v4l2_format *p64,
|
|
|
|
struct v4l2_format32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
if (get_user(p64->type, &p32->type))
|
[media] V4L2: fix VIDIOC_CREATE_BUFS in 64- / 32-bit compatibility mode
If a struct contains 64-bit fields, it is aligned on 64-bit boundaries
within containing structs in 64-bit compilations. This is the case with
struct v4l2_window, which contains pointers and is embedded into struct
v4l2_format, and that one is embedded into struct v4l2_create_buffers.
Unlike some other structs, used as a part of the kernel ABI as ioctl()
arguments, that are packed, these structs aren't packed. This isn't a
problem per se, but the ioctl-compat code for VIDIOC_CREATE_BUFS contains
a bug, that triggers in such 64-bit builds. That code wrongly assumes,
that in struct v4l2_create_buffers, struct v4l2_format immediately follows
the __u32 memory field, which in fact isn't the case. This bug wasn't
visible until now, because until recently hardly any applications used
this ioctl() and mostly embedded 32-bit only drivers implemented it. This
is changing now with addition of this ioctl() to some USB drivers, e.g.
UVC. This patch fixes the bug by copying parts of struct
v4l2_create_buffers separately.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
2014-04-26 15:51:31 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
switch (p64->type) {
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
|
|
|
|
sizeof(p64->fmt.pix)) ? -EFAULT : 0;
|
2010-07-29 17:56:47 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
|
|
|
|
sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
2020-10-30 16:55:27 +00:00
|
|
|
return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
|
|
|
|
sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
|
|
|
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
|
|
|
|
sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
|
2015-09-17 09:46:04 +00:00
|
|
|
case V4L2_BUF_TYPE_SDR_CAPTURE:
|
2015-10-10 16:51:00 +00:00
|
|
|
case V4L2_BUF_TYPE_SDR_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
|
|
|
|
sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
|
2016-04-12 22:40:46 +00:00
|
|
|
case V4L2_BUF_TYPE_META_CAPTURE:
|
2017-06-16 12:38:31 +00:00
|
|
|
case V4L2_BUF_TYPE_META_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
|
|
|
|
sizeof(p64->fmt.meta)) ? -EFAULT : 0;
|
2006-01-09 17:24:59 +00:00
|
|
|
default:
|
2008-12-21 13:35:25 +00:00
|
|
|
return -EINVAL;
|
2006-01-09 17:24:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int get_v4l2_create32(struct v4l2_create_buffers *p64,
|
|
|
|
struct v4l2_create_buffers32 __user *p32)
|
2011-09-28 14:34:06 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
if (copy_from_user(p64, p32,
|
|
|
|
offsetof(struct v4l2_create_buffers32, format)))
|
[media] V4L2: fix VIDIOC_CREATE_BUFS in 64- / 32-bit compatibility mode
If a struct contains 64-bit fields, it is aligned on 64-bit boundaries
within containing structs in 64-bit compilations. This is the case with
struct v4l2_window, which contains pointers and is embedded into struct
v4l2_format, and that one is embedded into struct v4l2_create_buffers.
Unlike some other structs, used as a part of the kernel ABI as ioctl()
arguments, that are packed, these structs aren't packed. This isn't a
problem per se, but the ioctl-compat code for VIDIOC_CREATE_BUFS contains
a bug, that triggers in such 64-bit builds. That code wrongly assumes,
that in struct v4l2_create_buffers, struct v4l2_format immediately follows
the __u32 memory field, which in fact isn't the case. This bug wasn't
visible until now, because until recently hardly any applications used
this ioctl() and mostly embedded 32-bit only drivers implemented it. This
is changing now with addition of this ioctl() to some USB drivers, e.g.
UVC. This patch fixes the bug by copying parts of struct
v4l2_create_buffers separately.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
2014-04-26 15:51:31 +00:00
|
|
|
return -EFAULT;
|
2021-09-09 11:24:29 +00:00
|
|
|
if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
|
|
|
|
return -EFAULT;
|
2020-10-30 16:55:27 +00:00
|
|
|
return get_v4l2_format32(&p64->format, &p32->format);
|
2011-09-28 14:34:06 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int put_v4l2_format32(struct v4l2_format *p64,
|
|
|
|
struct v4l2_format32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
switch (p64->type) {
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.pix)) ? -EFAULT : 0;
|
2010-07-29 17:56:47 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
|
2006-01-09 17:24:59 +00:00
|
|
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
|
2008-12-21 13:35:25 +00:00
|
|
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
|
|
|
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
|
2015-09-17 09:46:04 +00:00
|
|
|
case V4L2_BUF_TYPE_SDR_CAPTURE:
|
2015-10-10 16:51:00 +00:00
|
|
|
case V4L2_BUF_TYPE_SDR_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
|
2016-04-12 22:40:46 +00:00
|
|
|
case V4L2_BUF_TYPE_META_CAPTURE:
|
2017-06-16 12:38:31 +00:00
|
|
|
case V4L2_BUF_TYPE_META_OUTPUT:
|
2020-10-30 16:55:27 +00:00
|
|
|
return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p64->fmt.meta)) ? -EFAULT : 0;
|
2006-01-09 17:24:59 +00:00
|
|
|
default:
|
2008-12-21 13:35:25 +00:00
|
|
|
return -EINVAL;
|
2006-01-09 17:24:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:27 +00:00
|
|
|
static int put_v4l2_create32(struct v4l2_create_buffers *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_create_buffers32 __user *p32)
|
2011-09-28 14:34:06 +00:00
|
|
|
{
|
2020-10-30 16:55:27 +00:00
|
|
|
if (copy_to_user(p32, p64,
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
offsetof(struct v4l2_create_buffers32, format)) ||
|
2020-10-30 16:55:27 +00:00
|
|
|
put_user(p64->capabilities, &p32->capabilities) ||
|
2021-09-09 11:24:29 +00:00
|
|
|
put_user(p64->flags, &p32->flags) ||
|
2020-10-30 16:55:27 +00:00
|
|
|
copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
|
2014-05-30 23:26:38 +00:00
|
|
|
return -EFAULT;
|
2020-10-30 16:55:27 +00:00
|
|
|
return put_v4l2_format32(&p64->format, &p32->format);
|
2011-09-28 14:34:06 +00:00
|
|
|
}
|
|
|
|
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_standard32 {
|
2006-01-09 17:24:59 +00:00
|
|
|
__u32 index;
|
2015-08-31 11:56:15 +00:00
|
|
|
compat_u64 id;
|
2006-01-09 17:24:59 +00:00
|
|
|
__u8 name[24];
|
|
|
|
struct v4l2_fract frameperiod; /* Frames, not fields */
|
|
|
|
__u32 framelines;
|
|
|
|
__u32 reserved[4];
|
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int get_v4l2_standard32(struct v4l2_standard *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_standard32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
|
|
|
/* other fields are not set by the user, nor used by the driver */
|
2020-10-30 16:55:28 +00:00
|
|
|
return get_user(p64->index, &p32->index);
|
2006-01-09 17:24:59 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int put_v4l2_standard32(struct v4l2_standard *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_standard32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (put_user(p64->index, &p32->index) ||
|
|
|
|
put_user(p64->id, &p32->id) ||
|
|
|
|
copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
|
|
|
|
copy_to_user(&p32->frameperiod, &p64->frameperiod,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
sizeof(p32->frameperiod)) ||
|
2020-10-30 16:55:28 +00:00
|
|
|
put_user(p64->framelines, &p32->framelines) ||
|
|
|
|
copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2006-01-12 01:40:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-29 17:56:47 +00:00
|
|
|
struct v4l2_plane32 {
|
|
|
|
__u32 bytesused;
|
|
|
|
__u32 length;
|
|
|
|
union {
|
|
|
|
__u32 mem_offset;
|
|
|
|
compat_long_t userptr;
|
2012-06-14 13:37:35 +00:00
|
|
|
__s32 fd;
|
2010-07-29 17:56:47 +00:00
|
|
|
} m;
|
|
|
|
__u32 data_offset;
|
|
|
|
__u32 reserved[11];
|
|
|
|
};
|
|
|
|
|
2019-12-16 14:15:06 +00:00
|
|
|
/*
|
|
|
|
* This is correct for all architectures including i386, but not x32,
|
|
|
|
* which has different alignment requirements for timestamp
|
|
|
|
*/
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_buffer32 {
|
2006-01-09 17:24:59 +00:00
|
|
|
__u32 index;
|
2012-05-10 05:02:07 +00:00
|
|
|
__u32 type; /* enum v4l2_buf_type */
|
2006-01-09 17:24:59 +00:00
|
|
|
__u32 bytesused;
|
|
|
|
__u32 flags;
|
2012-05-10 05:02:07 +00:00
|
|
|
__u32 field; /* enum v4l2_field */
|
2019-12-16 14:15:06 +00:00
|
|
|
struct {
|
|
|
|
compat_s64 tv_sec;
|
|
|
|
compat_s64 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;
|
|
|
|
};
|
|
|
|
|
2020-11-09 08:47:44 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
2019-12-16 14:15:06 +00:00
|
|
|
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;
|
2006-01-09 17:24:59 +00:00
|
|
|
struct v4l2_timecode timecode;
|
|
|
|
__u32 sequence;
|
|
|
|
|
|
|
|
/* memory location */
|
2012-05-10 05:02:07 +00:00
|
|
|
__u32 memory; /* enum v4l2_memory */
|
2006-01-09 17:24:59 +00:00
|
|
|
union {
|
|
|
|
__u32 offset;
|
|
|
|
compat_long_t userptr;
|
2010-07-29 17:56:47 +00:00
|
|
|
compat_caddr_t planes;
|
2012-06-14 13:37:35 +00:00
|
|
|
__s32 fd;
|
2006-01-09 17:24:59 +00:00
|
|
|
} m;
|
|
|
|
__u32 length;
|
2012-05-02 12:40:03 +00:00
|
|
|
__u32 reserved2;
|
2018-05-21 08:54:44 +00:00
|
|
|
__s32 request_fd;
|
2006-01-09 17:24:59 +00:00
|
|
|
};
|
2020-11-09 08:47:44 +00:00
|
|
|
#endif
|
2006-01-09 17:24:59 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
static int get_v4l2_plane32(struct v4l2_plane *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_plane32 __user *p32,
|
2018-01-24 09:35:48 +00:00
|
|
|
enum v4l2_memory memory)
|
2010-07-29 17:56:47 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_plane32 plane32;
|
|
|
|
typeof(p64->m) m = {};
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_from_user(&plane32, p32, sizeof(plane32)))
|
2010-07-29 17:56:47 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2018-01-24 10:19:59 +00:00
|
|
|
switch (memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
2020-10-30 16:55:25 +00:00
|
|
|
m.mem_offset = plane32.m.mem_offset;
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
2020-10-30 16:55:25 +00:00
|
|
|
m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
2020-10-30 16:55:25 +00:00
|
|
|
m.fd = plane32.m.fd;
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
2010-07-29 17:56:47 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
memset(p64, 0, sizeof(*p64));
|
|
|
|
*p64 = (struct v4l2_plane) {
|
|
|
|
.bytesused = plane32.bytesused,
|
|
|
|
.length = plane32.length,
|
|
|
|
.m = m,
|
|
|
|
.data_offset = plane32.data_offset,
|
|
|
|
};
|
|
|
|
|
2010-07-29 17:56:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
static int put_v4l2_plane32(struct v4l2_plane *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_plane32 __user *p32,
|
2018-01-24 09:35:48 +00:00
|
|
|
enum v4l2_memory memory)
|
2010-07-29 17:56:47 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_plane32 plane32;
|
2018-01-24 10:19:59 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
memset(&plane32, 0, sizeof(plane32));
|
|
|
|
plane32 = (struct v4l2_plane32) {
|
|
|
|
.bytesused = p64->bytesused,
|
|
|
|
.length = p64->length,
|
|
|
|
.data_offset = p64->data_offset,
|
|
|
|
};
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2018-01-24 10:19:59 +00:00
|
|
|
switch (memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
2020-10-30 16:55:25 +00:00
|
|
|
plane32.m.mem_offset = p64->m.mem_offset;
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
2020-10-30 16:55:25 +00:00
|
|
|
plane32.m.userptr = (uintptr_t)(p64->m.userptr);
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
2020-10-30 16:55:25 +00:00
|
|
|
plane32.m.fd = p64->m.fd;
|
2018-01-24 10:19:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_to_user(p32, &plane32, sizeof(plane32)))
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
static int get_v4l2_buffer32(struct v4l2_buffer *vb,
|
|
|
|
struct v4l2_buffer32 __user *arg)
|
2019-12-16 14:15:06 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_buffer32 vb32;
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_from_user(&vb32, arg, sizeof(vb32)))
|
2019-12-16 14:15:06 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
memset(vb, 0, sizeof(*vb));
|
|
|
|
*vb = (struct v4l2_buffer) {
|
|
|
|
.index = vb32.index,
|
|
|
|
.type = vb32.type,
|
|
|
|
.bytesused = vb32.bytesused,
|
|
|
|
.flags = vb32.flags,
|
|
|
|
.field = vb32.field,
|
|
|
|
.timestamp.tv_sec = vb32.timestamp.tv_sec,
|
|
|
|
.timestamp.tv_usec = vb32.timestamp.tv_usec,
|
|
|
|
.timecode = vb32.timecode,
|
|
|
|
.sequence = vb32.sequence,
|
|
|
|
.memory = vb32.memory,
|
|
|
|
.m.offset = vb32.m.offset,
|
|
|
|
.length = vb32.length,
|
|
|
|
.request_fd = vb32.request_fd,
|
|
|
|
};
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
switch (vb->memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
|
|
|
vb->m.offset = vb32.m.offset;
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
|
|
|
vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
|
|
|
vb->m.fd = vb32.m.fd;
|
|
|
|
break;
|
2019-12-16 14:15:06 +00:00
|
|
|
}
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
|
|
|
|
vb->m.planes = (void __force *)
|
|
|
|
compat_ptr(vb32.m.planes);
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2006-01-09 17:24:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
|
|
|
|
struct v4l2_buffer32_time32 __user *arg)
|
2019-12-16 14:15:06 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_buffer32_time32 vb32;
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_from_user(&vb32, arg, sizeof(vb32)))
|
2019-12-16 14:15:06 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
*vb = (struct v4l2_buffer) {
|
|
|
|
.index = vb32.index,
|
|
|
|
.type = vb32.type,
|
|
|
|
.bytesused = vb32.bytesused,
|
|
|
|
.flags = vb32.flags,
|
|
|
|
.field = vb32.field,
|
|
|
|
.timestamp.tv_sec = vb32.timestamp.tv_sec,
|
|
|
|
.timestamp.tv_usec = vb32.timestamp.tv_usec,
|
|
|
|
.timecode = vb32.timecode,
|
|
|
|
.sequence = vb32.sequence,
|
|
|
|
.memory = vb32.memory,
|
|
|
|
.m.offset = vb32.m.offset,
|
|
|
|
.length = vb32.length,
|
|
|
|
.request_fd = vb32.request_fd,
|
|
|
|
};
|
|
|
|
switch (vb->memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
|
|
|
vb->m.offset = vb32.m.offset;
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
|
|
|
vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
|
|
|
vb->m.fd = vb32.m.fd;
|
|
|
|
break;
|
2019-12-16 14:15:06 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
|
|
|
|
vb->m.planes = (void __force *)
|
|
|
|
compat_ptr(vb32.m.planes);
|
|
|
|
|
2019-12-16 14:15:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2020-10-30 16:55:25 +00:00
|
|
|
#endif
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
static int put_v4l2_buffer32(struct v4l2_buffer *vb,
|
|
|
|
struct v4l2_buffer32 __user *arg)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_buffer32 vb32;
|
|
|
|
|
|
|
|
memset(&vb32, 0, sizeof(vb32));
|
|
|
|
vb32 = (struct v4l2_buffer32) {
|
|
|
|
.index = vb->index,
|
|
|
|
.type = vb->type,
|
|
|
|
.bytesused = vb->bytesused,
|
|
|
|
.flags = vb->flags,
|
|
|
|
.field = vb->field,
|
|
|
|
.timestamp.tv_sec = vb->timestamp.tv_sec,
|
|
|
|
.timestamp.tv_usec = vb->timestamp.tv_usec,
|
|
|
|
.timecode = vb->timecode,
|
|
|
|
.sequence = vb->sequence,
|
|
|
|
.memory = vb->memory,
|
|
|
|
.m.offset = vb->m.offset,
|
|
|
|
.length = vb->length,
|
|
|
|
.request_fd = vb->request_fd,
|
|
|
|
};
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
switch (vb->memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
|
|
|
vb32.m.offset = vb->m.offset;
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
|
|
|
vb32.m.userptr = (uintptr_t)(vb->m.userptr);
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
|
|
|
vb32.m.fd = vb->m.fd;
|
|
|
|
break;
|
|
|
|
}
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
|
|
|
|
vb32.m.planes = (uintptr_t)vb->m.planes;
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_to_user(arg, &vb32, sizeof(vb32)))
|
|
|
|
return -EFAULT;
|
2010-07-29 17:56:47 +00:00
|
|
|
|
2006-01-09 17:24:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
|
|
|
|
struct v4l2_buffer32_time32 __user *arg)
|
2019-12-16 14:15:06 +00:00
|
|
|
{
|
2020-10-30 16:55:25 +00:00
|
|
|
struct v4l2_buffer32_time32 vb32;
|
|
|
|
|
|
|
|
memset(&vb32, 0, sizeof(vb32));
|
|
|
|
vb32 = (struct v4l2_buffer32_time32) {
|
|
|
|
.index = vb->index,
|
|
|
|
.type = vb->type,
|
|
|
|
.bytesused = vb->bytesused,
|
|
|
|
.flags = vb->flags,
|
|
|
|
.field = vb->field,
|
|
|
|
.timestamp.tv_sec = vb->timestamp.tv_sec,
|
|
|
|
.timestamp.tv_usec = vb->timestamp.tv_usec,
|
|
|
|
.timecode = vb->timecode,
|
|
|
|
.sequence = vb->sequence,
|
|
|
|
.memory = vb->memory,
|
|
|
|
.m.offset = vb->m.offset,
|
|
|
|
.length = vb->length,
|
|
|
|
.request_fd = vb->request_fd,
|
|
|
|
};
|
|
|
|
switch (vb->memory) {
|
|
|
|
case V4L2_MEMORY_MMAP:
|
|
|
|
case V4L2_MEMORY_OVERLAY:
|
|
|
|
vb32.m.offset = vb->m.offset;
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_USERPTR:
|
|
|
|
vb32.m.userptr = (uintptr_t)(vb->m.userptr);
|
|
|
|
break;
|
|
|
|
case V4L2_MEMORY_DMABUF:
|
|
|
|
vb32.m.fd = vb->m.fd;
|
|
|
|
break;
|
|
|
|
}
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
|
|
|
|
vb32.m.planes = (uintptr_t)vb->m.planes;
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2020-10-30 16:55:25 +00:00
|
|
|
if (copy_to_user(arg, &vb32, sizeof(vb32)))
|
2019-12-16 14:15:06 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2020-10-30 16:55:25 +00:00
|
|
|
#endif
|
2019-12-16 14:15:06 +00:00
|
|
|
|
2008-10-22 03:04:45 +00:00
|
|
|
struct v4l2_framebuffer32 {
|
2006-01-09 17:24:59 +00:00
|
|
|
__u32 capability;
|
|
|
|
__u32 flags;
|
2018-01-04 18:08:56 +00:00
|
|
|
compat_caddr_t base;
|
2014-05-27 12:41:05 +00:00
|
|
|
struct {
|
|
|
|
__u32 width;
|
|
|
|
__u32 height;
|
|
|
|
__u32 pixelformat;
|
|
|
|
__u32 field;
|
|
|
|
__u32 bytesperline;
|
|
|
|
__u32 sizeimage;
|
|
|
|
__u32 colorspace;
|
|
|
|
__u32 priv;
|
|
|
|
} fmt;
|
2006-01-09 17:24:59 +00:00
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_framebuffer32 __user *p32)
|
2006-01-09 17:25:00 +00:00
|
|
|
{
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
compat_caddr_t tmp;
|
2006-01-09 17:25:00 +00:00
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
if (get_user(tmp, &p32->base) ||
|
|
|
|
get_user(p64->capability, &p32->capability) ||
|
|
|
|
get_user(p64->flags, &p32->flags) ||
|
|
|
|
copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2020-10-30 16:55:28 +00:00
|
|
|
p64->base = (void __force *)compat_ptr(tmp);
|
|
|
|
|
2006-01-09 17:25:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_framebuffer32 __user *p32)
|
2006-01-09 17:24:59 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (put_user((uintptr_t)p64->base, &p32->base) ||
|
|
|
|
put_user(p64->capability, &p32->capability) ||
|
|
|
|
put_user(p64->flags, &p32->flags) ||
|
|
|
|
copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2020-10-30 16:55:28 +00:00
|
|
|
|
2006-01-09 17:24:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-21 13:35:25 +00:00
|
|
|
struct v4l2_input32 {
|
|
|
|
__u32 index; /* Which input */
|
|
|
|
__u8 name[32]; /* Label */
|
|
|
|
__u32 type; /* Type of input */
|
|
|
|
__u32 audioset; /* Associated audios (bitfield) */
|
|
|
|
__u32 tuner; /* Associated tuner */
|
2015-08-31 11:56:15 +00:00
|
|
|
compat_u64 std;
|
2008-12-21 13:35:25 +00:00
|
|
|
__u32 status;
|
2017-08-04 11:25:06 +00:00
|
|
|
__u32 capabilities;
|
|
|
|
__u32 reserved[3];
|
2015-08-31 11:56:15 +00:00
|
|
|
};
|
2008-12-21 13:35:25 +00:00
|
|
|
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
/*
|
|
|
|
* The 64-bit v4l2_input struct has extra padding at the end of the struct.
|
|
|
|
* Otherwise it is identical to the 32-bit version.
|
|
|
|
*/
|
2020-10-30 16:55:28 +00:00
|
|
|
static inline int get_v4l2_input32(struct v4l2_input *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_input32 __user *p32)
|
2006-01-12 01:40:51 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (copy_from_user(p64, p32, sizeof(*p32)))
|
2006-02-01 10:24:20 +00:00
|
|
|
return -EFAULT;
|
2006-01-12 01:40:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static inline int put_v4l2_input32(struct v4l2_input *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_input32 __user *p32)
|
2006-01-12 01:40:51 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (copy_to_user(p32, p64, sizeof(*p32)))
|
2006-02-01 10:24:20 +00:00
|
|
|
return -EFAULT;
|
2006-01-12 01:40:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-21 13:35:25 +00:00
|
|
|
struct v4l2_ext_controls32 {
|
2015-10-29 10:10:28 +00:00
|
|
|
__u32 which;
|
2015-08-21 13:19:22 +00:00
|
|
|
__u32 count;
|
|
|
|
__u32 error_idx;
|
2018-05-21 08:54:35 +00:00
|
|
|
__s32 request_fd;
|
|
|
|
__u32 reserved[1];
|
2015-08-21 13:19:22 +00:00
|
|
|
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
|
2006-07-21 21:53:23 +00:00
|
|
|
};
|
|
|
|
|
2009-08-11 21:47:18 +00:00
|
|
|
struct v4l2_ext_control32 {
|
|
|
|
__u32 id;
|
|
|
|
__u32 size;
|
|
|
|
__u32 reserved2[1];
|
|
|
|
union {
|
|
|
|
__s32 value;
|
|
|
|
__s64 value64;
|
|
|
|
compat_caddr_t string; /* actually char * */
|
|
|
|
};
|
|
|
|
} __attribute__ ((packed));
|
|
|
|
|
2018-01-24 10:30:59 +00:00
|
|
|
/* Return true if this control is a pointer type. */
|
|
|
|
static inline bool ctrl_is_pointer(struct file *file, u32 id)
|
2009-08-11 21:47:18 +00:00
|
|
|
{
|
2018-01-24 10:30:59 +00:00
|
|
|
struct video_device *vdev = video_devdata(file);
|
|
|
|
struct v4l2_fh *fh = NULL;
|
|
|
|
struct v4l2_ctrl_handler *hdl = NULL;
|
|
|
|
struct v4l2_query_ext_ctrl qec = { id };
|
|
|
|
const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
|
|
|
|
|
|
|
|
if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
|
|
|
|
fh = file->private_data;
|
|
|
|
|
|
|
|
if (fh && fh->ctrl_handler)
|
|
|
|
hdl = fh->ctrl_handler;
|
|
|
|
else if (vdev->ctrl_handler)
|
|
|
|
hdl = vdev->ctrl_handler;
|
|
|
|
|
|
|
|
if (hdl) {
|
|
|
|
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
|
|
|
|
|
|
|
|
return ctrl && ctrl->is_ptr;
|
2009-08-11 21:49:12 +00:00
|
|
|
}
|
2018-01-24 10:30:59 +00:00
|
|
|
|
2018-01-30 15:18:32 +00:00
|
|
|
if (!ops || !ops->vidioc_query_ext_ctrl)
|
2018-01-24 10:30:59 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
|
|
|
|
(qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
|
2009-08-11 21:47:18 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
|
|
|
|
struct v4l2_ext_controls32 __user *p32)
|
2006-07-21 21:53:23 +00:00
|
|
|
{
|
2020-10-30 16:55:24 +00:00
|
|
|
struct v4l2_ext_controls32 ec32;
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
if (copy_from_user(&ec32, p32, sizeof(ec32)))
|
media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit
equivalent. It converts 32-bit data structures into its 64-bit
equivalents and needs to provide the data to the 64-bit ioctl in user
space memory which is commonly allocated using
compat_alloc_user_space().
However, due to how that function is implemented, it can only be called
a single time for every syscall invocation.
Supposedly to avoid this limitation, the existing code uses a mix of
memory from the kernel stack and memory allocated through
compat_alloc_user_space().
Under normal circumstances, this would not work, because the 64-bit
ioctl expects all pointers to point to user space memory. As a
workaround, set_fs(KERNEL_DS) is called to temporarily disable this
extra safety check and allow kernel pointers. However, this might
introduce a security vulnerability: The result of the 32-bit to 64-bit
conversion is writeable by user space because the output buffer has been
allocated via compat_alloc_user_space(). A malicious user space process
could then manipulate pointers inside this output buffer, and due to the
previous set_fs(KERNEL_DS) call, functions like get_user() or put_user()
no longer prevent kernel memory access.
The new approach is to pre-calculate the total amount of user space
memory that is needed, allocate it using compat_alloc_user_space() and
then divide up the allocated memory to accommodate all data structures
that need to be converted.
An alternative approach would have been to retain the union type karg
that they allocated on the kernel stack in do_video_ioctl(), copy all
data from user space into karg and then back to user space. However, we
decided against this approach because it does not align with other
compat syscall implementations. Instead, we tried to replicate the
get_user/put_user pairs as found in other places in the kernel:
if (get_user(clipcount, &up->clipcount) ||
put_user(clipcount, &kp->clipcount)) return -EFAULT;
Notes from hans.verkuil@cisco.com:
This patch was taken from:
https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7
Clearly nobody could be bothered to upstream this patch or at minimum
tell us :-( We only heard about this a week ago.
This patch was rebased and cleaned up. Compared to the original I
also swapped the order of the convert_in_user arguments so that they
matched copy_in_user. It was hard to review otherwise. I also replaced
the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function.
Fixes: 6b5a9492ca ("v4l: introduce string control support.")
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Co-developed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v4.15 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 23:03:19 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
*p64 = (struct v4l2_ext_controls) {
|
|
|
|
.which = ec32.which,
|
|
|
|
.count = ec32.count,
|
|
|
|
.error_idx = ec32.error_idx,
|
|
|
|
.request_fd = ec32.request_fd,
|
|
|
|
.reserved[0] = ec32.reserved[0],
|
|
|
|
.controls = (void __force *)compat_ptr(ec32.controls),
|
|
|
|
};
|
2009-08-11 21:47:18 +00:00
|
|
|
|
2006-07-21 21:53:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_ext_controls32 __user *p32)
|
2006-01-09 17:24:57 +00:00
|
|
|
{
|
2020-10-30 16:55:24 +00:00
|
|
|
struct v4l2_ext_controls32 ec32;
|
|
|
|
|
|
|
|
memset(&ec32, 0, sizeof(ec32));
|
|
|
|
ec32 = (struct v4l2_ext_controls32) {
|
|
|
|
.which = p64->which,
|
|
|
|
.count = p64->count,
|
|
|
|
.error_idx = p64->error_idx,
|
|
|
|
.request_fd = p64->request_fd,
|
|
|
|
.reserved[0] = p64->reserved[0],
|
|
|
|
.controls = (uintptr_t)p64->controls,
|
|
|
|
};
|
2006-01-12 01:40:51 +00:00
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
if (copy_to_user(p32, &ec32, sizeof(ec32)))
|
2006-01-09 17:24:57 +00:00
|
|
|
return -EFAULT;
|
|
|
|
|
2008-12-21 13:35:25 +00:00
|
|
|
return 0;
|
2006-01-09 17:24:57 +00:00
|
|
|
}
|
2008-12-21 13:35:25 +00:00
|
|
|
|
2019-12-16 14:15:05 +00:00
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
/*
|
|
|
|
* x86 is the only compat architecture with different struct alignment
|
|
|
|
* between 32-bit and 64-bit tasks.
|
|
|
|
*/
|
2011-06-07 14:43:57 +00:00
|
|
|
struct v4l2_event32 {
|
|
|
|
__u32 type;
|
|
|
|
union {
|
2015-08-31 11:56:15 +00:00
|
|
|
compat_s64 value64;
|
2011-06-07 14:43:57 +00:00
|
|
|
__u8 data[64];
|
|
|
|
} u;
|
|
|
|
__u32 pending;
|
|
|
|
__u32 sequence;
|
2019-12-16 14:15:05 +00:00
|
|
|
struct {
|
|
|
|
compat_s64 tv_sec;
|
|
|
|
compat_s64 tv_nsec;
|
|
|
|
} timestamp;
|
|
|
|
__u32 id;
|
|
|
|
__u32 reserved[8];
|
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int put_v4l2_event32(struct v4l2_event *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_event32 __user *p32)
|
2011-06-07 14:43:57 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (put_user(p64->type, &p32->type) ||
|
|
|
|
copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
|
|
|
|
put_user(p64->pending, &p32->pending) ||
|
|
|
|
put_user(p64->sequence, &p32->sequence) ||
|
|
|
|
put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
|
|
|
|
put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
|
|
|
|
put_user(p64->id, &p32->id) ||
|
|
|
|
copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2011-06-07 14:43:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-26 05:49:54 +00:00
|
|
|
#endif
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
2021-10-26 05:49:54 +00:00
|
|
|
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];
|
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int put_v4l2_event32_time32(struct v4l2_event *p64,
|
2019-12-16 14:15:05 +00:00
|
|
|
struct v4l2_event32_time32 __user *p32)
|
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (put_user(p64->type, &p32->type) ||
|
|
|
|
copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
|
|
|
|
put_user(p64->pending, &p32->pending) ||
|
|
|
|
put_user(p64->sequence, &p32->sequence) ||
|
|
|
|
put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
|
|
|
|
put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
|
|
|
|
put_user(p64->id, &p32->id) ||
|
|
|
|
copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
|
2019-12-16 14:15:05 +00:00
|
|
|
return -EFAULT;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-03-07 10:18:37 +00:00
|
|
|
struct v4l2_edid32 {
|
2012-08-10 09:07:12 +00:00
|
|
|
__u32 pad;
|
|
|
|
__u32 start_block;
|
|
|
|
__u32 blocks;
|
|
|
|
__u32 reserved[5];
|
|
|
|
compat_caddr_t edid;
|
|
|
|
};
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int get_v4l2_edid32(struct v4l2_edid *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_edid32 __user *p32)
|
2012-08-10 09:07:12 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
compat_uptr_t edid;
|
|
|
|
|
|
|
|
if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
|
|
|
|
get_user(edid, &p32->edid))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2020-10-30 16:55:28 +00:00
|
|
|
|
|
|
|
p64->edid = (void __force *)compat_ptr(edid);
|
2012-08-10 09:07:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-30 16:55:28 +00:00
|
|
|
static int put_v4l2_edid32(struct v4l2_edid *p64,
|
media: v4l2-compat-ioctl32: better name userspace pointers
In the past, "up" were an acronym for "user pointer" and "kp" for
"kernel pointer". However, since commit a1dfb4c48cc1 ("media:
v4l2-compat-ioctl32.c: refactor compat ioctl32 logic"), both
are now __user pointers.
So, the usage of "kp" is really misleading there. So, rename
both to just "p32" and "p64" everywhere it occurs, in order to
make peace with this file's namespace.
There are two exceptions to "up/kp" nomenclature: at
alloc_userspace() and at do_video_ioctl().
There, a new userspace pointer were allocated, in order to store
the 64 bits version of the ioctl. Those were called as "up_native",
with is, IMHO, an even worse name, as "native" could mislead of
being the arguments that were filled from userspace. I almost
renamed it to just "p64", but, after thinking more about that,
it sounded better to call it as "new_p64", as this makes clearer
that this is the data structure that was allocated inside this
file in order to be used to pass/retrieve data when calling the
64-bit ready file->f_op->unlocked_ioctl() function.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Suggested-by: Hans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2018-04-16 14:58:18 +00:00
|
|
|
struct v4l2_edid32 __user *p32)
|
2012-08-10 09:07:12 +00:00
|
|
|
{
|
2020-10-30 16:55:28 +00:00
|
|
|
if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
|
2018-01-24 09:35:48 +00:00
|
|
|
return -EFAULT;
|
2012-08-10 09:07:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-19 16:28:07 +00:00
|
|
|
/*
|
|
|
|
* List of ioctls that require 32-bits/64-bits conversion
|
|
|
|
*
|
|
|
|
* The V4L2 ioctls that aren't listed there don't have pointer arguments
|
|
|
|
* and the struct size is identical for both 32 and 64 bits versions, so
|
|
|
|
* they don't need translations.
|
|
|
|
*/
|
2012-08-10 09:07:12 +00:00
|
|
|
|
2008-12-21 13:35:25 +00:00
|
|
|
#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_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_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
|
|
|
|
#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
|
|
|
|
#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
|
2014-03-07 10:18:37 +00:00
|
|
|
#define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
|
|
|
|
#define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
|
2018-01-04 18:08:56 +00:00
|
|
|
#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
|
2008-12-21 13:35:25 +00:00
|
|
|
#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
|
|
|
|
#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
|
|
|
|
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
|
2011-06-07 14:43:57 +00:00
|
|
|
#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
|
2011-09-28 14:34:06 +00:00
|
|
|
#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
|
|
|
|
#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
|
2020-11-09 08:47:44 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
#define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32)
|
|
|
|
#define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32)
|
|
|
|
#define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32)
|
|
|
|
#define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32)
|
|
|
|
#define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32)
|
|
|
|
#endif
|
2008-12-21 13:35:25 +00:00
|
|
|
|
2020-10-30 16:55:22 +00:00
|
|
|
unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_G_FMT32:
|
|
|
|
return VIDIOC_G_FMT;
|
|
|
|
case VIDIOC_S_FMT32:
|
|
|
|
return VIDIOC_S_FMT;
|
|
|
|
case VIDIOC_TRY_FMT32:
|
|
|
|
return VIDIOC_TRY_FMT;
|
2020-10-30 16:55:28 +00:00
|
|
|
case VIDIOC_G_FBUF32:
|
|
|
|
return VIDIOC_G_FBUF;
|
|
|
|
case VIDIOC_S_FBUF32:
|
|
|
|
return VIDIOC_S_FBUF;
|
2020-10-30 16:55:25 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
case VIDIOC_QUERYBUF32_TIME32:
|
|
|
|
return VIDIOC_QUERYBUF;
|
|
|
|
case VIDIOC_QBUF32_TIME32:
|
|
|
|
return VIDIOC_QBUF;
|
|
|
|
case VIDIOC_DQBUF32_TIME32:
|
|
|
|
return VIDIOC_DQBUF;
|
|
|
|
case VIDIOC_PREPARE_BUF32_TIME32:
|
|
|
|
return VIDIOC_PREPARE_BUF;
|
|
|
|
#endif
|
|
|
|
case VIDIOC_QUERYBUF32:
|
|
|
|
return VIDIOC_QUERYBUF;
|
|
|
|
case VIDIOC_QBUF32:
|
|
|
|
return VIDIOC_QBUF;
|
|
|
|
case VIDIOC_DQBUF32:
|
|
|
|
return VIDIOC_DQBUF;
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_CREATE_BUFS32:
|
|
|
|
return VIDIOC_CREATE_BUFS;
|
2020-10-30 16:55:24 +00:00
|
|
|
case VIDIOC_G_EXT_CTRLS32:
|
|
|
|
return VIDIOC_G_EXT_CTRLS;
|
|
|
|
case VIDIOC_S_EXT_CTRLS32:
|
|
|
|
return VIDIOC_S_EXT_CTRLS;
|
|
|
|
case VIDIOC_TRY_EXT_CTRLS32:
|
|
|
|
return VIDIOC_TRY_EXT_CTRLS;
|
2020-10-30 16:55:25 +00:00
|
|
|
case VIDIOC_PREPARE_BUF32:
|
|
|
|
return VIDIOC_PREPARE_BUF;
|
2020-10-30 16:55:28 +00:00
|
|
|
case VIDIOC_ENUMSTD32:
|
|
|
|
return VIDIOC_ENUMSTD;
|
|
|
|
case VIDIOC_ENUMINPUT32:
|
|
|
|
return VIDIOC_ENUMINPUT;
|
|
|
|
case VIDIOC_G_EDID32:
|
|
|
|
return VIDIOC_G_EDID;
|
|
|
|
case VIDIOC_S_EDID32:
|
|
|
|
return VIDIOC_S_EDID;
|
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
case VIDIOC_DQEVENT32:
|
|
|
|
return VIDIOC_DQEVENT;
|
2021-10-26 05:49:54 +00:00
|
|
|
#endif
|
2020-10-30 16:55:28 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
case VIDIOC_DQEVENT32_TIME32:
|
|
|
|
return VIDIOC_DQEVENT;
|
|
|
|
#endif
|
2020-10-30 16:55:22 +00:00
|
|
|
}
|
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_G_FMT32:
|
|
|
|
case VIDIOC_S_FMT32:
|
|
|
|
case VIDIOC_TRY_FMT32:
|
|
|
|
return get_v4l2_format32(parg, arg);
|
2020-10-30 16:55:28 +00:00
|
|
|
|
|
|
|
case VIDIOC_S_FBUF32:
|
|
|
|
return get_v4l2_framebuffer32(parg, arg);
|
2020-10-30 16:55:25 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
case VIDIOC_QUERYBUF32_TIME32:
|
|
|
|
case VIDIOC_QBUF32_TIME32:
|
|
|
|
case VIDIOC_DQBUF32_TIME32:
|
|
|
|
case VIDIOC_PREPARE_BUF32_TIME32:
|
|
|
|
return get_v4l2_buffer32_time32(parg, arg);
|
|
|
|
#endif
|
|
|
|
case VIDIOC_QUERYBUF32:
|
|
|
|
case VIDIOC_QBUF32:
|
|
|
|
case VIDIOC_DQBUF32:
|
|
|
|
case VIDIOC_PREPARE_BUF32:
|
|
|
|
return get_v4l2_buffer32(parg, arg);
|
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
case VIDIOC_G_EXT_CTRLS32:
|
|
|
|
case VIDIOC_S_EXT_CTRLS32:
|
|
|
|
case VIDIOC_TRY_EXT_CTRLS32:
|
|
|
|
return get_v4l2_ext_controls32(parg, arg);
|
2020-10-30 16:55:27 +00:00
|
|
|
|
|
|
|
case VIDIOC_CREATE_BUFS32:
|
|
|
|
return get_v4l2_create32(parg, arg);
|
2020-10-30 16:55:28 +00:00
|
|
|
|
|
|
|
case VIDIOC_ENUMSTD32:
|
|
|
|
return get_v4l2_standard32(parg, arg);
|
|
|
|
|
|
|
|
case VIDIOC_ENUMINPUT32:
|
|
|
|
return get_v4l2_input32(parg, arg);
|
|
|
|
|
|
|
|
case VIDIOC_G_EDID32:
|
|
|
|
case VIDIOC_S_EDID32:
|
|
|
|
return get_v4l2_edid32(parg, arg);
|
2020-10-30 16:55:22 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_G_FMT32:
|
|
|
|
case VIDIOC_S_FMT32:
|
|
|
|
case VIDIOC_TRY_FMT32:
|
|
|
|
return put_v4l2_format32(parg, arg);
|
2020-10-30 16:55:28 +00:00
|
|
|
|
|
|
|
case VIDIOC_G_FBUF32:
|
|
|
|
return put_v4l2_framebuffer32(parg, arg);
|
2020-10-30 16:55:25 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
case VIDIOC_QUERYBUF32_TIME32:
|
|
|
|
case VIDIOC_QBUF32_TIME32:
|
|
|
|
case VIDIOC_DQBUF32_TIME32:
|
|
|
|
case VIDIOC_PREPARE_BUF32_TIME32:
|
|
|
|
return put_v4l2_buffer32_time32(parg, arg);
|
|
|
|
#endif
|
|
|
|
case VIDIOC_QUERYBUF32:
|
|
|
|
case VIDIOC_QBUF32:
|
|
|
|
case VIDIOC_DQBUF32:
|
|
|
|
case VIDIOC_PREPARE_BUF32:
|
|
|
|
return put_v4l2_buffer32(parg, arg);
|
|
|
|
|
2020-10-30 16:55:24 +00:00
|
|
|
case VIDIOC_G_EXT_CTRLS32:
|
|
|
|
case VIDIOC_S_EXT_CTRLS32:
|
|
|
|
case VIDIOC_TRY_EXT_CTRLS32:
|
|
|
|
return put_v4l2_ext_controls32(parg, arg);
|
2020-10-30 16:55:27 +00:00
|
|
|
|
|
|
|
case VIDIOC_CREATE_BUFS32:
|
|
|
|
return put_v4l2_create32(parg, arg);
|
2020-10-30 16:55:28 +00:00
|
|
|
|
|
|
|
case VIDIOC_ENUMSTD32:
|
|
|
|
return put_v4l2_standard32(parg, arg);
|
|
|
|
|
|
|
|
case VIDIOC_ENUMINPUT32:
|
|
|
|
return put_v4l2_input32(parg, arg);
|
|
|
|
|
|
|
|
case VIDIOC_G_EDID32:
|
|
|
|
case VIDIOC_S_EDID32:
|
|
|
|
return put_v4l2_edid32(parg, arg);
|
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
case VIDIOC_DQEVENT32:
|
|
|
|
return put_v4l2_event32(parg, arg);
|
2021-10-26 05:49:54 +00:00
|
|
|
#endif
|
2020-10-30 16:55:28 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
|
|
|
case VIDIOC_DQEVENT32_TIME32:
|
|
|
|
return put_v4l2_event32_time32(parg, arg);
|
|
|
|
#endif
|
2020-10-30 16:55:22 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v4l2_compat_get_array_args(struct file *file, void *mbuf,
|
|
|
|
void __user *user_ptr, size_t array_size,
|
|
|
|
unsigned int cmd, void *arg)
|
|
|
|
{
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
switch (cmd) {
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_G_FMT32:
|
|
|
|
case VIDIOC_S_FMT32:
|
|
|
|
case VIDIOC_TRY_FMT32: {
|
|
|
|
struct v4l2_format *f64 = arg;
|
|
|
|
struct v4l2_clip *c64 = mbuf;
|
|
|
|
struct v4l2_clip32 __user *c32 = user_ptr;
|
|
|
|
u32 clipcount = f64->fmt.win.clipcount;
|
|
|
|
|
|
|
|
if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
|
|
|
|
f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
|
|
|
|
clipcount == 0)
|
|
|
|
return 0;
|
|
|
|
if (clipcount > 2048)
|
|
|
|
return -EINVAL;
|
|
|
|
while (clipcount--) {
|
|
|
|
if (copy_from_user(c64, c32, sizeof(c64->c)))
|
|
|
|
return -EFAULT;
|
|
|
|
c64->next = NULL;
|
|
|
|
c64++;
|
|
|
|
c32++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-11-09 08:47:44 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
2020-10-30 16:55:25 +00:00
|
|
|
case VIDIOC_QUERYBUF32_TIME32:
|
|
|
|
case VIDIOC_QBUF32_TIME32:
|
|
|
|
case VIDIOC_DQBUF32_TIME32:
|
|
|
|
case VIDIOC_PREPARE_BUF32_TIME32:
|
2020-11-09 08:47:44 +00:00
|
|
|
#endif
|
2020-10-30 16:55:25 +00:00
|
|
|
case VIDIOC_QUERYBUF32:
|
|
|
|
case VIDIOC_QBUF32:
|
|
|
|
case VIDIOC_DQBUF32:
|
|
|
|
case VIDIOC_PREPARE_BUF32: {
|
|
|
|
struct v4l2_buffer *b64 = arg;
|
|
|
|
struct v4l2_plane *p64 = mbuf;
|
|
|
|
struct v4l2_plane32 __user *p32 = user_ptr;
|
|
|
|
|
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
|
|
|
|
u32 num_planes = b64->length;
|
|
|
|
|
|
|
|
if (num_planes == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (num_planes--) {
|
|
|
|
err = get_v4l2_plane32(p64, p32, b64->memory);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
++p64;
|
|
|
|
++p32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-10-30 16:55:24 +00:00
|
|
|
case VIDIOC_G_EXT_CTRLS32:
|
|
|
|
case VIDIOC_S_EXT_CTRLS32:
|
|
|
|
case VIDIOC_TRY_EXT_CTRLS32: {
|
|
|
|
struct v4l2_ext_controls *ecs64 = arg;
|
|
|
|
struct v4l2_ext_control *ec64 = mbuf;
|
|
|
|
struct v4l2_ext_control32 __user *ec32 = user_ptr;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
for (n = 0; n < ecs64->count; n++) {
|
|
|
|
if (copy_from_user(ec64, ec32, sizeof(*ec32)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
if (ctrl_is_pointer(file, ec64->id)) {
|
|
|
|
compat_uptr_t p;
|
|
|
|
|
|
|
|
if (get_user(p, &ec32->string))
|
|
|
|
return -EFAULT;
|
|
|
|
ec64->string = compat_ptr(p);
|
|
|
|
}
|
|
|
|
ec32++;
|
|
|
|
ec64++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-10-30 16:55:22 +00:00
|
|
|
default:
|
|
|
|
if (copy_from_user(mbuf, user_ptr, array_size))
|
|
|
|
err = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
|
|
|
|
void *mbuf, size_t array_size,
|
|
|
|
unsigned int cmd, void *arg)
|
|
|
|
{
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
switch (cmd) {
|
2020-10-30 16:55:27 +00:00
|
|
|
case VIDIOC_G_FMT32:
|
|
|
|
case VIDIOC_S_FMT32:
|
|
|
|
case VIDIOC_TRY_FMT32: {
|
|
|
|
struct v4l2_format *f64 = arg;
|
|
|
|
struct v4l2_clip *c64 = mbuf;
|
|
|
|
struct v4l2_clip32 __user *c32 = user_ptr;
|
|
|
|
u32 clipcount = f64->fmt.win.clipcount;
|
|
|
|
|
|
|
|
if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
|
|
|
|
f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
|
|
|
|
clipcount == 0)
|
|
|
|
return 0;
|
|
|
|
if (clipcount > 2048)
|
|
|
|
return -EINVAL;
|
|
|
|
while (clipcount--) {
|
|
|
|
if (copy_to_user(c32, c64, sizeof(c64->c)))
|
|
|
|
return -EFAULT;
|
|
|
|
c64++;
|
|
|
|
c32++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-11-09 08:47:44 +00:00
|
|
|
#ifdef CONFIG_COMPAT_32BIT_TIME
|
2020-10-30 16:55:25 +00:00
|
|
|
case VIDIOC_QUERYBUF32_TIME32:
|
|
|
|
case VIDIOC_QBUF32_TIME32:
|
|
|
|
case VIDIOC_DQBUF32_TIME32:
|
|
|
|
case VIDIOC_PREPARE_BUF32_TIME32:
|
2020-11-09 08:47:44 +00:00
|
|
|
#endif
|
2020-10-30 16:55:25 +00:00
|
|
|
case VIDIOC_QUERYBUF32:
|
|
|
|
case VIDIOC_QBUF32:
|
|
|
|
case VIDIOC_DQBUF32:
|
|
|
|
case VIDIOC_PREPARE_BUF32: {
|
|
|
|
struct v4l2_buffer *b64 = arg;
|
|
|
|
struct v4l2_plane *p64 = mbuf;
|
|
|
|
struct v4l2_plane32 __user *p32 = user_ptr;
|
|
|
|
|
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
|
|
|
|
u32 num_planes = b64->length;
|
|
|
|
|
|
|
|
if (num_planes == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (num_planes--) {
|
|
|
|
err = put_v4l2_plane32(p64, p32, b64->memory);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
++p64;
|
|
|
|
++p32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-10-30 16:55:24 +00:00
|
|
|
case VIDIOC_G_EXT_CTRLS32:
|
|
|
|
case VIDIOC_S_EXT_CTRLS32:
|
|
|
|
case VIDIOC_TRY_EXT_CTRLS32: {
|
|
|
|
struct v4l2_ext_controls *ecs64 = arg;
|
|
|
|
struct v4l2_ext_control *ec64 = mbuf;
|
|
|
|
struct v4l2_ext_control32 __user *ec32 = user_ptr;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
for (n = 0; n < ecs64->count; n++) {
|
|
|
|
unsigned int size = sizeof(*ec32);
|
|
|
|
/*
|
|
|
|
* Do not modify the pointer when copying a pointer
|
|
|
|
* control. The contents of the pointer was changed,
|
|
|
|
* not the pointer itself.
|
|
|
|
* The structures are otherwise compatible.
|
|
|
|
*/
|
|
|
|
if (ctrl_is_pointer(file, ec64->id))
|
|
|
|
size -= sizeof(ec32->value64);
|
|
|
|
|
|
|
|
if (copy_to_user(ec32, ec64, size))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
ec32++;
|
|
|
|
ec64++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-10-30 16:55:22 +00:00
|
|
|
default:
|
|
|
|
if (copy_to_user(user_ptr, mbuf, array_size))
|
|
|
|
err = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-04-19 16:28:07 +00:00
|
|
|
/**
|
|
|
|
* v4l2_compat_ioctl32() - Handles a compat32 ioctl call
|
|
|
|
*
|
|
|
|
* @file: pointer to &struct file with the file handler
|
|
|
|
* @cmd: ioctl to be called
|
|
|
|
* @arg: arguments passed from/to the ioctl handler
|
|
|
|
*
|
|
|
|
* This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
|
|
|
|
* in order to deal with 32-bit calls on a 64-bits Kernel.
|
|
|
|
*
|
|
|
|
* This function calls do_video_ioctl() for non-private V4L2 ioctls.
|
|
|
|
* If the function is a private one it calls vdev->fops->compat_ioctl32
|
|
|
|
* instead.
|
|
|
|
*/
|
2008-12-30 09:42:40 +00:00
|
|
|
long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
|
2006-01-09 17:24:57 +00:00
|
|
|
{
|
2011-12-18 23:41:19 +00:00
|
|
|
struct video_device *vdev = video_devdata(file);
|
2008-12-30 10:04:34 +00:00
|
|
|
long ret = -ENOIOCTLCMD;
|
2006-01-09 17:24:57 +00:00
|
|
|
|
2010-08-13 20:29:03 +00:00
|
|
|
if (!file->f_op->unlocked_ioctl)
|
2006-01-09 17:24:57 +00:00
|
|
|
return ret;
|
|
|
|
|
2021-06-14 10:34:06 +00:00
|
|
|
if (!video_is_registered(vdev))
|
|
|
|
return -ENODEV;
|
|
|
|
|
2014-02-10 11:08:44 +00:00
|
|
|
if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
|
2020-10-30 16:55:29 +00:00
|
|
|
ret = file->f_op->unlocked_ioctl(file, cmd,
|
|
|
|
(unsigned long)compat_ptr(arg));
|
2014-02-10 11:08:44 +00:00
|
|
|
else if (vdev->fops->compat_ioctl32)
|
|
|
|
ret = vdev->fops->compat_ioctl32(file, cmd, arg);
|
2006-01-09 17:24:57 +00:00
|
|
|
|
2014-02-10 11:08:44 +00:00
|
|
|
if (ret == -ENOIOCTLCMD)
|
2015-09-09 06:40:39 +00:00
|
|
|
pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
|
|
|
|
_IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
|
2006-01-09 17:24:59 +00:00
|
|
|
return ret;
|
2006-01-09 17:24:57 +00:00
|
|
|
}
|
2008-12-30 09:42:40 +00:00
|
|
|
EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
|