[PATCH for v4.4 00/14] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 4.4, the vivid driver (since that
emulates almost all V4L2 ioctls that need to pass through v4l2-compat-ioctl32.c)
and a 32-bit v4l2-compliance utility since that exercises almost all ioctls
as well. Combined this gives good test coverage.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other known bugs, and 2) keep the final patch at least
somewhat readable.

Regards,

Hans

Daniel Mentz (2):
  media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (11):
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors

Ricardo Ribalda Delgado (1):
  vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1023 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c  |5 +-
 drivers/media/v4l2-core/videobuf2-v4l2.c  |6 +
 3 files changed, 624 insertions(+), 410 deletions(-)

-- 
2.15.1



[PATCH for v4.4 14/14] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.

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, >clipcount) ||
put_user(clipcount, >clipcount)) return -EFAULT;

Notes from hans.verk...@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 
Co-developed-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 744 +-
 1 file changed, 483 insertions(+), 261 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 4b6ea1b20d2a..943f90e392a7 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -22,6 +22,14 @@
 #include 
 #include 
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)   \
+({ \
+   typeof(*from) __assign_tmp; \
+   \
+   get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
 {
long ret = -ENOIOCTLCMD;
@@ -35,12 +43,12 @@ static long native_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
 
 struct v4l2_clip32 {
struct v4l2_rectc;
-   compat_caddr_t  next;
+   compat_caddr_t  next;
 };
 
 struct v4l2_window32 {
struct v4l2_rectw;
-   __u32   field;  /* enum v4l2_field */
+   __u32   field;  /* enum v4l2_field */
__u32   chromakey;
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
@@ -48,37 +56,41 @@ struct v4l2_window32 {
__u8global_alpha;
 };
 
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+struct v4l2_window32 __user *up,
+void __user *aux_buf, u32 aux_space)
 {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user 

[PATCH for v4.4 10/14] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.

Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
overlays.") added the field global_alpha to struct v4l2_window but did
not update the compat layer accordingly. This change adds global_alpha
to struct v4l2_window32 and copies the value for global_alpha back and
forth.

Signed-off-by: Daniel Mentz 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 0c3949a00570..e55231a12f00 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,6 +45,7 @@ struct v4l2_window32 {
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
compat_caddr_t  bitmap;
+   __u8global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
@@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
@@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
return 0;
 }
-- 
2.15.1



[PATCH for v4.4 13/14] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.

Some ioctls need to copy back the result even if the ioctl returned
an error. However, don't do this for the error code -ENOTTY.
It makes no sense in that cases.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index c8635e4f91ef..4b6ea1b20d2a 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -956,6 +956,9 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
set_fs(old_fs);
}
 
+   if (err == -ENOTTY)
+   return err;
+
/* Special case: even after an error we need to put the
   results back for these ioctls since the error_idx will
   contain information on which control failed. */
-- 
2.15.1



[PATCH for v4.4 02/14] vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

2018-02-14 Thread Hans Verkuil
From: Ricardo Ribalda 

commit 3171cc2b4eb9831ab4df1d80d0410a945b8bc84e upstream.

According to the doc, V4L2_BUF_FLAG_DONE is cleared after DQBUF:

V4L2_BUF_FLAG_DONE 0x0004  ... After calling the VIDIOC_QBUF or
VIDIOC_DQBUF it is always cleared ...

Unfortunately, it seems that videobuf2 keeps it set after DQBUF. This
can be tested with vivid and dev_debug:

[257604.338082] video1: VIDIOC_DQBUF: 71:33:25.00260479 index=3,
type=vid-cap, flags=0x2004, field=none, sequence=163,
memory=userptr, bytesused=460800, offset/userptr=0x344b000,
length=460800

This patch forces FLAG_DONE to 0 after calling DQBUF.

Reported-by: Dimitrios Katsaros 
Signed-off-by: Ricardo Ribalda Delgado 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 6c441be8f893..bf23234d957e 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -593,6 +593,12 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct 
v4l2_buffer *b,
b->flags & V4L2_BUF_FLAG_LAST)
q->last_buffer_dequeued = true;
 
+   /*
+*  After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
+*  cleared.
+*/
+   b->flags &= ~V4L2_BUF_FLAG_DONE;
+
return ret;
 }
 
-- 
2.15.1



[PATCH for v4.4 07/14] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 ---
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index ace1d7b050a5..af197980ab8e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -299,19 +299,24 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else if (memory == V4L2_MEMORY_DMABUF) {
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd, sizeof(up32->m.fd)))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -320,22 +325,32 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 
__user *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
-   /* For DMABUF, driver might've set up the fd, so copy it back. */
-   if (memory == V4L2_MEMORY_DMABUF)
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd,
 sizeof(up->m.fd)))
return -EFAULT;
+   break;
+   }
 
return 0;
 }
@@ -395,6 +410,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (get_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -408,10 +424,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
-   case V4L2_MEMORY_OVERLAY:
-   if (get_user(kp->m.offset, >m.offset))
-   return -EFAULT;
-   break;
case V4L2_MEMORY_DMABUF:
if (get_user(kp->m.fd, >m.fd))
return -EFAULT;
@@ -468,6 +480,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (put_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -475,10 +488,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user

[PATCH for v4.4 06/14] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 77 +--
 1 file changed, 36 insertions(+), 41 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 5ebc11476f63..ace1d7b050a5 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -47,7 +47,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -157,14 +157,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -208,14 +208,14 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format)) ||
copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
@@ -234,7 +234,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -242,13 +242,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -296,7 +296,7 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 
if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
-   

[PATCH for v4.4 05/14] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 104 +-
 1 file changed, 20 insertions(+), 84 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index c849b67b98df..5ebc11476f63 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -89,78 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
__u32   type;   /* enum v4l2_buf_type */
union {
@@ -199,23 +127,27 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   return copy_from_user(>fmt.vbi, >fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-   return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
+   return copy_from_user(>fmt.sliced, >fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
case 

[PATCH for v4.4 03/14] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 4379b949bb93..f47a30b89281 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1022,6 +1022,7 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v4.4 12/14] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 84fb4c54b101..c8635e4f91ef 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -175,8 +175,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_from_user(>fmt.sdr, >fmt.sdr,
  sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
@@ -226,8 +224,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_to_user(>fmt.sdr, >fmt.sdr,
sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



[PATCH for v4.4 11/14] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 ++-
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index e55231a12f00..84fb4c54b101 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -50,6 +50,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v4.4 04/14] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 208 +-
 1 file changed, 104 insertions(+), 104 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f47a30b89281..c849b67b98df 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -48,11 +48,11 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount))
+   return -EFAULT;
return 0;
 }
 
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format 
*kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -218,7 +218,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return get_v4l2_sdr_format(>fmt.sdr, >fmt.sdr);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -265,7 +265,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return put_v4l2_sdr_format(>fmt.sdr, >fmt.sdr);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -299,7 +299,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-   get_user(kp->index, >index))
+   get_user(kp->index, >index))
return -EFAULT;
return 0;
 }
@@ -307,13 +307,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-   put_user(kp->index, >index) ||
-   put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
-   copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
-   put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
-   return 

[PATCH for v4.4 01/14] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 7486af2c8ae4..5e2a7e59f578 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2783,8 +2783,11 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+   goto out;
+   }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
-- 
2.15.1



[PATCH for v3.2 08/12] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.

Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
overlays.") added the field global_alpha to struct v4l2_window but did
not update the compat layer accordingly. This change adds global_alpha
to struct v4l2_window32 and copies the value for global_alpha back and
forth.

Signed-off-by: Daniel Mentz 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 925271c25177..a7b71a256d56 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -46,6 +46,7 @@ struct v4l2_window32 {
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
compat_caddr_t  bitmap;
+   __u8global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
@@ -54,7 +55,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
@@ -87,7 +89,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
return 0;
 }
-- 
2.15.1



[PATCH for v3.2 04/12] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 94 +++
 1 file changed, 21 insertions(+), 73 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index e35142d9781b..4d0901573860 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -89,64 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
enum v4l2_buf_type type;
union {
@@ -184,20 +126,23 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-   return get_v4l2_window32(>fmt.win, >fmt.win);
+   return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   return copy_from_user(>fmt.vbi, >fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-   return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
+   return copy_from_user(>fmt.sliced, >fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_PRIVATE:
if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
return -EFAULT;
@@ -229,20 +174,23 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return put_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return 

[PATCH for v3.2 12/12] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.

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, >clipcount) ||
put_user(clipcount, >clipcount)) return -EFAULT;

Notes from hans.verk...@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 
Co-developed-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/Makefile  |   7 +-
 drivers/media/video/v4l2-compat-ioctl32.c | 738 +++---
 2 files changed, 481 insertions(+), 264 deletions(-)

diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 117f9c4b4cb9..aa1e164cfb87 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -13,12 +13,13 @@ omap2cam-objs   :=  omap24xxcam.o omap24xxcam-dma.o
 videodev-objs  :=  v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
 
+ifeq ($(CONFIG_COMPAT),y)
+  videodev-objs += v4l2-compat-ioctl32.o
+endif
+
 # V4L2 core modules
 
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
-ifeq ($(CONFIG_COMPAT),y)
-  obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
-endif
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
 
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 7f0eeb8a4d3f..b4f19238c746 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -23,6 +23,14 @@
 
 #ifdef CONFIG_COMPAT
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)   \
+({ \
+   typeof(*from) __assign_tmp; \
+   \
+   get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
 {
long ret = -ENOIOCTLCMD;
@@ -36,12 +44,12 @@ static long native_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
 
 struct v4l2_clip32 {
struct v4l2_rectc;
-   compat_caddr_t  next;
+   compat_caddr_t  next;
 };
 
 struct v4l2_window32 {
struct v4l2_rectw;

[PATCH for v3.2 03/12] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 198 +++---
 1 file changed, 99 insertions(+), 99 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 9c4a7c7d3534..e35142d9781b 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -48,11 +48,11 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount))
+   return -EFAULT;
return 0;
 }
 
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format 
*kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -204,7 +204,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return 0;
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -249,7 +249,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return 0;
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -257,7 +257,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-   put_user(kp->type, >type))
+   put_user(kp->type, >type))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
@@ -266,7 +266,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers 
*kp, struct v4l2_create_
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format.fmt)))
-   return -EFAULT;
+   return -EFAULT;
return __put_v4l2_format32(>format, >format);
 }
 
@@ -283,7 +283,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-   get_user(kp->index, >index))
+   

[PATCH for v3.2 02/12] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 2671959f01bb..9c4a7c7d3534 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -920,6 +920,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v3.2 06/12] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 30 ++
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index e2dee29eaaa5..7477feff92b1 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -293,16 +293,20 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -311,17 +315,27 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   }
 
return 0;
 }
-- 
2.15.1



[PATCH for v3.2 07/12] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 51 +++
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 7477feff92b1..925271c25177 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -17,6 +17,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #ifdef CONFIG_COMPAT
 
