blob: 4312935f1dfcec4ae13230dbaaa3ec5aa227f891 [file] [log] [blame]
Philippe De Muytercf664a62006-01-09 15:24:59 -02001/*
2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
4 *
5 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
Pavel Macheka2531292010-07-18 14:27:13 +02008 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
Philippe De Muytercf664a62006-01-09 15:24:59 -02009 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
Hans Verkuil92f45ba2008-12-21 10:35:25 -030010 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
Philippe De Muytercf664a62006-01-09 15:24:59 -020011 *
12 * These routines maintain argument size conversion between 32bit and 64bit
13 * ioctls.
14 */
15
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020016#include <linux/compat.h>
Nickolay V. Shmyrev133b7352006-01-09 15:24:58 -020017#include <linux/module.h>
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -030018#include <linux/videodev2.h>
Hans Verkuiled45ce22012-08-10 06:07:12 -030019#include <linux/v4l2-subdev.h>
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -030020#include <media/v4l2-dev.h>
Hans Verkuilb8c601e2018-01-24 05:30:59 -050021#include <media/v4l2-fh.h>
22#include <media/v4l2-ctrls.h>
Mauro Carvalho Chehab28644622008-07-20 20:26:54 -030023#include <media/v4l2-ioctl.h>
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020024
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040025/* Use the same argument order as copy_in_user */
26#define assign_in_user(to, from) \
27({ \
28 typeof(*from) __assign_tmp; \
29 \
30 get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
31})
32
Hans Verkuil069b7472008-12-30 07:04:34 -030033static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020034{
Hans Verkuil069b7472008-12-30 07:04:34 -030035 long ret = -ENOIOCTLCMD;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020036
Philippe De Muyter13d133b2006-01-09 15:25:00 -020037 if (file->f_op->unlocked_ioctl)
38 ret = file->f_op->unlocked_ioctl(file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020039
40 return ret;
41}
42
43
Hans Verkuild1f81da2008-10-22 00:04:45 -030044struct v4l2_clip32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -020045 struct v4l2_rect c;
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -050046 compat_caddr_t next;
Philippe De Muytercf664a62006-01-09 15:24:59 -020047};
48
Hans Verkuild1f81da2008-10-22 00:04:45 -030049struct v4l2_window32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -020050 struct v4l2_rect w;
Mauro Carvalho Chehab4a3fad72018-01-04 06:47:28 -050051 __u32 field; /* enum v4l2_field */
Philippe De Muytercf664a62006-01-09 15:24:59 -020052 __u32 chromakey;
53 compat_caddr_t clips; /* actually struct v4l2_clip32 * */
54 __u32 clipcount;
55 compat_caddr_t bitmap;
Daniel Mentz025a26f2017-08-03 18:03:10 -040056 __u8 global_alpha;
Philippe De Muytercf664a62006-01-09 15:24:59 -020057};
58
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040059static int get_v4l2_window32(struct v4l2_window __user *kp,
60 struct v4l2_window32 __user *up,
61 void __user *aux_buf, u32 aux_space)
Philippe De Muytercf664a62006-01-09 15:24:59 -020062{
Hans Verkuila751be52018-01-24 06:03:08 -050063 struct v4l2_clip32 __user *uclips;
64 struct v4l2_clip __user *kclips;
65 compat_caddr_t p;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040066 u32 clipcount;
Hans Verkuila751be52018-01-24 06:03:08 -050067
Hans Verkuil333b1e92018-01-24 05:01:31 -050068 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040069 copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
70 assign_in_user(&kp->field, &up->field) ||
71 assign_in_user(&kp->chromakey, &up->chromakey) ||
72 assign_in_user(&kp->global_alpha, &up->global_alpha) ||
73 get_user(clipcount, &up->clipcount) ||
74 put_user(clipcount, &kp->clipcount))
Hans Verkuilb7b957d2018-01-24 04:35:48 -050075 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040076 if (clipcount > 2048)
Philippe De Muytercf664a62006-01-09 15:24:59 -020077 return -EINVAL;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040078 if (!clipcount)
79 return put_user(NULL, &kp->clips);
Hans Verkuila751be52018-01-24 06:03:08 -050080
Hans Verkuila751be52018-01-24 06:03:08 -050081 if (get_user(p, &up->clips))
82 return -EFAULT;
83 uclips = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040084 if (aux_space < clipcount * sizeof(*kclips))
85 return -EFAULT;
86 kclips = aux_buf;
87 if (put_user(kclips, &kp->clips))
88 return -EFAULT;
89
90 while (clipcount--) {
Hans Verkuila751be52018-01-24 06:03:08 -050091 if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
92 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -040093 if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
Hans Verkuila751be52018-01-24 06:03:08 -050094 return -EFAULT;
95 uclips++;
96 kclips++;
97 }
Philippe De Muytercf664a62006-01-09 15:24:59 -020098 return 0;
99}
100
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400101static int put_v4l2_window32(struct v4l2_window __user *kp,
102 struct v4l2_window32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200103{
Mauro Carvalho Chehab85ea29f2018-03-28 13:59:22 -0400104 struct v4l2_clip __user *kclips;
Hans Verkuila751be52018-01-24 06:03:08 -0500105 struct v4l2_clip32 __user *uclips;
Hans Verkuila751be52018-01-24 06:03:08 -0500106 compat_caddr_t p;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400107 u32 clipcount;
Hans Verkuila751be52018-01-24 06:03:08 -0500108
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400109 if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
110 assign_in_user(&up->field, &kp->field) ||
111 assign_in_user(&up->chromakey, &kp->chromakey) ||
112 assign_in_user(&up->global_alpha, &kp->global_alpha) ||
113 get_user(clipcount, &kp->clipcount) ||
114 put_user(clipcount, &up->clipcount))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500115 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400116 if (!clipcount)
Hans Verkuila751be52018-01-24 06:03:08 -0500117 return 0;
118
Mauro Carvalho Chehab85ea29f2018-03-28 13:59:22 -0400119 if (get_user(kclips, &kp->clips))
120 return -EFAULT;
Hans Verkuila751be52018-01-24 06:03:08 -0500121 if (get_user(p, &up->clips))
122 return -EFAULT;
123 uclips = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400124 while (clipcount--) {
Hans Verkuila751be52018-01-24 06:03:08 -0500125 if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
126 return -EFAULT;
127 uclips++;
128 kclips++;
129 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200130 return 0;
131}
132
Hans Verkuild1f81da2008-10-22 00:04:45 -0300133struct v4l2_format32 {
Sakari Ailus6016af82012-05-10 02:02:07 -0300134 __u32 type; /* enum v4l2_buf_type */
Hans Verkuild1f81da2008-10-22 00:04:45 -0300135 union {
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300136 struct v4l2_pix_format pix;
Pawel Osciak52a30822010-07-29 14:56:47 -0300137 struct v4l2_pix_format_mplane pix_mp;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300138 struct v4l2_window32 win;
139 struct v4l2_vbi_format vbi;
140 struct v4l2_sliced_vbi_format sliced;
Hans Verkuild5beb672015-09-17 06:46:04 -0300141 struct v4l2_sdr_format sdr;
Laurent Pinchartfb9ffa62016-04-12 19:40:46 -0300142 struct v4l2_meta_format meta;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300143 __u8 raw_data[200]; /* user-defined */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200144 } fmt;
145};
146
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300147/**
148 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
149 * @index: on return, index of the first created buffer
150 * @count: entry: number of requested buffers,
151 * return: number of created buffers
152 * @memory: buffer memory type
153 * @format: frame format, for which buffers are requested
154 * @reserved: future extensions
155 */
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300156struct v4l2_create_buffers32 {
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300157 __u32 index;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300158 __u32 count;
Sakari Ailus6016af82012-05-10 02:02:07 -0300159 __u32 memory; /* enum v4l2_memory */
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300160 struct v4l2_format32 format;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300161 __u32 reserved[8];
162};
163
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400164static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200165{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400166 u32 type;
167
168 if (get_user(type, &up->type))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300169 return -EFAULT;
170
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400171 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200172 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400173 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
174 u32 clipcount;
175
176 if (get_user(clipcount, &up->fmt.win.clipcount))
177 return -EFAULT;
178 if (clipcount > 2048)
179 return -EINVAL;
180 *size = clipcount * sizeof(struct v4l2_clip);
181 return 0;
182 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200183 default:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400184 *size = 0;
185 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200186 }
187}
188
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400189static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200190{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500191 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300192 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400193 return __bufsize_v4l2_format(up, size);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300194}
195
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400196static int __get_v4l2_format32(struct v4l2_format __user *kp,
197 struct v4l2_format32 __user *up,
198 void __user *aux_buf, u32 aux_space)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300199{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400200 u32 type;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300201
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400202 if (get_user(type, &up->type) || put_user(type, &kp->type))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300203 return -EFAULT;
204
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400205 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200206 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300207 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400208 return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
Hans Verkuil486c5212018-01-24 04:45:29 -0500209 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
Pawel Osciak52a30822010-07-29 14:56:47 -0300210 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
211 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400212 return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
Hans Verkuil486c5212018-01-24 04:45:29 -0500213 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200214 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300215 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400216 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
217 aux_buf, aux_space);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200218 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300219 case V4L2_BUF_TYPE_VBI_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400220 return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
Hans Verkuil486c5212018-01-24 04:45:29 -0500221 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300222 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
223 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400224 return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
Hans Verkuil486c5212018-01-24 04:45:29 -0500225 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
Hans Verkuild5beb672015-09-17 06:46:04 -0300226 case V4L2_BUF_TYPE_SDR_CAPTURE:
Antti Palosaari9effc722015-10-10 13:51:00 -0300227 case V4L2_BUF_TYPE_SDR_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400228 return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
Hans Verkuil486c5212018-01-24 04:45:29 -0500229 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
Laurent Pinchartfb9ffa62016-04-12 19:40:46 -0300230 case V4L2_BUF_TYPE_META_CAPTURE:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400231 return copy_in_user(&kp->fmt.meta, &up->fmt.meta,
Hans Verkuil486c5212018-01-24 04:45:29 -0500232 sizeof(kp->fmt.meta)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200233 default:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300234 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200235 }
236}
237
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400238static int get_v4l2_format32(struct v4l2_format __user *kp,
239 struct v4l2_format32 __user *up,
240 void __user *aux_buf, u32 aux_space)
241{
242 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
243 return -EFAULT;
244 return __get_v4l2_format32(kp, up, aux_buf, aux_space);
245}
246
247static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
248 u32 *size)
249{
250 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
251 return -EFAULT;
252 return __bufsize_v4l2_format(&up->format, size);
253}
254
255static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
256 struct v4l2_create_buffers32 __user *up,
257 void __user *aux_buf, u32 aux_space)
258{
259 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
260 copy_in_user(kp, up,
261 offsetof(struct v4l2_create_buffers32, format)))
262 return -EFAULT;
263 return __get_v4l2_format32(&kp->format, &up->format,
264 aux_buf, aux_space);
265}
266
267static int __put_v4l2_format32(struct v4l2_format __user *kp,
268 struct v4l2_format32 __user *up)
269{
270 u32 type;
271
272 if (get_user(type, &kp->type))
273 return -EFAULT;
274
275 switch (type) {
276 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
277 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
278 return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
279 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
280 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
281 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
282 return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
283 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
284 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
285 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
286 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
287 case V4L2_BUF_TYPE_VBI_CAPTURE:
288 case V4L2_BUF_TYPE_VBI_OUTPUT:
289 return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
290 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
291 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
292 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
293 return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
294 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
295 case V4L2_BUF_TYPE_SDR_CAPTURE:
296 case V4L2_BUF_TYPE_SDR_OUTPUT:
297 return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
298 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
299 case V4L2_BUF_TYPE_META_CAPTURE:
300 return copy_in_user(&up->fmt.meta, &kp->fmt.meta,
301 sizeof(kp->fmt.meta)) ? -EFAULT : 0;
302 default:
303 return -EINVAL;
304 }
305}
306
307static int put_v4l2_format32(struct v4l2_format __user *kp,
308 struct v4l2_format32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300309{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500310 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300311 return -EFAULT;
312 return __put_v4l2_format32(kp, up);
313}
314
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400315static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
316 struct v4l2_create_buffers32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300317{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500318 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400319 copy_in_user(up, kp,
320 offsetof(struct v4l2_create_buffers32, format)) ||
321 copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300322 return -EFAULT;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300323 return __put_v4l2_format32(&kp->format, &up->format);
324}
325
Hans Verkuild1f81da2008-10-22 00:04:45 -0300326struct v4l2_standard32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200327 __u32 index;
Andrzej Hajda655e9782015-08-31 08:56:15 -0300328 compat_u64 id;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200329 __u8 name[24];
330 struct v4l2_fract frameperiod; /* Frames, not fields */
331 __u32 framelines;
332 __u32 reserved[4];
333};
334
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400335static int get_v4l2_standard32(struct v4l2_standard __user *kp,
336 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200337{
338 /* other fields are not set by the user, nor used by the driver */
Hans Verkuil333b1e92018-01-24 05:01:31 -0500339 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400340 assign_in_user(&kp->index, &up->index))
Guy Martina113bc72006-01-11 23:40:51 -0200341 return -EFAULT;
342 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200343}
344
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400345static int put_v4l2_standard32(struct v4l2_standard __user *kp,
346 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200347{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500348 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400349 assign_in_user(&up->index, &kp->index) ||
350 assign_in_user(&up->id, &kp->id) ||
351 copy_in_user(up->name, kp->name, sizeof(up->name)) ||
352 copy_in_user(&up->frameperiod, &kp->frameperiod,
353 sizeof(up->frameperiod)) ||
354 assign_in_user(&up->framelines, &kp->framelines) ||
355 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500356 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200357 return 0;
358}
359
Pawel Osciak52a30822010-07-29 14:56:47 -0300360struct v4l2_plane32 {
361 __u32 bytesused;
362 __u32 length;
363 union {
364 __u32 mem_offset;
365 compat_long_t userptr;
Sumit Semwal051c7782012-06-14 10:37:35 -0300366 __s32 fd;
Pawel Osciak52a30822010-07-29 14:56:47 -0300367 } m;
368 __u32 data_offset;
369 __u32 reserved[11];
370};
371
Hans Verkuild1f81da2008-10-22 00:04:45 -0300372struct v4l2_buffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200373 __u32 index;
Sakari Ailus6016af82012-05-10 02:02:07 -0300374 __u32 type; /* enum v4l2_buf_type */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200375 __u32 bytesused;
376 __u32 flags;
Sakari Ailus6016af82012-05-10 02:02:07 -0300377 __u32 field; /* enum v4l2_field */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200378 struct compat_timeval timestamp;
379 struct v4l2_timecode timecode;
380 __u32 sequence;
381
382 /* memory location */
Sakari Ailus6016af82012-05-10 02:02:07 -0300383 __u32 memory; /* enum v4l2_memory */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200384 union {
385 __u32 offset;
386 compat_long_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300387 compat_caddr_t planes;
Sumit Semwal051c7782012-06-14 10:37:35 -0300388 __s32 fd;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200389 } m;
390 __u32 length;
Sakari Ailus2b719d72012-05-02 09:40:03 -0300391 __u32 reserved2;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200392 __u32 reserved;
393};
394
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400395static int get_v4l2_plane32(struct v4l2_plane __user *up,
396 struct v4l2_plane32 __user *up32,
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500397 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300398{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400399 compat_ulong_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300400
401 if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500402 copy_in_user(&up->data_offset, &up32->data_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500403 sizeof(up->data_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300404 return -EFAULT;
405
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500406 switch (memory) {
407 case V4L2_MEMORY_MMAP:
408 case V4L2_MEMORY_OVERLAY:
409 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
410 sizeof(up32->m.mem_offset)))
411 return -EFAULT;
412 break;
413 case V4L2_MEMORY_USERPTR:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400414 if (get_user(p, &up32->m.userptr) ||
415 put_user((unsigned long)compat_ptr(p), &up->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300416 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500417 break;
418 case V4L2_MEMORY_DMABUF:
Hans Verkuil333b1e92018-01-24 05:01:31 -0500419 if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
Sumit Semwal051c7782012-06-14 10:37:35 -0300420 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500421 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300422 }
423
424 return 0;
425}
426
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400427static int put_v4l2_plane32(struct v4l2_plane __user *up,
428 struct v4l2_plane32 __user *up32,
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500429 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300430{
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500431 unsigned long p;
432
Pawel Osciak52a30822010-07-29 14:56:47 -0300433 if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500434 copy_in_user(&up32->data_offset, &up->data_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500435 sizeof(up->data_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300436 return -EFAULT;
437
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500438 switch (memory) {
439 case V4L2_MEMORY_MMAP:
440 case V4L2_MEMORY_OVERLAY:
Pawel Osciak52a30822010-07-29 14:56:47 -0300441 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500442 sizeof(up->m.mem_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300443 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500444 break;
445 case V4L2_MEMORY_USERPTR:
446 if (get_user(p, &up->m.userptr) ||
447 put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
448 &up32->m.userptr))
449 return -EFAULT;
450 break;
451 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400452 if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
Sumit Semwal051c7782012-06-14 10:37:35 -0300453 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500454 break;
455 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300456
457 return 0;
458}
459
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400460static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200461{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400462 u32 type;
463 u32 length;
464
465 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
466 get_user(type, &up->type) ||
467 get_user(length, &up->length))
468 return -EFAULT;
469
470 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
471 if (length > VIDEO_MAX_PLANES)
472 return -EINVAL;
473
474 /*
475 * We don't really care if userspace decides to kill itself
476 * by passing a very big length value
477 */
478 *size = length * sizeof(struct v4l2_plane);
479 } else {
480 *size = 0;
481 }
482 return 0;
483}
484
485static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
486 struct v4l2_buffer32 __user *up,
487 void __user *aux_buf, u32 aux_space)
488{
489 u32 type;
490 u32 length;
491 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300492 struct v4l2_plane32 __user *uplane32;
493 struct v4l2_plane __user *uplane;
494 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300495 int ret;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200496
Hans Verkuil333b1e92018-01-24 05:01:31 -0500497 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400498 assign_in_user(&kp->index, &up->index) ||
499 get_user(type, &up->type) ||
500 put_user(type, &kp->type) ||
501 assign_in_user(&kp->flags, &up->flags) ||
502 get_user(memory, &up->memory) ||
503 put_user(memory, &kp->memory) ||
504 get_user(length, &up->length) ||
505 put_user(length, &kp->length))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500506 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200507
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400508 if (V4L2_TYPE_IS_OUTPUT(type))
509 if (assign_in_user(&kp->bytesused, &up->bytesused) ||
510 assign_in_user(&kp->field, &up->field) ||
511 assign_in_user(&kp->timestamp.tv_sec,
512 &up->timestamp.tv_sec) ||
513 assign_in_user(&kp->timestamp.tv_usec,
514 &up->timestamp.tv_usec))
Al Viro5b1a43d2006-02-01 05:24:20 -0500515 return -EFAULT;
516
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400517 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
518 u32 num_planes = length;
Sakari Ailusa56bc172016-11-08 14:06:44 -0200519
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400520 if (num_planes == 0) {
521 /*
522 * num_planes == 0 is legal, e.g. when userspace doesn't
523 * need planes array on DQBUF
524 */
525 return put_user(NULL, &kp->m.planes);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200526 }
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400527 if (num_planes > VIDEO_MAX_PLANES)
528 return -EINVAL;
Pawel Osciak52a30822010-07-29 14:56:47 -0300529
530 if (get_user(p, &up->m.planes))
Guy Martina113bc72006-01-11 23:40:51 -0200531 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300532
533 uplane32 = compat_ptr(p);
534 if (!access_ok(VERIFY_READ, uplane32,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400535 num_planes * sizeof(*uplane32)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300536 return -EFAULT;
537
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400538 /*
539 * We don't really care if userspace decides to kill itself
540 * by passing a very big num_planes value
541 */
542 if (aux_space < num_planes * sizeof(*uplane))
543 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300544
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400545 uplane = aux_buf;
546 if (put_user((__force struct v4l2_plane *)uplane,
547 &kp->m.planes))
548 return -EFAULT;
549
550 while (num_planes--) {
551 ret = get_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300552 if (ret)
553 return ret;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400554 uplane++;
555 uplane32++;
Pawel Osciak52a30822010-07-29 14:56:47 -0300556 }
557 } else {
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400558 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300559 case V4L2_MEMORY_MMAP:
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500560 case V4L2_MEMORY_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400561 if (assign_in_user(&kp->m.offset, &up->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300562 return -EFAULT;
563 break;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400564 case V4L2_MEMORY_USERPTR: {
565 compat_ulong_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300566
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400567 if (get_user(userptr, &up->m.userptr) ||
568 put_user((unsigned long)compat_ptr(userptr),
569 &kp->m.userptr))
570 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300571 break;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400572 }
Sumit Semwal051c7782012-06-14 10:37:35 -0300573 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400574 if (assign_in_user(&kp->m.fd, &up->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300575 return -EFAULT;
576 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300577 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200578 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300579
Philippe De Muytercf664a62006-01-09 15:24:59 -0200580 return 0;
581}
582
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400583static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
584 struct v4l2_buffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200585{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400586 u32 type;
587 u32 length;
588 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300589 struct v4l2_plane32 __user *uplane32;
590 struct v4l2_plane __user *uplane;
591 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300592 int ret;
593
Hans Verkuil333b1e92018-01-24 05:01:31 -0500594 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400595 assign_in_user(&up->index, &kp->index) ||
596 get_user(type, &kp->type) ||
597 put_user(type, &up->type) ||
598 assign_in_user(&up->flags, &kp->flags) ||
599 get_user(memory, &kp->memory) ||
600 put_user(memory, &up->memory))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500601 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300602
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400603 if (assign_in_user(&up->bytesused, &kp->bytesused) ||
604 assign_in_user(&up->field, &kp->field) ||
605 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
606 assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
607 copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
608 assign_in_user(&up->sequence, &kp->sequence) ||
609 assign_in_user(&up->reserved2, &kp->reserved2) ||
610 assign_in_user(&up->reserved, &kp->reserved) ||
611 get_user(length, &kp->length) ||
612 put_user(length, &up->length))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500613 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300614
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400615 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
616 u32 num_planes = length;
617
Pawel Osciak52a30822010-07-29 14:56:47 -0300618 if (num_planes == 0)
619 return 0;
620
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400621 if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
622 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300623 if (get_user(p, &up->m.planes))
624 return -EFAULT;
625 uplane32 = compat_ptr(p);
626
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400627 while (num_planes--) {
628 ret = put_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300629 if (ret)
630 return ret;
631 ++uplane;
632 ++uplane32;
633 }
634 } else {
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400635 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300636 case V4L2_MEMORY_MMAP:
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500637 case V4L2_MEMORY_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400638 if (assign_in_user(&up->m.offset, &kp->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300639 return -EFAULT;
640 break;
641 case V4L2_MEMORY_USERPTR:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400642 if (assign_in_user(&up->m.userptr, &kp->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300643 return -EFAULT;
644 break;
Sumit Semwal051c7782012-06-14 10:37:35 -0300645 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400646 if (assign_in_user(&up->m.fd, &kp->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300647 return -EFAULT;
648 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300649 }
650 }
651
Philippe De Muytercf664a62006-01-09 15:24:59 -0200652 return 0;
653}
654
Hans Verkuild1f81da2008-10-22 00:04:45 -0300655struct v4l2_framebuffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200656 __u32 capability;
657 __u32 flags;
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500658 compat_caddr_t base;
Laurent Pinchartd52e2382014-05-27 09:41:05 -0300659 struct {
660 __u32 width;
661 __u32 height;
662 __u32 pixelformat;
663 __u32 field;
664 __u32 bytesperline;
665 __u32 sizeimage;
666 __u32 colorspace;
667 __u32 priv;
668 } fmt;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200669};
670
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400671static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
672 struct v4l2_framebuffer32 __user *up)
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200673{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400674 compat_caddr_t tmp;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200675
Hans Verkuil333b1e92018-01-24 05:01:31 -0500676 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500677 get_user(tmp, &up->base) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400678 put_user((__force void *)compat_ptr(tmp), &kp->base) ||
679 assign_in_user(&kp->capability, &up->capability) ||
680 assign_in_user(&kp->flags, &up->flags) ||
681 copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500682 return -EFAULT;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200683 return 0;
684}
685
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400686static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
687 struct v4l2_framebuffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200688{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400689 void *base;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200690
Hans Verkuil333b1e92018-01-24 05:01:31 -0500691 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400692 get_user(base, &kp->base) ||
693 put_user(ptr_to_compat(base), &up->base) ||
694 assign_in_user(&up->capability, &kp->capability) ||
695 assign_in_user(&up->flags, &kp->flags) ||
696 copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500697 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200698 return 0;
699}
700
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300701struct v4l2_input32 {
702 __u32 index; /* Which input */
703 __u8 name[32]; /* Label */
704 __u32 type; /* Type of input */
705 __u32 audioset; /* Associated audios (bitfield) */
706 __u32 tuner; /* Associated tuner */
Andrzej Hajda655e9782015-08-31 08:56:15 -0300707 compat_u64 std;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300708 __u32 status;
Hans Verkuil037e0862017-08-04 07:25:06 -0400709 __u32 capabilities;
710 __u32 reserved[3];
Andrzej Hajda655e9782015-08-31 08:56:15 -0300711};
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300712
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400713/*
714 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
715 * Otherwise it is identical to the 32-bit version.
716 */
717static inline int get_v4l2_input32(struct v4l2_input __user *kp,
718 struct v4l2_input32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200719{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400720 if (copy_in_user(kp, up, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500721 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200722 return 0;
723}
724
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400725static inline int put_v4l2_input32(struct v4l2_input __user *kp,
726 struct v4l2_input32 __user *up)
Guy Martina113bc72006-01-11 23:40:51 -0200727{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400728 if (copy_in_user(up, kp, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500729 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200730 return 0;
731}
732
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300733struct v4l2_ext_controls32 {
Ricardo Ribalda0f8017b2015-10-29 08:10:28 -0200734 __u32 which;
Ricardo Ribalda28c50292015-08-21 10:19:22 -0300735 __u32 count;
736 __u32 error_idx;
737 __u32 reserved[2];
738 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300739};
740
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300741struct v4l2_ext_control32 {
742 __u32 id;
743 __u32 size;
744 __u32 reserved2[1];
745 union {
746 __s32 value;
747 __s64 value64;
748 compat_caddr_t string; /* actually char * */
749 };
750} __attribute__ ((packed));
751
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500752/* Return true if this control is a pointer type. */
753static inline bool ctrl_is_pointer(struct file *file, u32 id)
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300754{
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500755 struct video_device *vdev = video_devdata(file);
756 struct v4l2_fh *fh = NULL;
757 struct v4l2_ctrl_handler *hdl = NULL;
758 struct v4l2_query_ext_ctrl qec = { id };
759 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
760
761 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
762 fh = file->private_data;
763
764 if (fh && fh->ctrl_handler)
765 hdl = fh->ctrl_handler;
766 else if (vdev->ctrl_handler)
767 hdl = vdev->ctrl_handler;
768
769 if (hdl) {
770 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
771
772 return ctrl && ctrl->is_ptr;
Eduardo Valentinfdf82dc2009-08-11 18:49:12 -0300773 }
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500774
Hans Verkuil273caa22018-01-30 10:18:32 -0500775 if (!ops || !ops->vidioc_query_ext_ctrl)
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500776 return false;
777
778 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
779 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300780}
781
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400782static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
783 u32 *size)
784{
785 u32 count;
786
787 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
788 get_user(count, &up->count))
789 return -EFAULT;
790 if (count > V4L2_CID_MAX_CTRLS)
791 return -EINVAL;
792 *size = count * sizeof(struct v4l2_ext_control);
793 return 0;
794}
795
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500796static int get_v4l2_ext_controls32(struct file *file,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400797 struct v4l2_ext_controls __user *kp,
798 struct v4l2_ext_controls32 __user *up,
799 void __user *aux_buf, u32 aux_space)
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300800{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300801 struct v4l2_ext_control32 __user *ucontrols;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300802 struct v4l2_ext_control __user *kcontrols;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400803 u32 count;
804 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300805 compat_caddr_t p;
806
Hans Verkuil333b1e92018-01-24 05:01:31 -0500807 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400808 assign_in_user(&kp->which, &up->which) ||
809 get_user(count, &up->count) ||
810 put_user(count, &kp->count) ||
811 assign_in_user(&kp->error_idx, &up->error_idx) ||
812 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500813 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400814
815 if (count == 0)
816 return put_user(NULL, &kp->controls);
817 if (count > V4L2_CID_MAX_CTRLS)
Sakari Ailusa56bc172016-11-08 14:06:44 -0200818 return -EINVAL;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300819 if (get_user(p, &up->controls))
820 return -EFAULT;
821 ucontrols = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400822 if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300823 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400824 if (aux_space < count * sizeof(*kcontrols))
825 return -EFAULT;
826 kcontrols = aux_buf;
827 if (put_user((__force struct v4l2_ext_control *)kcontrols,
828 &kp->controls))
829 return -EFAULT;
830
831 for (n = 0; n < count; n++) {
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300832 u32 id;
833
Pawel Osciak52a30822010-07-29 14:56:47 -0300834 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300835 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400836
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300837 if (get_user(id, &kcontrols->id))
838 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400839
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500840 if (ctrl_is_pointer(file, id)) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300841 void __user *s;
842
843 if (get_user(p, &ucontrols->string))
844 return -EFAULT;
845 s = compat_ptr(p);
846 if (put_user(s, &kcontrols->string))
847 return -EFAULT;
848 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300849 ucontrols++;
850 kcontrols++;
851 }
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300852 return 0;
853}
854
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500855static int put_v4l2_ext_controls32(struct file *file,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400856 struct v4l2_ext_controls __user *kp,
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500857 struct v4l2_ext_controls32 __user *up)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200858{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300859 struct v4l2_ext_control32 __user *ucontrols;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400860 struct v4l2_ext_control __user *kcontrols;
861 u32 count;
862 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300863 compat_caddr_t p;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200864
Hans Verkuil333b1e92018-01-24 05:01:31 -0500865 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400866 assign_in_user(&up->which, &kp->which) ||
867 get_user(count, &kp->count) ||
868 put_user(count, &up->count) ||
869 assign_in_user(&up->error_idx, &kp->error_idx) ||
870 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
871 get_user(kcontrols, &kp->controls))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500872 return -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300873
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400874 if (!count)
875 return 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300876 if (get_user(p, &up->controls))
877 return -EFAULT;
878 ucontrols = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400879 if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
Guy Martina113bc72006-01-11 23:40:51 -0200880 return -EFAULT;
881
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400882 for (n = 0; n < count; n++) {
883 unsigned int size = sizeof(*ucontrols);
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300884 u32 id;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300885
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400886 if (get_user(id, &kcontrols->id) ||
887 put_user(id, &ucontrols->id) ||
888 assign_in_user(&ucontrols->size, &kcontrols->size) ||
889 copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
890 sizeof(ucontrols->reserved2)))
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300891 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400892
893 /*
894 * Do not modify the pointer when copying a pointer control.
895 * The contents of the pointer was changed, not the pointer
896 * itself.
897 */
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500898 if (ctrl_is_pointer(file, id))
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300899 size -= sizeof(ucontrols->value64);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400900
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300901 if (copy_in_user(ucontrols, kcontrols, size))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300902 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400903
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300904 ucontrols++;
905 kcontrols++;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200906 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300907 return 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200908}
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300909
Hans Verkuil2330fb82011-06-07 11:43:57 -0300910struct v4l2_event32 {
911 __u32 type;
912 union {
Andrzej Hajda655e9782015-08-31 08:56:15 -0300913 compat_s64 value64;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300914 __u8 data[64];
915 } u;
916 __u32 pending;
917 __u32 sequence;
918 struct compat_timespec timestamp;
919 __u32 id;
920 __u32 reserved[8];
921};
922
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400923static int put_v4l2_event32(struct v4l2_event __user *kp,
924 struct v4l2_event32 __user *up)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300925{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500926 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400927 assign_in_user(&up->type, &kp->type) ||
928 copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
929 assign_in_user(&up->pending, &kp->pending) ||
930 assign_in_user(&up->sequence, &kp->sequence) ||
931 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
932 assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
933 assign_in_user(&up->id, &kp->id) ||
934 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500935 return -EFAULT;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300936 return 0;
937}
938
Hans Verkuildd519bb2014-03-07 07:18:37 -0300939struct v4l2_edid32 {
Hans Verkuiled45ce22012-08-10 06:07:12 -0300940 __u32 pad;
941 __u32 start_block;
942 __u32 blocks;
943 __u32 reserved[5];
944 compat_caddr_t edid;
945};
946
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400947static int get_v4l2_edid32(struct v4l2_edid __user *kp,
948 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300949{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400950 compat_uptr_t tmp;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300951
Hans Verkuil333b1e92018-01-24 05:01:31 -0500952 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400953 assign_in_user(&kp->pad, &up->pad) ||
954 assign_in_user(&kp->start_block, &up->start_block) ||
955 assign_in_user(&kp->blocks, &up->blocks) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500956 get_user(tmp, &up->edid) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400957 put_user(compat_ptr(tmp), &kp->edid) ||
958 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500959 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300960 return 0;
961}
962
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400963static int put_v4l2_edid32(struct v4l2_edid __user *kp,
964 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300965{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400966 void *edid;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300967
Hans Verkuil333b1e92018-01-24 05:01:31 -0500968 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400969 assign_in_user(&up->pad, &kp->pad) ||
970 assign_in_user(&up->start_block, &kp->start_block) ||
971 assign_in_user(&up->blocks, &kp->blocks) ||
972 get_user(edid, &kp->edid) ||
973 put_user(ptr_to_compat(edid), &up->edid) ||
974 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500975 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300976 return 0;
977}
978
979
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300980#define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
981#define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
982#define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
983#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
984#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
985#define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
986#define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
987#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
988#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
Hans Verkuildd519bb2014-03-07 07:18:37 -0300989#define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
990#define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500991#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300992#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
993#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
994#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300995#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300996#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
997#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300998
999#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001000#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
1001#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
1002#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
1003#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
1004#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
1005#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001006
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001007static int alloc_userspace(unsigned int size, u32 aux_space,
1008 void __user **up_native)
1009{
1010 *up_native = compat_alloc_user_space(size + aux_space);
1011 if (!*up_native)
1012 return -ENOMEM;
1013 if (clear_user(*up_native, size))
1014 return -EFAULT;
1015 return 0;
1016}
1017
Hans Verkuil069b7472008-12-30 07:04:34 -03001018static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001019{
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001020 void __user *up = compat_ptr(arg);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001021 void __user *up_native = NULL;
1022 void __user *aux_buf;
1023 u32 aux_space;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001024 int compatible_arg = 1;
Hans Verkuil069b7472008-12-30 07:04:34 -03001025 long err = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001026
1027 /* First, convert the command. */
Hans Verkuild1f81da2008-10-22 00:04:45 -03001028 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001029 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
1030 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
1031 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
1032 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
1033 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
1034 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
1035 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
1036 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
1037 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
1038 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
1039 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
1040 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
1041 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001042 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001043 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001044 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
1045 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
1046 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
1047 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
1048 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
1049 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001050 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
1051 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
Hans Verkuildd519bb2014-03-07 07:18:37 -03001052 case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
1053 case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001054 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001055
Hans Verkuild1f81da2008-10-22 00:04:45 -03001056 switch (cmd) {
Philippe De Muytercf664a62006-01-09 15:24:59 -02001057 case VIDIOC_OVERLAY:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001058 case VIDIOC_STREAMON:
1059 case VIDIOC_STREAMOFF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001060 case VIDIOC_S_INPUT:
1061 case VIDIOC_S_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001062 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
1063 if (!err && assign_in_user((unsigned int __user *)up_native,
1064 (compat_uint_t __user *)up))
1065 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001066 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001067 break;
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001068
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001069 case VIDIOC_G_INPUT:
1070 case VIDIOC_G_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001071 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001072 compatible_arg = 0;
1073 break;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001074
Hans Verkuildd519bb2014-03-07 07:18:37 -03001075 case VIDIOC_G_EDID:
1076 case VIDIOC_S_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001077 err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
1078 if (!err)
1079 err = get_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001080 compatible_arg = 0;
1081 break;
1082
Philippe De Muytercf664a62006-01-09 15:24:59 -02001083 case VIDIOC_G_FMT:
1084 case VIDIOC_S_FMT:
1085 case VIDIOC_TRY_FMT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001086 err = bufsize_v4l2_format(up, &aux_space);
1087 if (!err)
1088 err = alloc_userspace(sizeof(struct v4l2_format),
1089 aux_space, &up_native);
1090 if (!err) {
1091 aux_buf = up_native + sizeof(struct v4l2_format);
1092 err = get_v4l2_format32(up_native, up,
1093 aux_buf, aux_space);
1094 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001095 compatible_arg = 0;
1096 break;
1097
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001098 case VIDIOC_CREATE_BUFS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001099 err = bufsize_v4l2_create(up, &aux_space);
1100 if (!err)
1101 err = alloc_userspace(sizeof(struct v4l2_create_buffers),
1102 aux_space, &up_native);
1103 if (!err) {
1104 aux_buf = up_native + sizeof(struct v4l2_create_buffers);
1105 err = get_v4l2_create32(up_native, up,
1106 aux_buf, aux_space);
1107 }
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001108 compatible_arg = 0;
1109 break;
1110
1111 case VIDIOC_PREPARE_BUF:
Philippe De Muytercf664a62006-01-09 15:24:59 -02001112 case VIDIOC_QUERYBUF:
1113 case VIDIOC_QBUF:
1114 case VIDIOC_DQBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001115 err = bufsize_v4l2_buffer(up, &aux_space);
1116 if (!err)
1117 err = alloc_userspace(sizeof(struct v4l2_buffer),
1118 aux_space, &up_native);
1119 if (!err) {
1120 aux_buf = up_native + sizeof(struct v4l2_buffer);
1121 err = get_v4l2_buffer32(up_native, up,
1122 aux_buf, aux_space);
1123 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001124 compatible_arg = 0;
1125 break;
1126
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001127 case VIDIOC_S_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001128 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1129 &up_native);
1130 if (!err)
1131 err = get_v4l2_framebuffer32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001132 compatible_arg = 0;
1133 break;
1134
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001135 case VIDIOC_G_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001136 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1137 &up_native);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001138 compatible_arg = 0;
1139 break;
1140
1141 case VIDIOC_ENUMSTD:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001142 err = alloc_userspace(sizeof(struct v4l2_standard), 0,
1143 &up_native);
1144 if (!err)
1145 err = get_v4l2_standard32(up_native, up);
Philippe De Muytercf664a62006-01-09 15:24:59 -02001146 compatible_arg = 0;
1147 break;
1148
Guy Martina113bc72006-01-11 23:40:51 -02001149 case VIDIOC_ENUMINPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001150 err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
1151 if (!err)
1152 err = get_v4l2_input32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001153 compatible_arg = 0;
1154 break;
1155
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001156 case VIDIOC_G_EXT_CTRLS:
1157 case VIDIOC_S_EXT_CTRLS:
1158 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001159 err = bufsize_v4l2_ext_controls(up, &aux_space);
1160 if (!err)
1161 err = alloc_userspace(sizeof(struct v4l2_ext_controls),
1162 aux_space, &up_native);
1163 if (!err) {
1164 aux_buf = up_native + sizeof(struct v4l2_ext_controls);
1165 err = get_v4l2_ext_controls32(file, up_native, up,
1166 aux_buf, aux_space);
1167 }
Guy Martina113bc72006-01-11 23:40:51 -02001168 compatible_arg = 0;
1169 break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001170 case VIDIOC_DQEVENT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001171 err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001172 compatible_arg = 0;
1173 break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001174 }
Hans Verkuild1f81da2008-10-22 00:04:45 -03001175 if (err)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001176 return err;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001177
Hans Verkuild1f81da2008-10-22 00:04:45 -03001178 if (compatible_arg)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001179 err = native_ioctl(file, cmd, (unsigned long)up);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001180 else
1181 err = native_ioctl(file, cmd, (unsigned long)up_native);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001182
Hans Verkuild83a8242018-01-26 03:24:53 -05001183 if (err == -ENOTTY)
1184 return err;
1185
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001186 /*
1187 * Special case: even after an error we need to put the
1188 * results back for these ioctls since the error_idx will
1189 * contain information on which control failed.
1190 */
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001191 switch (cmd) {
1192 case VIDIOC_G_EXT_CTRLS:
1193 case VIDIOC_S_EXT_CTRLS:
1194 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001195 if (put_v4l2_ext_controls32(file, up_native, up))
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001196 err = -EFAULT;
1197 break;
Hans Verkuilba7ed692017-03-30 09:05:25 -03001198 case VIDIOC_S_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001199 if (put_v4l2_edid32(up_native, up))
Hans Verkuilba7ed692017-03-30 09:05:25 -03001200 err = -EFAULT;
1201 break;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001202 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001203 if (err)
1204 return err;
1205
1206 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001207 case VIDIOC_S_INPUT:
1208 case VIDIOC_S_OUTPUT:
1209 case VIDIOC_G_INPUT:
1210 case VIDIOC_G_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001211 if (assign_in_user((compat_uint_t __user *)up,
1212 ((unsigned int __user *)up_native)))
1213 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001214 break;
1215
1216 case VIDIOC_G_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001217 err = put_v4l2_framebuffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001218 break;
1219
Hans Verkuil2330fb82011-06-07 11:43:57 -03001220 case VIDIOC_DQEVENT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001221 err = put_v4l2_event32(up_native, up);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001222 break;
1223
Hans Verkuildd519bb2014-03-07 07:18:37 -03001224 case VIDIOC_G_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001225 err = put_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001226 break;
1227
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001228 case VIDIOC_G_FMT:
1229 case VIDIOC_S_FMT:
1230 case VIDIOC_TRY_FMT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001231 err = put_v4l2_format32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001232 break;
1233
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001234 case VIDIOC_CREATE_BUFS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001235 err = put_v4l2_create32(up_native, up);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001236 break;
1237
Hans Verkuil3ee6d042018-01-24 08:37:04 -05001238 case VIDIOC_PREPARE_BUF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001239 case VIDIOC_QUERYBUF:
1240 case VIDIOC_QBUF:
1241 case VIDIOC_DQBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001242 err = put_v4l2_buffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001243 break;
1244
1245 case VIDIOC_ENUMSTD:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001246 err = put_v4l2_standard32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001247 break;
1248
1249 case VIDIOC_ENUMINPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001250 err = put_v4l2_input32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001251 break;
1252 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001253 return err;
1254}
1255
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001256long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001257{
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -03001258 struct video_device *vdev = video_devdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03001259 long ret = -ENOIOCTLCMD;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001260
Frederic Weisbeckerc6d7ba82010-08-13 22:29:03 +02001261 if (!file->f_op->unlocked_ioctl)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001262 return ret;
1263
Hans Verkuilab58a302014-02-10 08:08:44 -03001264 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001265 ret = do_video_ioctl(file, cmd, arg);
Hans Verkuilab58a302014-02-10 08:08:44 -03001266 else if (vdev->fops->compat_ioctl32)
1267 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001268
Hans Verkuilab58a302014-02-10 08:08:44 -03001269 if (ret == -ENOIOCTLCMD)
Hans Verkuil9ec32cc2015-09-09 03:40:39 -03001270 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1271 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
Hans Verkuile8efb712006-01-09 15:24:59 -02001272 return ret;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001273}
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001274EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);