@@ -568,24 +571,32 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   struct video_device *vdev = video_devdata(file);
+   struct v4l2_fh *fh = NULL;
+   struct v4l2_ctrl_handler *hdl = NULL;
+
+   if (test_bit(V4L2_FL_USES_V4L2_FH, >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->type == V4L2_CTRL_TYPE_STRING;
}
+   return false;
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -613,7 +624,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
while (--n >= 0) {
if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
return -EFAULT;
-   if (ctrl_is_pointer(kcontrols->id)) {
+   if (ctrl_is_pointer(file, kcontrols->id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -628,7 +639,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols = kp->controls;
@@ -656,7 +669,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(kcontrols->id))
+   if (ctrl_is_pointer(file, kcontrols->id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -819,7 +832,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);
compatible_arg = 0;
break;
case VIDIOC_DQEVENT:
@@ -846,7 +859,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:

[PATCH for v3.2 09/12] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 59 +--
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index a7b71a256d56..6c3e15f7703e 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -51,6 +51,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -60,38 +65,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v3.2 00/12] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 3.2, the vivi driver (a poor substitute for
the much improved vivid driver that's available in later kernels, but it's the
best I had) since that emulates the more common V4L2 ioctls that need to pass
through v4l2-compat-ioctl32.c) and the 32-bit v4l2-compliance + 32-bit v4l2-ctl
utilities that together exercised the most common ioctls.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other known bugs, and 2) keep the final patch at least
somewhat readable.

Regards,

Hans

Daniel Mentz (2):
  media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (10):
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors

 drivers/media/video/Makefile  |   7 +-
 drivers/media/video/v4l2-compat-ioctl32.c | 966 ++
 drivers/media/video/v4l2-ioctl.c  |   6 +-
 3 files changed, 597 insertions(+), 382 deletions(-)

-- 
2.15.1



[PATCH for v3.2 11/12] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.

Some ioctls need to copy back the result even if the ioctl returned
an error. However, don't do this for the error code -ENOTTY.
It makes no sense in that cases.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 44e8a8d15558..7f0eeb8a4d3f 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -872,6 +872,9 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
set_fs(old_fs);
}
 
+   if (err == -ENOTTY)
+   return err;
+
/* Special case: even after an error we need to put the
   results back for these ioctls since the error_idx will
   contain information on which control failed. */
-- 
2.15.1



[PATCH for v3.2 10/12] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 6c3e15f7703e..44e8a8d15558 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -175,8 +175,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return -EFAULT;
return 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
@@ -223,8 +221,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return -EFAULT;
return 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



Re: exposing a large-ish calibration table through V4L2?

2018-02-14 Thread Hans Verkuil
Hi Florian,

On 14/02/18 13:09, Florian Echtler wrote:
> Hello Hans,
> 
> I've picked up work on the sur40 driver again recently. There is one major
> feature left that is currently unsupported by the Linux driver, which is the
> hardware-based calibration.
> 
> The internal device memory contains a table with two bytes for each sensor 
> pixel
> (i.e. 960x540x2 = 1036800 bytes) that basically provide individual black and
> white levels per-pixel that are used in preprocessing. The table can either be
> set externally, or the sensor can be covered with a black/white surface and a
> custom command triggers an internal calibration.
> 
> AFAICT the usual V4L2 controls are unsuitable for this sort of data; do you 
> have
> any suggestions on how to approach this? Maybe something like a custom IOCTL?

So the table has a fixed size?

You can use array controls for that, a V4L2_CTRL_TYPE_U16 in a two-dimensional 
array
would do it.

See https://hverkuil.home.xs4all.nl/spec/uapi/v4l/vidioc-queryctrl.html for more
information on how this works.

Regards,

Hans


media: v4l: alsa: Associating V4L2 and ALSA devices coming from the same device (a webcam for example)

2018-02-14 Thread Carlos Rafael Giani
I have an application that allows for recording audio/video from input 
devices. I now want to add to it the ability to autodetect plugged-in 
USB webcams via udev. The problem is that audio and video are handled 
separately, by a video4linux and an ALSA device. The goal is to discover 
the ALSA device name and the Video4Linux device node that are associated 
(that is, belonging to the same camera input feed).


Surprisingly, there does not seem to be any interface in V4L2 for this, 
so I had to resort to looking at the udev properties. I came up with a 
very dirty hack that accomplishes what I want. I pasted it below.


This code relies on the ID_USB_INTERFACES property to associate the V4L2 
and ALSA devices, which may or may not be fragile. Furthermore, it 
traverses directories in /sys/ . I use libgudev here.


I now ask the mailing list if there is an easier way to do this. Note 
that I cannot rely on tools like the gst device monitor. It would also 
be preferable to not have to rely on specific udev rules, though I will 
add them if it is truly necessary.


Also, I found it difficult to get a meaningful label that I can present 
the user. The V4L2 properties produced fairly useless labels (something 
like "UVC camera (:)"). What produced the best results was the 
ID_MODEL_FROM_DATABASE - but this is a property of the ALSA devices.


So, anybody has a better idea how to accomplish this?


The hacky code:

    std::regex 
sndcard_regex(".*/sound/card[[:digit:]]+/controlC[[:digit:]]+$");

    std::regex pcmc_regex("pcmC([[:digit:]]+)D([[:digit:]]+)c");

    void process_added_device(GUdevDevice *p_added_device)
    {
        gchar const *bus_cstr = 
g_udev_device_get_property(p_added_device, "ID_BUS");

        if (g_strcmp0(bus_cstr, "usb") != 0)
            return;

        gchar const *path_cstr = 
g_udev_device_get_sysfs_path(p_added_device);
        gchar const *subsystem_cstr = 
g_udev_device_get_property(p_added_device, "SUBSYSTEM");
        gchar const *usb_interfaces_cstr = 
g_udev_device_get_property(p_added_device, "ID_USB_INTERFACES");


        std::string id = std::string("usbif_") + usb_interfaces_cstr;

        capture_device new_capture_device;
        new_capture_device.m_is_hdmi_device = false;
        new_capture_device.m_label = id; // initially use the ID as 
label, as fallback if no other label can be found

        new_capture_device.m_id = id;

        auto _view = m_entries.get < id_tag > ();
        auto iter = id_view.find(id);
        if (iter != id_view.end()) // check if an entry exists already; 
if so, retrieve it

        {
            new_capture_device = *iter;
            // remove the device from the boost multi-index container. 
we'll reinsert a modified version later.

            id_view.erase(iter);
        }

        if (g_strcmp0(subsystem_cstr, "video4linux") == 0)
        {
            gchar const *devnode_cstr = 
g_udev_device_get_device_file(p_added_device);

            new_capture_device.m_v4l2_device = devnode_cstr;
        }
        else if (g_strcmp0(subsystem_cstr, "sound") == 0)
        {
            gchar const *model_from_db = 
g_udev_device_get_property(p_added_device, "ID_MODEL_FROM_DATABASE");

            if (model_from_db != nullptr)
                new_capture_device.m_label = model_from_db;

            std::smatch base_match;
            std::string path_str = path_cstr;
            if (std::regex_match(path_str, base_match, sndcard_regex)) 
// check if this sound device path is one to an ALSA control device

            {
                boost::filesystem::path path = path_str;
                path = path.parent_path();
                boost::system::error_code ec;
                boost::filesystem::directory_iterator dir_iter(path, ec);
                if (ec)
                    return;

                // search the parent directory for a PCM capture device
                boost::filesystem::directory_iterator end_dir_iter;
                for (; dir_iter != end_dir_iter; ++dir_iter)
                {
                    std::smatch pcm_match;
                    if 
(std::regex_match(dir_iter->path().filename().string(), pcm_match, 
pcmc_regex))
                        new_capture_device.m_alsa_device = 
std::string("plughw:") + std::string(pcm_match[1]) + "," + 
std::string(pcm_match[2]);

                }
            }
        }

        id_view.emplace(new_capture_device);
    }



[PATCH for v4.9 10/13] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 ++-
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index c32feb94b3e5..3b5f3c8956f2 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -50,6 +50,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v4.9 09/13] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.

Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
overlays.") added the field global_alpha to struct v4l2_window but did
not update the compat layer accordingly. This change adds global_alpha
to struct v4l2_window32 and copies the value for global_alpha back and
forth.

Signed-off-by: Daniel Mentz 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index da55322bbb0f..c32feb94b3e5 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,6 +45,7 @@ struct v4l2_window32 {
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
compat_caddr_t  bitmap;
+   __u8global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
@@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
@@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
return 0;
 }
-- 
2.15.1



[PATCH for v4.9 11/13] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 3b5f3c8956f2..75653d756dd9 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -175,8 +175,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_from_user(>fmt.sdr, >fmt.sdr,
  sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
@@ -226,8 +224,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_to_user(>fmt.sdr, >fmt.sdr,
sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



[PATCH for v4.9 06/13] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 ---
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 64e3977ab851..2ddeecdababe 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -299,19 +299,24 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else if (memory == V4L2_MEMORY_DMABUF) {
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd, sizeof(up32->m.fd)))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -320,22 +325,32 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 
__user *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
-   /* For DMABUF, driver might've set up the fd, so copy it back. */
-   if (memory == V4L2_MEMORY_DMABUF)
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd,
 sizeof(up->m.fd)))
return -EFAULT;
+   break;
+   }
 
return 0;
 }
@@ -395,6 +410,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (get_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -408,10 +424,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
-   case V4L2_MEMORY_OVERLAY:
-   if (get_user(kp->m.offset, >m.offset))
-   return -EFAULT;
-   break;
case V4L2_MEMORY_DMABUF:
if (get_user(kp->m.fd, >m.fd))
return -EFAULT;
@@ -468,6 +480,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (put_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -475,10 +488,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user

[PATCH for v4.9 05/13] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 77 +--
 1 file changed, 36 insertions(+), 41 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 64bc493edd7f..64e3977ab851 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -47,7 +47,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -157,14 +157,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -208,14 +208,14 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format)) ||
copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
@@ -234,7 +234,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -242,13 +242,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -296,7 +296,7 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 
if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
-   

[PATCH for v4.9 01/13] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index c52d94c018bb..4510e8a37244 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2862,8 +2862,11 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+   goto out;
+   }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
-- 
2.15.1



[PATCH for v4.9 07/13] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++-
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2ddeecdababe..c8dd39884f6e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
@@ -587,24 +589,39 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   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, >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;
}
+
+   if (!ops->vidioc_query_ext_ctrl)
+   return false;
+
+   return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
+   (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -636,7 +653,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return -EFAULT;
if (get_user(id, >id))
return -EFAULT;
-   if (ctrl_is_pointer(id)) {
+   if (ctrl_is_pointer(file, id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -651,7 +668,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols =
@@ -683,7 +702,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(id))
+   if (ctrl_is_pointer(file, id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -897,7 +916,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);

[PATCH for v4.9 03/13] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 208 +-
 1 file changed, 104 insertions(+), 104 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 049380bbf4cf..57211c7fc491 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -48,11 +48,11 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount))
+   return -EFAULT;
return 0;
 }
 
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format 
*kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -218,7 +218,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return get_v4l2_sdr_format(>fmt.sdr, >fmt.sdr);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -265,7 +265,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return put_v4l2_sdr_format(>fmt.sdr, >fmt.sdr);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -299,7 +299,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-   get_user(kp->index, >index))
+   get_user(kp->index, >index))
return -EFAULT;
return 0;
 }
@@ -307,13 +307,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-   put_user(kp->index, >index) ||
-   put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
-   copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
-   put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
-   return 

[PATCH for v4.9 04/13] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 104 +-
 1 file changed, 20 insertions(+), 84 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 57211c7fc491..64bc493edd7f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -89,78 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
__u32   type;   /* enum v4l2_buf_type */
union {
@@ -199,23 +127,27 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   return copy_from_user(>fmt.vbi, >fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-   return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
+   return copy_from_user(>fmt.sliced, >fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
case 

[PATCH for v4.9 02/13] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index dc51dd86377d..049380bbf4cf 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1022,6 +1022,7 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v4.9 00/13] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 4.9, the vivid driver (since that
emulates almost all V4L2 ioctls that need to pass through v4l2-compat-ioctl32.c)
and a 32-bit v4l2-compliance utility since that exercises almost all ioctls
as well. Combined this gives good test coverage.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other bugs, and 2) keep the final patch at least somewhat
readable.

Regards,

Hans


Daniel Mentz (2):
  media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (11):
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors

 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1023 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c  |5 +-
 2 files changed, 618 insertions(+), 410 deletions(-)

-- 
2.15.1



[PATCH for v4.9 08/13] media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream.

If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops
is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash.
Add a test for !ops to the condition.

All sub-devices that have controls will use the control framework,
so they do not have an equivalent to ops->vidioc_query_ext_ctrl.
Returning false if ops is NULL is the correct thing to do here.

Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer")

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reported-by: Laurent Pinchart 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index c8dd39884f6e..da55322bbb0f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -612,7 +612,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 
id)
return ctrl && ctrl->is_ptr;
}
 
-   if (!ops->vidioc_query_ext_ctrl)
+   if (!ops || !ops->vidioc_query_ext_ctrl)
return false;
 
return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
-- 
2.15.1



[PATCH for v3.16 13/14] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.

Some ioctls need to copy back the result even if the ioctl returned
an error. However, don't do this for the error code -ENOTTY.
It makes no sense in that cases.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2a03bd72cefc..64d1a2bddd5e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -921,6 +921,9 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
set_fs(old_fs);
}
 
+   if (err == -ENOTTY)
+   return err;
+
/* Special case: even after an error we need to put the
   results back for these ioctls since the error_idx will
   contain information on which control failed. */
-- 
2.15.1



[PATCH for v3.16 12/14] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index e7ebd20b6c6a..2a03bd72cefc 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -170,8 +170,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_from_user(>fmt.sliced, >fmt.sliced,
  sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
@@ -214,8 +212,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_to_user(>fmt.sliced, >fmt.sliced,
sizeof(kp->fmt.sliced)) ?  -EFAULT : 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



[PATCH for v3.16 11/14] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 ++-
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index de69afde9e86..e7ebd20b6c6a 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -50,6 +50,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v3.16 14/14] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.

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, >clipcount) ||
put_user(clipcount, >clipcount)) return -EFAULT;

Notes from hans.verk...@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 
Co-developed-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 780 +-
 1 file changed, 510 insertions(+), 270 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 64d1a2bddd5e..d35b67b37077 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -22,6 +22,14 @@
 #include 
 #include 
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)   \
+({ \
+   typeof(*from) __assign_tmp; \
+   \
+   get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
 {
long ret = -ENOIOCTLCMD;
@@ -35,12 +43,12 @@ static long native_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
 
 struct v4l2_clip32 {
struct v4l2_rectc;
-   compat_caddr_t  next;
+   compat_caddr_t  next;
 };
 
 struct v4l2_window32 {
struct v4l2_rectw;
-   __u32   field;  /* enum v4l2_field */
+   __u32   field;  /* enum v4l2_field */
__u32   chromakey;
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
@@ -48,37 +56,41 @@ struct v4l2_window32 {
__u8global_alpha;
 };
 
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+struct v4l2_window32 __user *up,
+void __user *aux_buf, u32 aux_space)
 {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user 

[PATCH for v3.16 09/14] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 50 +--
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 3a72a735a940..69d772d1237d 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
@@ -567,24 +569,32 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   struct video_device *vdev = video_devdata(file);
+   struct v4l2_fh *fh = NULL;
+   struct v4l2_ctrl_handler *hdl = NULL;
+
+   if (test_bit(V4L2_FL_USES_V4L2_FH, >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->type == V4L2_CTRL_TYPE_STRING;
}
+   return false;
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -612,7 +622,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
while (--n >= 0) {
if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
return -EFAULT;
-   if (ctrl_is_pointer(kcontrols->id)) {
+   if (ctrl_is_pointer(file, kcontrols->id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -627,7 +637,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols = kp->controls;
@@ -655,7 +667,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(kcontrols->id))
+   if (ctrl_is_pointer(file, kcontrols->id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -869,7 +881,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);
compatible_arg = 0;
break;
case VIDIOC_DQEVENT:
@@ -896,7 +908,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
 

[PATCH for v3.16 01/14] adv7604: use correct drive strength defines

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

The prefix is ADV7604_, not ADV76XX.

Fixes: f31b62e14a ("adv7604: add hdmi driver strength adjustment")

Signed-off-by: Hans Verkuil 
---
 drivers/media/i2c/adv7604.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index af8a99716de5..9e0e592f50ab 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2735,9 +2735,9 @@ static int adv7604_parse_dt(struct adv7604_state *state)
state->pdata.alt_data_sat = 1;
state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
state->pdata.bus_order = ADV7604_BUS_ORDER_RGB;
-   state->pdata.dr_str_data = ADV76XX_DR_STR_MEDIUM_HIGH;
-   state->pdata.dr_str_clk = ADV76XX_DR_STR_MEDIUM_HIGH;
-   state->pdata.dr_str_sync = ADV76XX_DR_STR_MEDIUM_HIGH;
+   state->pdata.dr_str_data = ADV7604_DR_STR_MEDIUM_HIGH;
+   state->pdata.dr_str_clk = ADV7604_DR_STR_MEDIUM_HIGH;
+   state->pdata.dr_str_sync = ADV7604_DR_STR_MEDIUM_HIGH;
 
return 0;
 }
-- 
2.15.1



[no subject]

2018-02-14 Thread Scott Tisdale
hi Linux https://goo.gl/jMp8sb   Scott Tisdale

Re: exposing a large-ish calibration table through V4L2?

2018-02-14 Thread Hans Verkuil
On 14/02/18 13:27, Florian Echtler wrote:
> Hello Hans,
> 
> On 14.02.2018 13:13, Hans Verkuil wrote:
>>
>> On 14/02/18 13:09, Florian Echtler wrote:
>>>
>>> The internal device memory contains a table with two bytes for each sensor 
>>> pixel
>>> (i.e. 960x540x2 = 1036800 bytes) that basically provide individual black and
>>> white levels per-pixel that are used in preprocessing. The table can either 
>>> be
>>> set externally, or the sensor can be covered with a black/white surface and 
>>> a
>>> custom command triggers an internal calibration.
>>>
>>> AFAICT the usual V4L2 controls are unsuitable for this sort of data; do you 
>>> have
>>> any suggestions on how to approach this? Maybe something like a custom 
>>> IOCTL?
>>
>> So the table has a fixed size?
>> You can use array controls for that, a V4L2_CTRL_TYPE_U16 in a 
>> two-dimensional array
>> would do it.
> 
> Good to know, thanks.
> 
>> See https://hverkuil.home.xs4all.nl/spec/uapi/v4l/vidioc-queryctrl.html for 
>> more
>> information on how this works.
> 
> This means I have to implement QUERY_EXT_CTRL, G_EXT_CTRLS and S_EXT_CTRLS,
> correct? Will this work in parallel to the "regular" controls that use the
> control framework?

No, just use the control framework. You need to make a custom control that is
specific to your driver

So reserve a range for your driver in include/uapi/linux/v4l2-controls.h
(search for 'USER-class private control IDs'). Then you can define a control
ID. The next step is to configure the control:

static const struct v4l2_ctrl_config cal_table_control = {
.ops = _ctrl_ops,
.id = V4L2_CID_SUR40_CAL_TABLE,
.name = "Calibration Table",
.type = V4L2_CTRL_TYPE_U16,
.max = 0x,
.step = 1,
.def = 0,
.dims = { 960, 540 },
};

And register it with a control handler:

v4l2_ctrl_new_custom(hdl, _table_control, NULL);

See e.g. drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c and the DETECT_MD 
controls.

Regards,

Hans


Re: [PATCH v7 2/2] v4l: cadence: Add Cadence MIPI-CSI2 RX driver

2018-02-14 Thread Maxime Ripard
Hi Laurent,

On Thu, Feb 08, 2018 at 08:17:19PM +0200, Laurent Pinchart wrote:
> > +   /*
> > +* Create a static mapping between the CSI virtual channels
> > +* and the output stream.
> > +*
> > +* This should be enhanced, but v4l2 lacks the support for
> > +* changing that mapping dynamically.
> > +*
> > +* We also cannot enable and disable independant streams here,
> > +* hence the reference counting.
> > +*/
> 
> If you start all streams in one go, will s_stream(1) be called multiple times 
> ? If not, you could possibly skip the whole reference counting and avoid 
> locking.

I guess that while we should expect the CSI-2 bus to be always
enabled, the downstream camera interface could be shutdown
independently, so I guess s_stream would be called each time one is
brought up or brought down?

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
http://bootlin.com


signature.asc
Description: PGP signature


[PATCH for v4.14 13/13] media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream.

If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops
is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash.
Add a test for !ops to the condition.

All sub-devices that have controls will use the control framework,
so they do not have an equivalent to ops->vidioc_query_ext_ctrl.
Returning false if ops is NULL is the correct thing to do here.

Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer")

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reported-by: Laurent Pinchart 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index ec4a69728ed4..cbeea8343a5c 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -770,7 +770,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 
id)
return ctrl && ctrl->is_ptr;
}
 
-   if (!ops->vidioc_query_ext_ctrl)
+   if (!ops || !ops->vidioc_query_ext_ctrl)
return false;
 
return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
-- 
2.15.1



[PATCH for v4.14 11/13] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.

Some ioctls need to copy back the result even if the ioctl returned
an error. However, don't do this for the error code -ENOTTY.
It makes no sense in that cases.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index bef9c990c9bd..5603c7c1edd5 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -968,6 +968,9 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
set_fs(old_fs);
}
 
+   if (err == -ENOTTY)
+   return err;
+
/* Special case: even after an error we need to put the
   results back for these ioctls since the error_idx will
   contain information on which control failed. */
-- 
2.15.1



[PATCH for v3.16 06/14] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 92 ++-
 1 file changed, 20 insertions(+), 72 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index a3e62cf3acaa..f76ed4ee7df9 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -89,64 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
__u32   type;   /* enum v4l2_buf_type */
union {
@@ -184,20 +126,23 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   return copy_from_user(>fmt.vbi, >fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-   return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
+   return copy_from_user(>fmt.sliced, >fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
   kp->type);
@@ -225,20 +170,23 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return put_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_to_user(>fmt.pix, >fmt.pix,
+ 

[PATCH for v3.16 10/14] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.

Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
overlays.") added the field global_alpha to struct v4l2_window but did
not update the compat layer accordingly. This change adds global_alpha
to struct v4l2_window32 and copies the value for global_alpha back and
forth.

Signed-off-by: Daniel Mentz 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 69d772d1237d..de69afde9e86 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,6 +45,7 @@ struct v4l2_window32 {
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
compat_caddr_t  bitmap;
+   __u8global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
@@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
@@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
return 0;
 }
-- 
2.15.1



[PATCH for v3.16 07/14] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 73 +--
 1 file changed, 35 insertions(+), 38 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f76ed4ee7df9..c9d9f23e660a 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -47,7 +47,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -152,14 +152,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -196,7 +196,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->type, >type))
return -EFAULT;
return __put_v4l2_format32(kp, up);
@@ -204,7 +204,7 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct 
v4l2_format32 __user
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format.fmt)))
return -EFAULT;
return __put_v4l2_format32(>format, >format);
@@ -222,7 +222,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -230,13 +230,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -284,7 +284,7 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 

[PATCH for v3.16 00/14] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 3.16, the vivi driver (a poor substitute for
the much improved vivid driver that's available in later kernels, but it's the
best I had) since that emulates the more common V4L2 ioctls that need to pass
through v4l2-compat-ioctl32.c) and the 32-bit v4l2-compliance + 32-bit v4l2-ctl
utilities that together exercised the most common ioctls.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other known bugs, and 2) keep the final patch at least
somewhat readable.

While compiling the media drivers for 3.16 I also came across a bug
introduced in the 3.16 stable series that caused a compile error in the
adv7604 driver. That's fixed in the first patch. Call it a bonus patch :-)

Regards,

Hans

Daniel Mentz (2):
  media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (11):
  adv7604: use correct drive strength defines
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors

Ricardo Ribalda (1):
  vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

 drivers/media/i2c/adv7604.c   |6 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1030 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c  |5 +-
 drivers/media/v4l2-core/videobuf2-core.c  |5 +
 4 files changed, 642 insertions(+), 404 deletions(-)

-- 
2.15.1



[PATCH for v3.16 08/14] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 ---
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index c9d9f23e660a..3a72a735a940 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -287,19 +287,24 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else if (memory == V4L2_MEMORY_DMABUF) {
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd, sizeof(up32->m.fd)))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -308,22 +313,32 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
-   /* For DMABUF, driver might've set up the fd, so copy it back. */
-   if (memory == V4L2_MEMORY_DMABUF)
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd,
 sizeof(up->m.fd)))
return -EFAULT;
+   break;
+   }
 
return 0;
 }
@@ -384,6 +399,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (get_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -397,10 +413,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
-   case V4L2_MEMORY_OVERLAY:
-   if (get_user(kp->m.offset, >m.offset))
-   return -EFAULT;
-   break;
case V4L2_MEMORY_DMABUF:
if (get_user(kp->m.fd, >m.fd))
return -EFAULT;
@@ -457,6 +469,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (put_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -464,10 +477,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
 

[PATCH for v3.16 05/14] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 216 +-
 1 file changed, 108 insertions(+), 108 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index ebedf95a31ed..a3e62cf3acaa 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -48,11 +48,11 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount))
+   return -EFAULT;
return 0;
 }
 
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format 
*kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -200,7 +200,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -241,7 +241,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return put_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -249,7 +249,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-   put_user(kp->type, >type))
+   put_user(kp->type, >type))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
@@ -258,7 +258,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers 
*kp, struct v4l2_create_
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format.fmt)))
-   return -EFAULT;
+   return -EFAULT;
return __put_v4l2_format32(>format, >format);
 }
 
@@ -275,7 +275,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if 

[PATCH for v3.16 04/14] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 0f747ba40b52..ebedf95a31ed 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -980,6 +980,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v3.16 02/14] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 16bffd851bf9..e2f71def945a 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2402,8 +2402,11 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+   goto out;
+   }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
-- 
2.15.1



[PATCH for v3.16 03/14] vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

2018-02-14 Thread Hans Verkuil
From: Ricardo Ribalda 

commit 3171cc2b4eb9831ab4df1d80d0410a945b8bc84e upstream.

According to the doc, V4L2_BUF_FLAG_DONE is cleared after DQBUF:

V4L2_BUF_FLAG_DONE 0x0004  ... After calling the VIDIOC_QBUF or
VIDIOC_DQBUF it is always cleared ...

Unfortunately, it seems that videobuf2 keeps it set after DQBUF. This
can be tested with vivid and dev_debug:

[257604.338082] video1: VIDIOC_DQBUF: 71:33:25.00260479 index=3,
type=vid-cap, flags=0x2004, field=none, sequence=163,
memory=userptr, bytesused=460800, offset/userptr=0x344b000,
length=460800

This patch forces FLAG_DONE to 0 after calling DQBUF.

Reported-by: Dimitrios Katsaros 
Signed-off-by: Ricardo Ribalda Delgado 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/videobuf2-core.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index e63a7904bf5b..ee8b697972bb 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -2069,6 +2069,11 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, 
struct v4l2_buffer *b, bool n
dprintk(1, "dqbuf of buffer %d, with state %d\n",
vb->v4l2_buf.index, vb->state);
 
+   /*
+* After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
+* cleared.
+*/
+   b->flags &= ~V4L2_BUF_FLAG_DONE;
return 0;
 }
 
-- 
2.15.1



[PATCH for v3.2 01/12] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-ioctl.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 639abeee3392..bae5dd776d82 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -2308,8 +2308,10 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
-   err = -EINVAL;
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
+   err = -ENOTTY;
+   goto out;
+   }
 
if (has_array_args) {
*kernel_ptr = user_ptr;
-- 
2.15.1



[PATCH for v3.2 05/12] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/video/v4l2-compat-ioctl32.c | 65 +++
 1 file changed, 31 insertions(+), 34 deletions(-)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c 
b/drivers/media/video/v4l2-compat-ioctl32.c
index 4d0901573860..e2dee29eaaa5 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -47,7 +47,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -156,14 +156,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -204,7 +204,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->type, >type))
return -EFAULT;
return __put_v4l2_format32(kp, up);
@@ -212,7 +212,7 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct 
v4l2_format32 __user
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format.fmt)))
return -EFAULT;
return __put_v4l2_format32(>format, >format);
@@ -230,7 +230,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -238,13 +238,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
copy_to_user(up->id, >id, sizeof(__u64)) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -290,7 +290,7 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct 
v4l2_plane32 *up32,
 
  

Re: exposing a large-ish calibration table through V4L2?

2018-02-14 Thread Florian Echtler
Hello Hans,

On 14.02.2018 13:13, Hans Verkuil wrote:
> 
> On 14/02/18 13:09, Florian Echtler wrote:
>>
>> The internal device memory contains a table with two bytes for each sensor 
>> pixel
>> (i.e. 960x540x2 = 1036800 bytes) that basically provide individual black and
>> white levels per-pixel that are used in preprocessing. The table can either 
>> be
>> set externally, or the sensor can be covered with a black/white surface and a
>> custom command triggers an internal calibration.
>>
>> AFAICT the usual V4L2 controls are unsuitable for this sort of data; do you 
>> have
>> any suggestions on how to approach this? Maybe something like a custom IOCTL?
> 
> So the table has a fixed size?
> You can use array controls for that, a V4L2_CTRL_TYPE_U16 in a 
> two-dimensional array
> would do it.

Good to know, thanks.

> See https://hverkuil.home.xs4all.nl/spec/uapi/v4l/vidioc-queryctrl.html for 
> more
> information on how this works.

This means I have to implement QUERY_EXT_CTRL, G_EXT_CTRLS and S_EXT_CTRLS,
correct? Will this work in parallel to the "regular" controls that use the
control framework?

Best, Florian
-- 
SENT FROM MY DEC VT50 TERMINAL



signature.asc
Description: OpenPGP digital signature


Re: [PATCH v10 6/8] media: i2c: Add TDA1997x HDMI receiver driver

2018-02-14 Thread Hans Verkuil
Hi Tim,

On 12/02/18 23:27, Tim Harvey wrote:
> On Fri, Feb 9, 2018 at 12:08 AM, Hans Verkuil  wrote:
>> Hi Tim,
>>
>> We're almost there. Two more comments:
>>
>> On 02/09/2018 07:32 AM, Tim Harvey wrote:
>>> +static int
>>> +tda1997x_detect_std(struct tda1997x_state *state,
>>> + struct v4l2_dv_timings *timings)
>>> +{
>>> + struct v4l2_subdev *sd = >sd;
>>> + u32 vper;
>>> + u16 hper;
>>> + u16 hsper;
>>> + int i;
>>> +
>>> + /*
>>> +  * Read the FMT registers
>>> +  *   REG_V_PER: Period of a frame (or two fields) in MCLK(27MHz) 
>>> cycles
>>> +  *   REG_H_PER: Period of a line in MCLK(27MHz) cycles
>>> +  *   REG_HS_WIDTH: Period of horiz sync pulse in MCLK(27MHz) cycles
>>> +  */
>>> + vper = io_read24(sd, REG_V_PER) & MASK_VPER;
>>> + hper = io_read16(sd, REG_H_PER) & MASK_HPER;
>>> + hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
>>> + if (!vper || !hper || !hsper)
>>> + return -ENOLINK;
>>
>> See my comment for g_input_status below. This condition looks more like a
>> ENOLCK.
>>
>> Or perhaps it should be:
>>
>> if (!vper && !hper && !hsper)
>> return -ENOLINK;
>> if (!vper || !hper || !hsper)
>> return -ENOLCK;
>>
>> I would recommend that you test a bit with no signal and a bad signal 
>> (perhaps
>> one that uses a pixelclock that is too high for this device?).
> 
> I can't figure out how to produce a signal that can't be locked onto
> with what I have available.

Are you using a signal generator or just a laptop or something similar as the
source?

Without a good signal generator it is tricky to test this. A very long HDMI
cable would likely do it. But for 1080p60 you probably need 20 meters or
more.

> 
>>
>>> + v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, 
>>> hsper);
>>> +
>>> + for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
>>> + const struct v4l2_bt_timings *bt;
>>> + u32 lines, width, _hper, _hsper;
>>> + u32 vmin, vmax, hmin, hmax, hsmin, hsmax;
>>> + bool vmatch, hmatch, hsmatch;
>>> +
>>> + bt = _dv_timings_presets[i].bt;
>>> + width = V4L2_DV_BT_FRAME_WIDTH(bt);
>>> + lines = V4L2_DV_BT_FRAME_HEIGHT(bt);
>>> + _hper = (u32)bt->pixelclock / width;
>>> + if (bt->interlaced)
>>> + lines /= 2;
>>> + /* vper +/- 0.7% */
>>> + vmin = ((2700 / 1000) * 993) / _hper * lines;
>>> + vmax = ((2700 / 1000) * 1007) / _hper * lines;
>>> + /* hper +/- 1.0% */
>>> + hmin = ((2700 / 100) * 99) / _hper;
>>> + hmax = ((2700 / 100) * 101) / _hper;
>>> + /* hsper +/- 2 (take care to avoid 32bit overflow) */
>>> + _hsper = 27000 * bt->hsync / ((u32)bt->pixelclock/1000);
>>> + hsmin = _hsper - 2;
>>> + hsmax = _hsper + 2;
>>> +
>>> + /* vmatch matches the framerate */
>>> + vmatch = ((vper <= vmax) && (vper >= vmin)) ? 1 : 0;
>>> + /* hmatch matches the width */
>>> + hmatch = ((hper <= hmax) && (hper >= hmin)) ? 1 : 0;
>>> + /* hsmatch matches the hswidth */
>>> + hsmatch = ((hsper <= hsmax) && (hsper >= hsmin)) ? 1 : 0;
>>> + if (hmatch && vmatch && hsmatch) {
>>> + *timings = v4l2_dv_timings_presets[i];
>>> + v4l2_print_dv_timings(sd->name, "Detected format: ",
>>> +   timings, false);
>>> + return 0;
>>> + }
>>> + }
>>> +
>>> + v4l_err(state->client, "no resolution match for timings: %d/%d/%d\n",
>>> + vper, hper, hsper);
>>> + return -EINVAL;
>>> +}
>>
>> -EINVAL isn't the correct error code here. I would go for -ERANGE. It's not
>> perfect, but close enough.
>>
>> -EINVAL indicates that the user filled in wrong values, but that's not the
>> case here.
> 
> done
> 
>>
>>> +static int
>>> +tda1997x_g_input_status(struct v4l2_subdev *sd, u32 *status)
>>> +{
>>> + struct tda1997x_state *state = to_state(sd);
>>> + u32 vper;
>>> + u16 hper;
>>> + u16 hsper;
>>> +
>>> + mutex_lock(>lock);
>>> + v4l2_dbg(1, debug, sd, "inputs:%d/%d\n",
>>> +  state->input_detect[0], state->input_detect[1]);
>>> + if (state->input_detect[0] || state->input_detect[1])
>>
>> I'm confused. This device has two HDMI inputs?
>>
>> Does 'detecting input' equate to 'I see a signal and I am locked'?
>> I gather from the irq function that sets these values that it is closer
>> to 'I see a signal' and that 'I am locked' is something you would test
>> by looking at the vper/hper/hsper.
> 
> The TDA19972 and/or TDA19973 has an A and B input but only a single
> output. I'm not entirely clear if/how to select between the two and I

[PATCH 1/1] media: request: Add support for tagged request-based objects

2018-02-14 Thread Sakari Ailus
Allow binding objects to requests that can be later on fetched based on
that tag.

The intent is that the objects are bound at the time data is bound to a
request and later retrieved for validation (and finally applied) when the
request is queued. A tag can be any pointer, as long as it is unique to a
request.

Signed-off-by: Sakari Ailus 
---
Hi Alexandre,

Here's the patch. It's on top of your current set so if you remove entity
data support there may be some conflicts to resolve. It's only been
compile tested so far, but is rather simple. By providing a tag, the
caller may attach data objects to the request and they can be found later
on, by using the same tag, when the request is queued.

The drivers are still responsible for adding only objects they can support
with requests. The driver must also detach the data from the request, and
at the queue time, make sure that no objects that weren't accounted for
were added.

 drivers/media/media-request.c | 105 ++
 include/media/media-request.h |  75 ++
 2 files changed, 180 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 30a2323..c96b747 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -57,10 +57,115 @@ media_request_get_from_fd(int fd)
 }
 EXPORT_SYMBOL_GPL(media_request_get_from_fd);
 
+int media_request_data_attach(struct media_request *req, const void *tag,
+ void *data,
+ void (*release)(struct media_request *req,
+ const void *tag, void *data))
+{
+   struct media_request_data *req_data;
+
+   req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+   if (!req_data)
+   return -ENOMEM;
+
+   req_data->req = req;
+   req_data->tag = tag;
+   req_data->data = data;
+   req_data->release = release;
+
+   mutex_lock(>lock);
+   list_add(_data->list, >data_list);
+   mutex_unlock(>lock);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(media_request_data_attach);
+
+struct media_request_data *__media_request_data_find(
+   struct media_request *req, const void *tag)
+{
+   struct media_request_data *req_data;
+
+   lockdep_assert_held(>lock);
+
+   list_for_each_entry(req_data, >data_list, list)
+   if (req_data->tag == tag)
+   return req_data;
+
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(__media_request_data_find);
+
+void *media_request_data_find(struct media_request *req, const void *tag)
+{
+   struct media_request_data *req_data;
+   void *data;
+
+   mutex_lock(>lock);
+   req_data = __media_request_data_find(req, tag);
+   mutex_lock(>lock);
+
+   data = req_data ? req_data->data : NULL;
+
+   return data;
+}
+EXPORT_SYMBOL_GPL(media_request_data_find);
+
+void media_request_data_detach(struct media_request *req, const void *tag)
+{
+   struct media_request_data *req_data;
+
+   mutex_lock(>lock);
+
+   req_data = __media_request_data_find(req, tag);
+   if (WARN_ON(!req_data)) {
+   mutex_unlock(>lock);
+   return;
+   }
+
+   list_del(_data->list);
+
+   mutex_unlock(>lock);
+
+   if (req_data->release)
+   req_data->release(req_data->req, req_data->tag, req_data->data);
+
+   kfree(req_data);
+}
+EXPORT_SYMBOL_GPL(media_request_data_detach);
+
+static void __media_request_data_detach(struct media_request_data *req)
+{
+   struct media_request_data *req_data;
+
+   list_del(_data->list);
+
+   if (req_data->release)
+   req_data->release(req_data->req, req_data->tag, req_data->data);
+
+   kfree(req_data);
+}
+
+bool media_request_has_data(struct media_request *req)
+{
+   bool ret;
+
+   mutex_lock(>lock);
+   ret = list_empty(>data_list);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+
 static void media_request_release(struct kref *kref)
 {
struct media_request *req =
container_of(kref, typeof(*req), kref);
+   struct media_request_data *req_data, *req_data_safe;
+
+   /* Last reference; no need to acquire the lock here. */
+   list_for_each_entry_safe(req_data, req_data_safe, >data_list, list)
+   __media_request_data_detach(req_data);
 
req->mgr->ops->req_free(req);
 }
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 817df13..64b945d 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -36,12 +36,23 @@ enum media_request_state {
MEDIA_REQUEST_STATE_DELETED,
 };
 
+struct media_request_data {
+   struct media_request *req;
+   const void *tag;
+   struct list_head list;
+   void *data;
+   void (*release)(struct media_request *req,
+   const void *tag, void *data);
+};
+
 

[PATCH for v4.14 12/13] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.

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, >clipcount) ||
put_user(clipcount, >clipcount)) return -EFAULT;

Notes from hans.verk...@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 
Co-developed-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 740 +-
 1 file changed, 477 insertions(+), 263 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 5603c7c1edd5..ec4a69728ed4 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -22,6 +22,14 @@
 #include 
 #include 
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)   \
+({ \
+   typeof(*from) __assign_tmp; \
+   \
+   get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
 {
long ret = -ENOIOCTLCMD;
@@ -48,37 +56,41 @@ struct v4l2_window32 {
__u8global_alpha;
 };
 
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+struct v4l2_window32 __user *up,
+void __user *aux_buf, u32 aux_space)
 {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user *kclips;
compat_caddr_t p;
-   u32 n;
+   u32 clipcount;
 
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount) ||
-   get_user(kp->global_alpha, >global_alpha))
+   copy_in_user(>w, >w, sizeof(up->w)) ||
+   assign_in_user(>field, >field) ||
+   assign_in_user(>chromakey, >chromakey) ||
+   assign_in_user(>global_alpha, >global_alpha) 

[PATCH for v4.14 07/13] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 ---
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index d156b8975f1e..62d44fab5671 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -310,19 +310,24 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else if (memory == V4L2_MEMORY_DMABUF) {
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd, sizeof(up32->m.fd)))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -331,22 +336,32 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 
__user *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
-   /* For DMABUF, driver might've set up the fd, so copy it back. */
-   if (memory == V4L2_MEMORY_DMABUF)
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd,
 sizeof(up->m.fd)))
return -EFAULT;
+   break;
+   }
 
return 0;
 }
@@ -408,6 +423,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (get_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -421,10 +437,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
-   case V4L2_MEMORY_OVERLAY:
-   if (get_user(kp->m.offset, >m.offset))
-   return -EFAULT;
-   break;
case V4L2_MEMORY_DMABUF:
if (get_user(kp->m.fd, >m.fd))
return -EFAULT;
@@ -481,6 +493,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (put_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -488,10 +501,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user

[PATCH for v4.14 02/13] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 42e376f46729..d06941cc6a55 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2892,8 +2892,11 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+   goto out;
+   }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
-- 
2.15.1



[PATCH for v4.14 01/13] media: v4l2-ioctl.c: use check_fmt for enum/g/s/try_fmt

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b2469c814fbc8f1f19676dd4912717b798df511e upstream.

Don't duplicate the buffer type checks in enum/g/s/try_fmt.
The check_fmt function does that already.

It is hard to keep the checks in sync for all these functions and
in fact the check for VBI was wrong in the _fmt functions as it
allowed SDR types as well. This caused a v4l2-compliance failure
for /dev/swradio0 using vivid.

This simplifies the code and keeps the check in one place and
fixes the SDR/VBI bug.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 140 ++-
 1 file changed, 54 insertions(+), 86 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index b60a6b0841d1..42e376f46729 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1308,52 +1308,50 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops 
*ops,
struct file *file, void *fh, void *arg)
 {
struct v4l2_fmtdesc *p = arg;
-   struct video_device *vfd = video_devdata(file);
-   bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
-   bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
-   bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
-   bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
-   bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
-   int ret = -EINVAL;
+   int ret = check_fmt(file, p->type);
+
+   if (ret)
+   return ret;
+   ret = -EINVAL;
 
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-   if (unlikely(!is_rx || (!is_vid && !is_tch) || 
!ops->vidioc_enum_fmt_vid_cap))
+   if (unlikely(!ops->vidioc_enum_fmt_vid_cap))
break;
ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-   if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_enum_fmt_vid_cap_mplane))
+   if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane))
break;
ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-   if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_enum_fmt_vid_overlay))
+   if (unlikely(!ops->vidioc_enum_fmt_vid_overlay))
break;
ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_enum_fmt_vid_out))
+   if (unlikely(!ops->vidioc_enum_fmt_vid_out))
break;
ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_enum_fmt_vid_out_mplane))
+   if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane))
break;
ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
break;
case V4L2_BUF_TYPE_SDR_CAPTURE:
-   if (unlikely(!is_rx || !is_sdr || 
!ops->vidioc_enum_fmt_sdr_cap))
+   if (unlikely(!ops->vidioc_enum_fmt_sdr_cap))
break;
ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
break;
case V4L2_BUF_TYPE_SDR_OUTPUT:
-   if (unlikely(!is_tx || !is_sdr || 
!ops->vidioc_enum_fmt_sdr_out))
+   if (unlikely(!ops->vidioc_enum_fmt_sdr_out))
break;
ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
break;
case V4L2_BUF_TYPE_META_CAPTURE:
-   if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_enum_fmt_meta_cap))
+   if (unlikely(!ops->vidioc_enum_fmt_meta_cap))
break;
ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
break;
@@ -1367,13 +1365,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
 {
struct v4l2_format *p = arg;
-   struct video_device *vfd = video_devdata(file);
-   bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
-   bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
-   bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
-   bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
-   bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
-   int ret;
+   int ret = check_fmt(file, p->type);
+
+   if (ret)
+   return ret;
 
/*
 * fmt can't be cleared for these overlay types due to the 'clips'
@@ -1401,7 +1396,7 @@ static int 

[PATCH for v4.14 00/13] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 4.14, the vivid driver (since that
emulates almost all V4L2 ioctls that need to pass through v4l2-compat-ioctl32.c)
and a 32-bit v4l2-compliance utility since that exercises almost all ioctls
as well. Combined this gives good test coverage.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other bugs, and 2) keep the final patch at least somewhat
readable.

Rgards,

Hans

Daniel Mentz (1):
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (12):
  media: v4l2-ioctl.c: use check_fmt for enum/g/s/try_fmt
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors
  media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs

 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1032 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c  |  145 ++--
 2 files changed, 665 insertions(+), 512 deletions(-)

-- 
2.15.1



[PATCH for v4.14 06/13] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 79 ---
 1 file changed, 36 insertions(+), 43 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 297c924aefce..d156b8975f1e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -48,7 +48,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -66,7 +66,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -164,14 +164,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -218,14 +218,14 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format)) ||
copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
@@ -244,7 +244,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -252,14 +252,14 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod,
 sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -307,7 +307,7 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 
if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, 

[PATCH for v4.14 04/13] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 212 +-
 1 file changed, 107 insertions(+), 105 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f6a7f8793720..44644a2ea3e9 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -49,12 +49,12 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount) ||
-   get_user(kp->global_alpha, >global_alpha))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -84,11 +84,11 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount) ||
-   put_user(kp->global_alpha, >global_alpha))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
+   return -EFAULT;
return 0;
 }
 
@@ -100,7 +100,7 @@ static inline int get_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -115,7 +115,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -238,7 +238,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return get_v4l2_meta_format(>fmt.meta, >fmt.meta);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -287,7 +287,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return put_v4l2_meta_format(>fmt.meta, >fmt.meta);
default:
pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
+   kp->type);
return -EINVAL;
}
 }
@@ -321,7 +321,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-   get_user(kp->index, >index))
+   get_user(kp->index, >index))
return -EFAULT;
return 0;
 }
@@ -329,13 +329,14 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-   put_user(kp->index, >index) ||
-   put_user(kp->id, >id) ||
-   copy_to_user(up->name, kp->name, 24) ||
-  

[PATCH for v4.14 08/13] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++-
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 62d44fab5671..d11334712c65 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
@@ -601,24 +603,39 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   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, >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;
}
+
+   if (!ops->vidioc_query_ext_ctrl)
+   return false;
+
+   return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
+   (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -651,7 +668,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return -EFAULT;
if (get_user(id, >id))
return -EFAULT;
-   if (ctrl_is_pointer(id)) {
+   if (ctrl_is_pointer(file, id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -666,7 +683,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols =
@@ -698,7 +717,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(id))
+   if (ctrl_is_pointer(file, id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -912,7 +931,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);

[PATCH for v4.14 10/13] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index de3e99dc3caa..bef9c990c9bd 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -179,8 +179,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_from_user(>fmt.meta, >fmt.meta,
  sizeof(kp->fmt.meta)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
@@ -233,8 +231,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_to_user(>fmt.meta, >fmt.meta,
sizeof(kp->fmt.meta)) ? -EFAULT : 0;
default:
-   pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-   kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



[PATCH for v4.14 09/13] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 ++-
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index d11334712c65..de3e99dc3caa 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -50,6 +50,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v4.14 05/13] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 124 +-
 1 file changed, 24 insertions(+), 100 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 44644a2ea3e9..297c924aefce 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -92,92 +92,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct 
v4l2_sdr_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct 
v4l2_meta_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct 
v4l2_meta_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
__u32   type;   /* enum v4l2_buf_type */
union {
@@ -217,25 +131,30 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   

[PATCH for v4.14 03/13] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 821f2aa299ae..f6a7f8793720 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1052,6 +1052,7 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v4.1 00/14] v4l2-compat-ioctl32.c: remove set_fs(KERNEL_DS)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

This patch series fixes a number of bugs and culminates in the removal
of the set_fs(KERNEL_DS) call in v4l2-compat-ioctl32.c.

This was tested with a VM running 4.1, the vivid driver (since that
emulates almost all V4L2 ioctls that need to pass through v4l2-compat-ioctl32.c)
and a 32-bit v4l2-compliance utility since that exercises almost all ioctls
as well. Combined this gives good test coverage.

Most of the v4l2-compat-ioctl32.c do cleanups and fix subtle issues that
v4l2-compliance complained about. The purpose is to 1) make it easy to
verify that the final patch didn't introduce errors by first eliminating
errors caused by other known bugs, and 2) keep the final patch at least
somewhat readable.

Regards,

Hans

Daniel Mentz (2):
  media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
  media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

Hans Verkuil (11):
  media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
  media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
  media: v4l2-compat-ioctl32.c: fix the indentation
  media: v4l2-compat-ioctl32.c: move 'helper' functions to
__get/put_v4l2_format32
  media: v4l2-compat-ioctl32.c: avoid sizeof(type)
  media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
  media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
  media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
  media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
  media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
  media: v4l2-compat-ioctl32.c: don't copy back the result for certain
errors

Ricardo Ribalda Delgado (1):
  vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1014 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c  |5 +-
 drivers/media/v4l2-core/videobuf2-core.c  |5 +
 3 files changed, 625 insertions(+), 399 deletions(-)

-- 
2.15.1



[PATCH for v4.1 07/14] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream.

The struct v4l2_plane32 should set m.userptr as well. The same
happens in v4l2_buffer32 and v4l2-compliance tests for this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 ---
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 03d1d92a2a8e..25a61fc27a36 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -290,19 +290,24 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 sizeof(up->data_offset)))
return -EFAULT;
 
-   if (memory == V4L2_MEMORY_USERPTR) {
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
+   if (copy_in_user(>m.mem_offset, >m.mem_offset,
+sizeof(up32->m.mem_offset)))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_USERPTR:
if (get_user(p, >m.userptr))
return -EFAULT;
up_pln = compat_ptr(p);
if (put_user((unsigned long)up_pln, >m.userptr))
return -EFAULT;
-   } else if (memory == V4L2_MEMORY_DMABUF) {
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd, sizeof(up32->m.fd)))
return -EFAULT;
-   } else {
-   if (copy_in_user(>m.mem_offset, >m.mem_offset,
-sizeof(up32->m.mem_offset)))
-   return -EFAULT;
+   break;
}
 
return 0;
@@ -311,22 +316,32 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 
__user *up32,
enum v4l2_memory memory)
 {
+   unsigned long p;
+
if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, >data_offset,
 sizeof(up->data_offset)))
return -EFAULT;
 
-   /* For MMAP, driver might've set up the offset, so copy it back.
-* USERPTR stays the same (was userspace-provided), so no copying. */
-   if (memory == V4L2_MEMORY_MMAP)
+   switch (memory) {
+   case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (copy_in_user(>m.mem_offset, >m.mem_offset,
 sizeof(up->m.mem_offset)))
return -EFAULT;
-   /* For DMABUF, driver might've set up the fd, so copy it back. */
-   if (memory == V4L2_MEMORY_DMABUF)
+   break;
+   case V4L2_MEMORY_USERPTR:
+   if (get_user(p, >m.userptr) ||
+   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+>m.userptr))
+   return -EFAULT;
+   break;
+   case V4L2_MEMORY_DMABUF:
if (copy_in_user(>m.fd, >m.fd,
 sizeof(up->m.fd)))
return -EFAULT;
+   break;
+   }
 
return 0;
 }
@@ -386,6 +401,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (get_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -399,10 +415,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user
kp->m.userptr = (unsigned long)compat_ptr(tmp);
}
break;
-   case V4L2_MEMORY_OVERLAY:
-   if (get_user(kp->m.offset, >m.offset))
-   return -EFAULT;
-   break;
case V4L2_MEMORY_DMABUF:
if (get_user(kp->m.fd, >m.fd))
return -EFAULT;
@@ -459,6 +471,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct 
v4l2_buffer32 __user
} else {
switch (kp->memory) {
case V4L2_MEMORY_MMAP:
+   case V4L2_MEMORY_OVERLAY:
if (put_user(kp->m.offset, >m.offset))
return -EFAULT;
break;
@@ -466,10 +479,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, 
struct v4l2_buffer32 __user

[PATCH for v4.1 09/14] media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream.

If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops
is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash.
Add a test for !ops to the condition.

All sub-devices that have controls will use the control framework,
so they do not have an equivalent to ops->vidioc_query_ext_ctrl.
Returning false if ops is NULL is the correct thing to do here.

Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer")

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reported-by: Laurent Pinchart 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 52205d37f97f..626a3b345075 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -603,7 +603,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 
id)
return ctrl && ctrl->is_ptr;
}
 
-   if (!ops->vidioc_query_ext_ctrl)
+   if (!ops || !ops->vidioc_query_ext_ctrl)
return false;
 
return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
-- 
2.15.1



[PATCH for v4.1 12/14] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream.

There is nothing wrong with using an unknown buffer type. So
stop spamming the kernel log whenever this happens. The kernel
will just return -EINVAL to signal this.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 25cf19193c13..8371bbbda383 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -170,8 +170,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_from_user(>fmt.sliced, >fmt.sliced,
  sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
@@ -217,8 +215,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return copy_to_user(>fmt.sliced, >fmt.sliced,
sizeof(kp->fmt.sliced)) ?  -EFAULT : 0;
default:
-   printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-  kp->type);
return -EINVAL;
}
 }
-- 
2.15.1



[PATCH for v4.1 04/14] media: v4l2-compat-ioctl32.c: fix the indentation

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b7b957d429f601d6d1942122b339474f31191d75 upstream.

The indentation of this source is all over the place. Fix this.
This patch only changes whitespace.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 216 +-
 1 file changed, 108 insertions(+), 108 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 42d402948ea2..ba6aaea11e2f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -48,11 +48,11 @@ struct v4l2_window32 {
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-   copy_from_user(>w, >w, sizeof(up->w)) ||
-   get_user(kp->field, >field) ||
-   get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   copy_from_user(>w, >w, sizeof(up->w)) ||
+   get_user(kp->field, >field) ||
+   get_user(kp->chromakey, >chromakey) ||
+   get_user(kp->clipcount, >clipcount))
+   return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
if (kp->clipcount) {
@@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
-   put_user(kp->field, >field) ||
-   put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
-   return -EFAULT;
+   put_user(kp->field, >field) ||
+   put_user(kp->chromakey, >chromakey) ||
+   put_user(kp->clipcount, >clipcount))
+   return -EFAULT;
return 0;
 }
 
@@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format 
*kp, struct v4l2_pi
 }
 
 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct 
v4l2_pix_format *kp, struct v4l2_pi
 }
 
 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-   struct v4l2_pix_format_mplane __user *up)
+struct v4l2_pix_format_mplane 
__user *up)
 {
if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
@@ -200,7 +200,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -244,7 +244,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
return put_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
-   kp->type);
+  kp->type);
return -EINVAL;
}
 }
@@ -278,7 +278,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 {
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-   get_user(kp->index, >index))
+   get_user(kp->index, >index))
return -EFAULT;
return 0;
 }
@@ -286,13 +286,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-   put_user(kp->index, >index) ||
-   copy_to_user(up->id, >id, sizeof(__u64)) ||
-   copy_to_user(up->name, kp->name, 24) ||
-   copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
-   put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, 

[PATCH for v4.1 14/14] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream.

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, >clipcount) ||
put_user(clipcount, >clipcount)) return -EFAULT;

Notes from hans.verk...@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 
Co-developed-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 748 +-
 1 file changed, 485 insertions(+), 263 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 3e1d3ed3561c..e03aa0961360 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -22,6 +22,14 @@
 #include 
 #include 
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)   \
+({ \
+   typeof(*from) __assign_tmp; \
+   \
+   get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
 {
long ret = -ENOIOCTLCMD;
@@ -35,12 +43,12 @@ static long native_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg)
 
 struct v4l2_clip32 {
struct v4l2_rectc;
-   compat_caddr_t  next;
+   compat_caddr_t  next;
 };
 
 struct v4l2_window32 {
struct v4l2_rectw;
-   __u32   field;  /* enum v4l2_field */
+   __u32   field;  /* enum v4l2_field */
__u32   chromakey;
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
@@ -48,37 +56,41 @@ struct v4l2_window32 {
__u8global_alpha;
 };
 
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+struct v4l2_window32 __user *up,
+void __user *aux_buf, u32 aux_space)
 {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user 

[PATCH for v4.1 03/14] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream.

The result of the VIDIOC_PREPARE_BUF ioctl was never copied back
to userspace since it was missing in the switch.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 4f002d0bebb1..42d402948ea2 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -999,6 +999,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
err = put_v4l2_create32(, up);
break;
 
+   case VIDIOC_PREPARE_BUF:
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
-- 
2.15.1



[PATCH for v4.1 13/14] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream.

Some ioctls need to copy back the result even if the ioctl returned
an error. However, don't do this for the error code -ENOTTY.
It makes no sense in that cases.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 8371bbbda383..3e1d3ed3561c 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -946,6 +946,9 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
set_fs(old_fs);
}
 
+   if (err == -ENOTTY)
+   return err;
+
/* Special case: even after an error we need to put the
   results back for these ioctls since the error_idx will
   contain information on which control failed. */
-- 
2.15.1



[PATCH for v4.1 05/14] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream.

These helper functions do not really help. Move the code to the
__get/put_v4l2_format32 functions.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 84 +--
 1 file changed, 16 insertions(+), 68 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index ba6aaea11e2f..2a116d671f92 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -89,64 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return 0;
 }
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct 
v4l2_pix_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-struct v4l2_pix_format_mplane 
__user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct 
v4l2_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format 
*kp, struct v4l2_sliced_vbi_format __user *up)
-{
-   if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-   return -EFAULT;
-   return 0;
-}
-
 struct v4l2_format32 {
__u32   type;   /* enum v4l2_buf_type */
union {
@@ -184,20 +126,23 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return get_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_from_user(>fmt.pix, >fmt.pix,
+ sizeof(kp->fmt.pix)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-   return get_v4l2_pix_format_mplane(>fmt.pix_mp,
- >fmt.pix_mp);
+   return copy_from_user(>fmt.pix_mp, >fmt.pix_mp,
+ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
return get_v4l2_window32(>fmt.win, >fmt.win);
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
-   return get_v4l2_vbi_format(>fmt.vbi, >fmt.vbi);
+   return copy_from_user(>fmt.vbi, >fmt.vbi,
+ sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-   return get_v4l2_sliced_vbi_format(>fmt.sliced, 
>fmt.sliced);
+   return copy_from_user(>fmt.sliced, >fmt.sliced,
+ sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
default:
printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type 
%d\n",
   kp->type);
@@ -228,20 +173,23 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-   return put_v4l2_pix_format(>fmt.pix, >fmt.pix);
+   return copy_to_user(>fmt.pix, >fmt.pix,
+ 

[PATCH for v4.1 10/14] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha

2018-02-14 Thread Hans Verkuil
From: Daniel Mentz 

commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream.

Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output
overlays.") added the field global_alpha to struct v4l2_window but did
not update the compat layer accordingly. This change adds global_alpha
to struct v4l2_window32 and copies the value for global_alpha back and
forth.

Signed-off-by: Daniel Mentz 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 626a3b345075..88e4f5716387 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,6 +45,7 @@ struct v4l2_window32 {
compat_caddr_t  clips; /* actually struct v4l2_clip32 * */
__u32   clipcount;
compat_caddr_t  bitmap;
+   __u8global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
@@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
-   get_user(kp->clipcount, >clipcount))
+   get_user(kp->clipcount, >clipcount) ||
+   get_user(kp->global_alpha, >global_alpha))
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
@@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
-   put_user(kp->clipcount, >clipcount))
+   put_user(kp->clipcount, >clipcount) ||
+   put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
return 0;
 }
-- 
2.15.1



[PATCH for v4.1 02/14] vb2: V4L2_BUF_FLAG_DONE is set after DQBUF

2018-02-14 Thread Hans Verkuil
From: Ricardo Ribalda 

commit 3171cc2b4eb9831ab4df1d80d0410a945b8bc84e upstream.

According to the doc, V4L2_BUF_FLAG_DONE is cleared after DQBUF:

V4L2_BUF_FLAG_DONE 0x0004  ... After calling the VIDIOC_QBUF or
VIDIOC_DQBUF it is always cleared ...

Unfortunately, it seems that videobuf2 keeps it set after DQBUF. This
can be tested with vivid and dev_debug:

[257604.338082] video1: VIDIOC_DQBUF: 71:33:25.00260479 index=3,
type=vid-cap, flags=0x2004, field=none, sequence=163,
memory=userptr, bytesused=460800, offset/userptr=0x344b000,
length=460800

This patch forces FLAG_DONE to 0 after calling DQBUF.

Reported-by: Dimitrios Katsaros 
Signed-off-by: Ricardo Ribalda Delgado 
Signed-off-by: Hans Verkuil 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/videobuf2-core.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index fd9b252e2b34..079ee4ae9436 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -2119,6 +2119,11 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, 
struct v4l2_buffer *b, bool n
dprintk(1, "dqbuf of buffer %d, with state %d\n",
vb->v4l2_buf.index, vb->state);
 
+   /*
+* After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
+* cleared.
+*/
+   b->flags &= ~V4L2_BUF_FLAG_DONE;
return 0;
 }
 
-- 
2.15.1



[PATCH for v4.1 06/14] media: v4l2-compat-ioctl32.c: avoid sizeof(type)

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream.

Instead of doing sizeof(struct foo) use sizeof(*up). There even were
cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved),
which is very dangerous when the size of the reserved array changes.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 74 +--
 1 file changed, 35 insertions(+), 39 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2a116d671f92..03d1d92a2a8e 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -47,7 +47,7 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
get_user(kp->chromakey, >chromakey) ||
@@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
if (get_user(p, >clips))
return -EFAULT;
uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
kp->clips = kclips;
while (--n >= 0) {
if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
@@ -152,14 +152,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, 
format)))
return -EFAULT;
return __get_v4l2_format32(>format, >format);
@@ -199,14 +199,14 @@ static int __put_v4l2_format32(struct v4l2_format *kp, 
struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 
__user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct 
v4l2_create_buffers32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) 
||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, 
format)) ||
copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
@@ -225,7 +225,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
/* other fields are not set by the user, nor used by the driver */
-   if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
get_user(kp->index, >index))
return -EFAULT;
return 0;
@@ -233,13 +233,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, 
struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct 
v4l2_standard32 __user *up)
 {
-   if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+   if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
put_user(kp->index, >index) ||
copy_to_user(up->id, >id, sizeof(__u64)) ||
-   copy_to_user(up->name, kp->name, 24) ||
+   copy_to_user(up->name, kp->name, sizeof(up->name)) ||
copy_to_user(>frameperiod, >frameperiod, 
sizeof(kp->frameperiod)) ||
put_user(kp->framelines, >framelines) ||
-   copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+   copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return 0;
 }
@@ -287,7 +287,7 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, 
struct v4l2_plane32 __
 
if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
copy_in_user(>data_offset, 

[PATCH for v4.1 08/14] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++-
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 25a61fc27a36..52205d37f97f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
@@ -578,24 +580,39 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   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, >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;
}
+
+   if (!ops->vidioc_query_ext_ctrl)
+   return false;
+
+   return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
+   (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -627,7 +644,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return -EFAULT;
if (get_user(id, >id))
return -EFAULT;
-   if (ctrl_is_pointer(id)) {
+   if (ctrl_is_pointer(file, id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -642,7 +659,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols =
@@ -674,7 +693,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(id))
+   if (ctrl_is_pointer(file, id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -887,7 +906,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);

[PATCH for v4.1 11/14] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream.

put_v4l2_window32() didn't copy back the clip list to userspace.
Drivers can update the clip rectangles, so this should be done.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 59 ++-
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 88e4f5716387..25cf19193c13 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -50,6 +50,11 @@ struct v4l2_window32 {
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip32 __user *uclips;
+   struct v4l2_clip __user *kclips;
+   compat_caddr_t p;
+   u32 n;
+
if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
copy_from_user(>w, >w, sizeof(up->w)) ||
get_user(kp->field, >field) ||
@@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct 
v4l2_window32 __user
return -EFAULT;
if (kp->clipcount > 2048)
return -EINVAL;
-   if (kp->clipcount) {
-   struct v4l2_clip32 __user *uclips;
-   struct v4l2_clip __user *kclips;
-   int n = kp->clipcount;
-   compat_caddr_t p;
+   if (!kp->clipcount) {
+   kp->clips = NULL;
+   return 0;
+   }
 
-   if (get_user(p, >clips))
+   n = kp->clipcount;
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   kclips = compat_alloc_user_space(n * sizeof(*kclips));
+   kp->clips = kclips;
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
return -EFAULT;
-   uclips = compat_ptr(p);
-   kclips = compat_alloc_user_space(n * sizeof(*kclips));
-   kp->clips = kclips;
-   while (--n >= 0) {
-   if (copy_in_user(>c, >c, 
sizeof(uclips->c)))
-   return -EFAULT;
-   if (put_user(n ? kclips + 1 : NULL, >next))
-   return -EFAULT;
-   uclips += 1;
-   kclips += 1;
-   }
-   } else
-   kp->clips = NULL;
+   if (put_user(n ? kclips + 1 : NULL, >next))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 
__user *up)
 {
+   struct v4l2_clip __user *kclips = kp->clips;
+   struct v4l2_clip32 __user *uclips;
+   u32 n = kp->clipcount;
+   compat_caddr_t p;
+
if (copy_to_user(>w, >w, sizeof(kp->w)) ||
put_user(kp->field, >field) ||
put_user(kp->chromakey, >chromakey) ||
put_user(kp->clipcount, >clipcount) ||
put_user(kp->global_alpha, >global_alpha))
return -EFAULT;
+
+   if (!kp->clipcount)
+   return 0;
+
+   if (get_user(p, >clips))
+   return -EFAULT;
+   uclips = compat_ptr(p);
+   while (n--) {
+   if (copy_in_user(>c, >c, sizeof(uclips->c)))
+   return -EFAULT;
+   uclips++;
+   kclips++;
+   }
return 0;
 }
 
-- 
2.15.1



[PATCH for v4.1 01/14] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream.

If the ioctl returned -ENOTTY, then don't bother copying
back the result as there is no point.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index aa407cb5f830..7004477e7ffc 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2552,8 +2552,11 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 
/* Handles IOCTL */
err = func(file, cmd, parg);
-   if (err == -ENOIOCTLCMD)
+   if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
+   goto out;
+   }
+
if (err == 0) {
if (cmd == VIDIOC_DQBUF)
trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
-- 
2.15.1



[PATCH for v4.4 09/14] media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream.

If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops
is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash.
Add a test for !ops to the condition.

All sub-devices that have controls will use the control framework,
so they do not have an equivalent to ops->vidioc_query_ext_ctrl.
Returning false if ops is NULL is the correct thing to do here.

Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer")

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reported-by: Laurent Pinchart 
Reviewed-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2104d3af94f5..0c3949a00570 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -612,7 +612,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 
id)
return ctrl && ctrl->is_ptr;
}
 
-   if (!ops->vidioc_query_ext_ctrl)
+   if (!ops || !ops->vidioc_query_ext_ctrl)
return false;
 
return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
-- 
2.15.1



[PATCH for v4.4 08/14] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer

2018-02-14 Thread Hans Verkuil
From: Hans Verkuil 

commit b8c601e8af2d08f733d74defa8465303391bb930 upstream.

ctrl_is_pointer just hardcoded two known string controls, but that
caused problems when using e.g. custom controls that use a pointer
for the payload.

Reimplement this function: it now finds the v4l2_ctrl (if the driver
uses the control framework) or it calls vidioc_query_ext_ctrl (if the
driver implements that directly).

In both cases it can now check if the control is a pointer control
or not.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++-
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index af197980ab8e..2104d3af94f5 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long 
arg)
@@ -587,24 +589,39 @@ struct v4l2_ext_control32 {
};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-   switch (id) {
-   case V4L2_CID_RDS_TX_PS_NAME:
-   case V4L2_CID_RDS_TX_RADIO_TEXT:
-   return 1;
-   default:
-   return 0;
+   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, >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;
}
+
+   if (!ops->vidioc_query_ext_ctrl)
+   return false;
+
+   return !ops->vidioc_query_ext_ctrl(file, fh, ) &&
+   (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
@@ -636,7 +653,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return -EFAULT;
if (get_user(id, >id))
return -EFAULT;
-   if (ctrl_is_pointer(id)) {
+   if (ctrl_is_pointer(file, id)) {
void __user *s;
 
if (get_user(p, >string))
@@ -651,7 +668,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct 
v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+  struct v4l2_ext_controls *kp,
+  struct v4l2_ext_controls32 __user *up)
 {
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols =
@@ -683,7 +702,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls 
*kp, struct v4l2_ext
/* Do not modify the pointer when copying a pointer control.
   The contents of the pointer was changed, not the pointer
   itself. */
-   if (ctrl_is_pointer(id))
+   if (ctrl_is_pointer(file, id))
size -= sizeof(ucontrols->value64);
if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
@@ -897,7 +916,7 @@ static long do_video_ioctl(struct file *file, unsigned int 
cmd, unsigned long ar
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
-   err = get_v4l2_ext_controls32(, up);
+   err = get_v4l2_ext_controls32(file, , up);

exposing a large-ish calibration table through V4L2?

2018-02-14 Thread Florian Echtler
Hello Hans,

I've picked up work on the sur40 driver again recently. There is one major
feature left that is currently unsupported by the Linux driver, which is the
hardware-based calibration.

The internal device memory contains a table with two bytes for each sensor pixel
(i.e. 960x540x2 = 1036800 bytes) that basically provide individual black and
white levels per-pixel that are used in preprocessing. The table can either be
set externally, or the sensor can be covered with a black/white surface and a
custom command triggers an internal calibration.

AFAICT the usual V4L2 controls are unsuitable for this sort of data; do you have
any suggestions on how to approach this? Maybe something like a custom IOCTL?

Best regards, Florian
-- 
SENT FROM MY DEC VT50 TERMINAL



signature.asc
Description: OpenPGP digital signature


[PATCH v2] videodev2.h: add helper to validate colorspace

2018-02-14 Thread Niklas Söderlund
There is no way for drivers to validate a colorspace value, which could
be provided by user-space by VIDIOC_S_FMT for example. Add a helper to
validate that the colorspace value is part of enum v4l2_colorspace.

Signed-off-by: Niklas Söderlund 
---
 include/uapi/linux/videodev2.h | 4 
 1 file changed, 4 insertions(+)

Hi,

I hope this is the correct header to add this helper to. I think it's
since if it's in uapi not only can v4l2 drivers use it but tools like
v4l-compliance gets access to it and can be updated to use this instead
of the hard-coded check of just < 0xff as it was last time I checked.

* Changes since v1
- Cast colorspace to u32 as suggested by Sakari and only check the upper 
  boundary to address a potential issue brought up by Laurent if the 
  data type tested is u32 which is not uncommon:

enum.c:30:16: warning: comparison of unsigned expression >= 0 is always true
[-Wtype-limits]
  return V4L2_COLORSPACE_IS_VALID(colorspace);

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 9827189651801e12..1f27c0f4187cbded 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -238,6 +238,10 @@ enum v4l2_colorspace {
V4L2_COLORSPACE_DCI_P3= 12,
 };
 
+/* Determine if a colorspace is defined in enum v4l2_colorspace */
+#define V4L2_COLORSPACE_IS_VALID(colorspace)   \
+   ((u32)(colorspace) <= V4L2_COLORSPACE_DCI_P3)
+
 /*
  * Determine how COLORSPACE_DEFAULT should map to a proper colorspace.
  * This depends on whether this is a SDTV image (use SMPTE 170M), an
-- 
2.16.1



Re: [PATCH v2] videodev2.h: add helper to validate colorspace

2018-02-14 Thread Sakari Ailus
On Wed, Feb 14, 2018 at 11:36:43AM +0100, Niklas Söderlund wrote:
> There is no way for drivers to validate a colorspace value, which could
> be provided by user-space by VIDIOC_S_FMT for example. Add a helper to
> validate that the colorspace value is part of enum v4l2_colorspace.
> 
> Signed-off-by: Niklas Söderlund 

Acked-by: Sakari Ailus 

> ---
>  include/uapi/linux/videodev2.h | 4 
>  1 file changed, 4 insertions(+)
> 
> Hi,
> 
> I hope this is the correct header to add this helper to. I think it's
> since if it's in uapi not only can v4l2 drivers use it but tools like
> v4l-compliance gets access to it and can be updated to use this instead
> of the hard-coded check of just < 0xff as it was last time I checked.
> 
> * Changes since v1
> - Cast colorspace to u32 as suggested by Sakari and only check the upper 
>   boundary to address a potential issue brought up by Laurent if the 
>   data type tested is u32 which is not uncommon:
> 
> enum.c:30:16: warning: comparison of unsigned expression >= 0 is always 
> true
> [-Wtype-limits]
>   return V4L2_COLORSPACE_IS_VALID(colorspace);
> 
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 9827189651801e12..1f27c0f4187cbded 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -238,6 +238,10 @@ enum v4l2_colorspace {
>   V4L2_COLORSPACE_DCI_P3= 12,
>  };
>  
> +/* Determine if a colorspace is defined in enum v4l2_colorspace */
> +#define V4L2_COLORSPACE_IS_VALID(colorspace) \
> + ((u32)(colorspace) <= V4L2_COLORSPACE_DCI_P3)
> +
>  /*
>   * Determine how COLORSPACE_DEFAULT should map to a proper colorspace.
>   * This depends on whether this is a SDTV image (use SMPTE 170M), an
> -- 
> 2.16.1
> 

-- 
Sakari Ailus
e-mail: sakari.ai...@iki.fi


Re: i.MX53 using imx-media to capture analog video through ADV7180

2018-02-14 Thread Fabio Estevam
[Adding Steve and Philipp in case they could provide some suggestions]

On Wed, Feb 14, 2018 at 1:21 PM, Matthew Starr  wrote:
> I have successfully modified device tree files in the mainline 4.15.1 kernel 
> to get a display product using the i.MX53 processor to initialize the 
> imx-media drivers.  I think up to this point they have only been tested on 
> i.MX6 processors.  I am using two ADV7180 analog capture chips, one per CSI 
> port, on this display product.
>
> I have everything initialize successfully at boot, but I am unable to get the 
> media-ctl command to link the ADV7180 devices to the CSI ports.  I used the 
> following website as guidance of how to setup the links between media devices:
> https://linuxtv.org/downloads/v4l-dvb-apis/v4l-drivers/imx.html
>
> When trying to link the ADV7180 chip to a CSI port, I use the following 
> command and get the result below:
>
> media-ctl -v -l "'adv7180 1-0021':0->'ipu1_csi0':0[1]"
>
> No link between "adv7180 1-0021":0 and "ipu1_csi0":0
> media_parse_setup_link: Unable to parse link
> Unable to parse link: Invalid argument (22)
>
> How do I get the ADV7180 and CSI port on the i.MX53 processor to link?
>
> The difference for the i.MX53 compared to the i.MX6 processor is that there 
> is only one IPU and no mipi support, so my device tree does not use any 
> video-mux or mux devices.  Could this have something to do with why I can't 
> link the ADV7180 to the CSI port?
>
> Here is the output of the "media-ctl -p -v" command:
>
> Opening media device /dev/media0
> Enumerating entities
> looking up device: 81:10
> looking up device: 81:11
> looking up device: 81:12
> looking up device: 81:4
> looking up device: 81:13
> looking up device: 81:5
> looking up device: 81:14
> looking up device: 81:15
> looking up device: 81:16
> looking up device: 81:17
> looking up device: 81:6
> looking up device: 81:18
> looking up device: 81:7
> looking up device: 81:19
> looking up device: 81:20
> looking up device: 81:8
> looking up device: 81:21
> looking up device: 81:9
> Found 18 entities
> Enumerating pads and links
> Media controller API version 4.15.1
>
> Media device information
> 
> driver  imx-media
> model   imx-media
> serial
> bus info
> hw revision 0x0
> driver version  4.15.1
>
> Device topology
> - entity 1: adv7180 1-0021 (1 pad, 0 link)
> type V4L2 subdev subtype Unknown flags 20004
> device node name /dev/v4l-subdev0
> pad0: Source
> [fmt:UYVY8_2X8/720x480 field:interlaced]
>
> - entity 3: adv7180 1-0020 (1 pad, 0 link)
> type V4L2 subdev subtype Unknown flags 20004
> device node name /dev/v4l-subdev1
> pad0: Source
> [fmt:UYVY8_2X8/720x480 field:interlaced]
>
> - entity 5: ipu1_csi1 (3 pads, 3 links)
> type V4L2 subdev subtype Unknown flags 0
> device node name /dev/v4l-subdev2
> pad0: Sink
> [fmt:UYVY8_2X8/640x480 field:none
>  crop.bounds:(0,0)/640x480
>  crop:(0,0)/640x480
>  compose.bounds:(0,0)/640x480
>  compose:(0,0)/640x480]
> pad1: Source
> [fmt:AYUV8_1X32/640x480 field:none]
> -> "ipu1_ic_prp":0 []
> -> "ipu1_vdic":0 []
> pad2: Source
> [fmt:AYUV8_1X32/640x480 field:none]
> -> "ipu1_csi1 capture":0 []
>
> - entity 9: ipu1_csi1 capture (1 pad, 1 link)
> type Node subtype V4L flags 0
> device node name /dev/video4
> pad0: Sink
> <- "ipu1_csi1":2 []
>
> - entity 15: ipu1_csi0 (3 pads, 3 links)
>  type V4L2 subdev subtype Unknown flags 0
>  device node name /dev/v4l-subdev3
> pad0: Sink
> [fmt:UYVY8_2X8/640x480 field:none
>  crop.bounds:(0,0)/640x480
>  crop:(0,0)/640x480
>  compose.bounds:(0,0)/640x480
>  compose:(0,0)/640x480]
> pad1: Source
> [fmt:AYUV8_1X32/640x480 field:none]
> -> "ipu1_ic_prp":0 []
> -> "ipu1_vdic":0 [ENABLED]
> pad2: Source
> [fmt:AYUV8_1X32/640x480 field:none]
> -> "ipu1_csi0 capture":0 []
>
> - entity 19: ipu1_csi0 capture (1 pad, 1 link)
>  type Node subtype V4L flags 0
>  device node name /dev/video5
> pad0: Sink
> <- "ipu1_csi0":2 []
>
> - entity 25: ipu1_ic_prp (3 pads, 5 links)
>  type V4L2 subdev subtype Unknown flags 0
>  device node name /dev/v4l-subdev4
> pad0: Sink
> [fmt:AYUV8_1X32/640x480 field:none]
> <- "ipu1_csi1":1 []
> <- "ipu1_csi0":1 []
> <- "ipu1_vdic":2 [ENABLED]
> pad1: Source
> 

Re: [PATCH v4 16/18] scripts: kernel-doc: improve nested logic to handle multiple identifiers

2018-02-14 Thread Jani Nikula
On Mon, 18 Dec 2017, Mauro Carvalho Chehab  wrote:
> It is possible to use nested structs like:
>
> struct {
>   struct {
>   void *arg1;
>   } st1, st2, *st3, st4;
> };
>
> Handling it requires to split each parameter. Change the logic
> to allow such definitions.
>
> In order to test the new nested logic, the following file
> was used to test

Hi Mauro, resurrecting an old thread...

So this was a great improvement to documenting nested structs. However,
it looks like it only supports describing the nested structs at the top
level comment, and fails for inline documentation comments.

For example, in v4.16-rc1:

$ scripts/kernel-doc -none drivers/gpu/drm/i915/intel_dpio_phy.c
drivers/gpu/drm/i915/intel_dpio_phy.c:154: warning: Function parameter or 
member 'channel.port' not described in 'bxt_ddi_phy_info'

The struct in question is:

/**
 * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy
 */
struct bxt_ddi_phy_info {
/* [some members removed] */

/**
 * @channel: struct containing per channel information.
 */
struct {
/**
 * @port: which port maps to this channel.
 */
enum port port;
} channel[2];
};

Apparently the only way to currently do this is to add channel.port at
the top level:

/**
 * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy
 * @channel.port: which port maps to this channel.
 */

Which is less than perfect if you have everything else described
inline. :(

BR,
Jani.


>
> 
> struct foo { int a; }; /* Just to avoid errors if compiled */
>
> /**
>  * struct my_struct - a struct with nested unions and structs
>  * @arg1: first argument of anonymous union/anonymous struct
>  * @arg2: second argument of anonymous union/anonymous struct
>  * @arg1b: first argument of anonymous union/anonymous struct
>  * @arg2b: second argument of anonymous union/anonymous struct
>  * @arg3: third argument of anonymous union/anonymous struct
>  * @arg4: fourth argument of anonymous union/anonymous struct
>  * @bar.st1.arg1: first argument of struct st1 on union bar
>  * @bar.st1.arg2: second argument of struct st1 on union bar
>  * @bar.st1.bar1: bar1 at st1
>  * @bar.st1.bar2: bar2 at st1
>  * @bar.st2.arg1: first argument of struct st2 on union bar
>  * @bar.st2.arg2: second argument of struct st2 on union bar
>  * @bar.st3.arg2: second argument of struct st3 on union bar
>  * @f1: nested function on anonimous union/struct
>  * @bar.st2.f2: nested function on named union/struct
>  */
> struct my_struct {
>/* Anonymous union/struct*/
>union {
>   struct {
>   char arg1 : 1;
>   char arg2 : 3;
>   };
>struct {
>int arg1b;
>int arg2b;
>};
>struct {
>void *arg3;
>int arg4;
>int (*f1)(char foo, int bar);
>};
>};
>union {
>struct {
>int arg1;
>int arg2;
>  struct foo bar1, *bar2;
>} st1;   /* bar.st1 is undocumented, cause a warning */
>struct {
>void *arg1;  /* bar.st3.arg1 is undocumented, cause a warning */
>   int arg2;
>   int (*f2)(char foo, int bar); /* bar.st3.fn2 is undocumented, cause 
> a warning */
>} st2, st3, *st4;
>int (*f3)(char foo, int bar); /* f3 is undocumented, cause a warning */
>} bar;   /* bar is undocumented, cause a warning */
>
>/* private: */
>int undoc_privat;/* is undocumented but private, no warning */
>
>/* public: */
>int undoc_public;/* is undocumented, cause a warning */
> };
> 
>
> It produces the following warnings, as expected:
>
> test2.h:57: warning: Function parameter or member 'bar' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st1' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st2' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st3' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st3.arg1' not 
> described in 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st3.f2' not described 
> in 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st4' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st4.arg1' not 
> described in 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st4.arg2' not 
> described in 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.st4.f2' not described 
> in 'my_struct'
> test2.h:57: warning: Function parameter or member 'bar.f3' not described in 
> 'my_struct'
> test2.h:57: warning: Function parameter or member 'undoc_public' not 
> described in 'my_struct'
>
> Suggested-by: Markus Heiser 
> 

Re: [PATCHv2 3/9] staging: atomisp: Kill subdev s_parm abuse

2018-02-14 Thread Mauro Carvalho Chehab
Sakari,

Em Mon, 22 Jan 2018 13:31:19 +0100
Hans Verkuil  escreveu:

> From: Sakari Ailus 
> 
> Remove sensor driver's interface that made use of use case specific
> knowledge of platform capabilities.

Could you better describe it? What s_param abuse?
What happens after this patch? It seems that atomISP relies on
gc0310_res. So, I would be expecting that a patch removing
s_param would be also adding/changing other parts of the code
accordingly, in order to get rid of that as a hole (or initialize
it somewhere else).

Regards,
Mauro

> 
> Signed-off-by: Sakari Ailus 
> Signed-off-by: Hans Verkuil 
> ---
>  drivers/staging/media/atomisp/i2c/atomisp-gc0310.c | 26 -
>  drivers/staging/media/atomisp/i2c/atomisp-gc2235.c | 26 -
>  drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 29 -
>  drivers/staging/media/atomisp/i2c/atomisp-ov2722.c | 26 -
>  drivers/staging/media/atomisp/i2c/gc0310.h | 43 --
>  drivers/staging/media/atomisp/i2c/gc2235.h |  1 -
>  drivers/staging/media/atomisp/i2c/ov2680.h | 68 
> --
>  .../media/atomisp/i2c/ov5693/atomisp-ov5693.c  | 27 -
>  .../media/atomisp/pci/atomisp2/atomisp_cmd.c   |  9 +--
>  .../media/atomisp/pci/atomisp2/atomisp_subdev.c| 12 +---
>  10 files changed, 3 insertions(+), 264 deletions(-)
> 
> diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c 
> b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
> index 61b7598469eb..572c9127c24d 100644
> --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
> +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
> @@ -1224,37 +1224,12 @@ static int gc0310_g_parm(struct v4l2_subdev *sd,
>   if (dev->fmt_idx >= 0 && dev->fmt_idx < N_RES) {
>   param->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
>   param->parm.capture.timeperframe.numerator = 1;
> - param->parm.capture.capturemode = dev->run_mode;
>   param->parm.capture.timeperframe.denominator =
>   gc0310_res[dev->fmt_idx].fps;
>   }
>   return 0;
>  }
>  
> -static int gc0310_s_parm(struct v4l2_subdev *sd,
> - struct v4l2_streamparm *param)
> -{
> - struct gc0310_device *dev = to_gc0310_sensor(sd);
> - dev->run_mode = param->parm.capture.capturemode;
> -
> - mutex_lock(>input_lock);
> - switch (dev->run_mode) {
> - case CI_MODE_VIDEO:
> - gc0310_res = gc0310_res_video;
> - N_RES = N_RES_VIDEO;
> - break;
> - case CI_MODE_STILL_CAPTURE:
> - gc0310_res = gc0310_res_still;
> - N_RES = N_RES_STILL;
> - break;
> - default:
> - gc0310_res = gc0310_res_preview;
> - N_RES = N_RES_PREVIEW;
> - }
> - mutex_unlock(>input_lock);
> - return 0;
> -}
> -
>  static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
>  struct v4l2_subdev_frame_interval *interval)
>  {
> @@ -1314,7 +1289,6 @@ static const struct v4l2_subdev_sensor_ops 
> gc0310_sensor_ops = {
>  static const struct v4l2_subdev_video_ops gc0310_video_ops = {
>   .s_stream = gc0310_s_stream,
>   .g_parm = gc0310_g_parm,
> - .s_parm = gc0310_s_parm,
>   .g_frame_interval = gc0310_g_frame_interval,
>  };
>  
> diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c 
> b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
> index d8de46da64ae..2bc179f3afe5 100644
> --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
> +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c
> @@ -964,37 +964,12 @@ static int gc2235_g_parm(struct v4l2_subdev *sd,
>   if (dev->fmt_idx >= 0 && dev->fmt_idx < N_RES) {
>   param->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
>   param->parm.capture.timeperframe.numerator = 1;
> - param->parm.capture.capturemode = dev->run_mode;
>   param->parm.capture.timeperframe.denominator =
>   gc2235_res[dev->fmt_idx].fps;
>   }
>   return 0;
>  }
>  
> -static int gc2235_s_parm(struct v4l2_subdev *sd,
> - struct v4l2_streamparm *param)
> -{
> - struct gc2235_device *dev = to_gc2235_sensor(sd);
> - dev->run_mode = param->parm.capture.capturemode;
> -
> - mutex_lock(>input_lock);
> - switch (dev->run_mode) {
> - case CI_MODE_VIDEO:
> - gc2235_res = gc2235_res_video;
> - N_RES = N_RES_VIDEO;
> - break;
> - case CI_MODE_STILL_CAPTURE:
> - gc2235_res = gc2235_res_still;
> - N_RES = N_RES_STILL;
> - break;
> - default:
> - gc2235_res = gc2235_res_preview;
> - N_RES = N_RES_PREVIEW;
> - }
> - mutex_unlock(>input_lock);
> - return 0;
> -}
> -
>  static int 

Re: [PATCH v7 2/2] v4l: cadence: Add Cadence MIPI-CSI2 RX driver

2018-02-14 Thread Laurent Pinchart
Hi Maxime,

On Wednesday, 14 February 2018 15:19:33 EET Maxime Ripard wrote:
> On Thu, Feb 08, 2018 at 08:17:19PM +0200, Laurent Pinchart wrote:
> >> +  /*
> >> +   * Create a static mapping between the CSI virtual channels
> >> +   * and the output stream.
> >> +   *
> >> +   * This should be enhanced, but v4l2 lacks the support for
> >> +   * changing that mapping dynamically.
> >> +   *
> >> +   * We also cannot enable and disable independant streams here,
> >> +   * hence the reference counting.
> >> +   */
> > 
> > If you start all streams in one go, will s_stream(1) be called multiple
> > times ? If not, you could possibly skip the whole reference counting and
> > avoid locking.
> 
> I guess that while we should expect the CSI-2 bus to be always
> enabled, the downstream camera interface could be shutdown
> independently, so I guess s_stream would be called each time one is
> brought up or brought down?

That's the idea. However, we don't have support for multiplexed streams in 
mainline yet, so there's no way it can be implemented today in your driver.

-- 
Regards,

Laurent Pinchart



Re: [PATCH v10 6/8] media: i2c: Add TDA1997x HDMI receiver driver

2018-02-14 Thread Tim Harvey
On Wed, Feb 14, 2018 at 6:08 AM, Hans Verkuil  wrote:
> Hi Tim,
>
> On 12/02/18 23:27, Tim Harvey wrote:
>> On Fri, Feb 9, 2018 at 12:08 AM, Hans Verkuil  wrote:
>>> Hi Tim,
>>>
>>> We're almost there. Two more comments:
>>>
>>> On 02/09/2018 07:32 AM, Tim Harvey wrote:
 +static int
 +tda1997x_detect_std(struct tda1997x_state *state,
 + struct v4l2_dv_timings *timings)
 +{
 + struct v4l2_subdev *sd = >sd;
 + u32 vper;
 + u16 hper;
 + u16 hsper;
 + int i;
 +
 + /*
 +  * Read the FMT registers
 +  *   REG_V_PER: Period of a frame (or two fields) in MCLK(27MHz) 
 cycles
 +  *   REG_H_PER: Period of a line in MCLK(27MHz) cycles
 +  *   REG_HS_WIDTH: Period of horiz sync pulse in MCLK(27MHz) cycles
 +  */
 + vper = io_read24(sd, REG_V_PER) & MASK_VPER;
 + hper = io_read16(sd, REG_H_PER) & MASK_HPER;
 + hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
 + if (!vper || !hper || !hsper)
 + return -ENOLINK;
>>>
>>> See my comment for g_input_status below. This condition looks more like a
>>> ENOLCK.
>>>
>>> Or perhaps it should be:
>>>
>>> if (!vper && !hper && !hsper)
>>> return -ENOLINK;
>>> if (!vper || !hper || !hsper)
>>> return -ENOLCK;
>>>
>>> I would recommend that you test a bit with no signal and a bad signal 
>>> (perhaps
>>> one that uses a pixelclock that is too high for this device?).
>>
>> I can't figure out how to produce a signal that can't be locked onto
>> with what I have available.
>
> Are you using a signal generator or just a laptop or something similar as the
> source?
>
> Without a good signal generator it is tricky to test this. A very long HDMI
> cable would likely do it. But for 1080p60 you probably need 20 meters or
> more.
>

I'm using a Marshall V-SG4K-HDI
(http://www.lcdracks.com/racks/DLW/V-SG4K-HDI-signal-generator.php).
It does support 'user defined timings' (see
http://www.lcdracks.com/racks/pdf-pages/instruction_sheets/V-SG4K-HDI_Manual-web.pdf
Timings Details Menu page) and it looks like the max pixel-clock is
300MHz so perhaps I can create a timing that can't be locked onto that
way.

The TDA19971 datasheet
(http://tharvey/src/nxp/tda1997x/TDA19971-datasheet-rev3.pdf) says it
supports:
- All HDTV formats up to 1920x1080p at 50/60 Hz with support for
reduced blanking
- 3D formats including all primary formats up to 1920x1080p at 30 Hz
Frame Packing and 1920x1080p at 60 Hz Side-by-Side and Top-and-Bottom
- PC formats up to UXGA (1600x1200p at 60 Hz) and WUXGA (1920x1200p at 60 Hz)

>>

>>>
 +static int
 +tda1997x_g_input_status(struct v4l2_subdev *sd, u32 *status)
 +{
 + struct tda1997x_state *state = to_state(sd);
 + u32 vper;
 + u16 hper;
 + u16 hsper;
 +
 + mutex_lock(>lock);
 + v4l2_dbg(1, debug, sd, "inputs:%d/%d\n",
 +  state->input_detect[0], state->input_detect[1]);
 + if (state->input_detect[0] || state->input_detect[1])
>>>
>>> I'm confused. This device has two HDMI inputs?
>>>
>>> Does 'detecting input' equate to 'I see a signal and I am locked'?
>>> I gather from the irq function that sets these values that it is closer
>>> to 'I see a signal' and that 'I am locked' is something you would test
>>> by looking at the vper/hper/hsper.
>>
>> The TDA19972 and/or TDA19973 has an A and B input but only a single
>> output. I'm not entirely clear if/how to select between the two and I
>> don't have proper documentation for the three chips.
>>
>> The TDA19971 which I have on my board only has 1 input which is
>> reported as the 'A' input. I can likely nuke the stuff looking at the
>> B input and/or put some qualifiers around it but I didn't want to
>> remove code that was derived from some vendor code that might help
>> support the other chips in the future. So I would rather like to leave
>> the 'if A or B' stuff.
>
> OK. Can you add a comment somewhere in the driver about this?
>
> It sounds like it is similar to what the adv7604 has: several inputs but
> only one is used for streaming. But the EDID is made available on both inputs.
>

sure, I will comment about it. I believe that is the way the it works as well.

>>>
 + *status = 0;
 + else {
 + vper = io_read24(sd, REG_V_PER) & MASK_VPER;
 + hper = io_read16(sd, REG_H_PER) & MASK_HPER;
 + hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
 + v4l2_dbg(1, debug, sd, "timings:%d/%d/%d\n", vper, hper, 
 hsper);
 + if (!vper || !hper || !hsper)
 + *status |= V4L2_IN_ST_NO_SYNC;
 + else
 + *status |= V4L2_IN_ST_NO_SIGNAL;
>>>
>>> So if we have valid vper, hper and hsper, then there is no signal? That 
>>> 

  1   2   >