blob: bdb5c226d01c4f9be363306984ed834852b30539 [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{
Hans Verkuila751be52018-01-24 06:03:08 -0500104 struct v4l2_clip __user *kclips = kp->clips;
105 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
119 if (get_user(p, &up->clips))
120 return -EFAULT;
121 uclips = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400122 while (clipcount--) {
Hans Verkuila751be52018-01-24 06:03:08 -0500123 if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
124 return -EFAULT;
125 uclips++;
126 kclips++;
127 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200128 return 0;
129}
130
Hans Verkuild1f81da2008-10-22 00:04:45 -0300131struct v4l2_format32 {
Sakari Ailus6016af82012-05-10 02:02:07 -0300132 __u32 type; /* enum v4l2_buf_type */
Hans Verkuild1f81da2008-10-22 00:04:45 -0300133 union {
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300134 struct v4l2_pix_format pix;
Pawel Osciak52a30822010-07-29 14:56:47 -0300135 struct v4l2_pix_format_mplane pix_mp;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300136 struct v4l2_window32 win;
137 struct v4l2_vbi_format vbi;
138 struct v4l2_sliced_vbi_format sliced;
Hans Verkuild5beb672015-09-17 06:46:04 -0300139 struct v4l2_sdr_format sdr;
Laurent Pinchartfb9ffa62016-04-12 19:40:46 -0300140 struct v4l2_meta_format meta;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300141 __u8 raw_data[200]; /* user-defined */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200142 } fmt;
143};
144
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300145/**
146 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
147 * @index: on return, index of the first created buffer
148 * @count: entry: number of requested buffers,
149 * return: number of created buffers
150 * @memory: buffer memory type
151 * @format: frame format, for which buffers are requested
152 * @reserved: future extensions
153 */
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300154struct v4l2_create_buffers32 {
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300155 __u32 index;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300156 __u32 count;
Sakari Ailus6016af82012-05-10 02:02:07 -0300157 __u32 memory; /* enum v4l2_memory */
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300158 struct v4l2_format32 format;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300159 __u32 reserved[8];
160};
161
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400162static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200163{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400164 u32 type;
165
166 if (get_user(type, &up->type))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300167 return -EFAULT;
168
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400169 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200170 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400171 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
172 u32 clipcount;
173
174 if (get_user(clipcount, &up->fmt.win.clipcount))
175 return -EFAULT;
176 if (clipcount > 2048)
177 return -EINVAL;
178 *size = clipcount * sizeof(struct v4l2_clip);
179 return 0;
180 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200181 default:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400182 *size = 0;
183 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200184 }
185}
186
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400187static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200188{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500189 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300190 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400191 return __bufsize_v4l2_format(up, size);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300192}
193
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400194static int __get_v4l2_format32(struct v4l2_format __user *kp,
195 struct v4l2_format32 __user *up,
196 void __user *aux_buf, u32 aux_space)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300197{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400198 u32 type;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300199
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400200 if (get_user(type, &up->type) || put_user(type, &kp->type))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300201 return -EFAULT;
202
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400203 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200204 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300205 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400206 return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
Hans Verkuil486c5212018-01-24 04:45:29 -0500207 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
Pawel Osciak52a30822010-07-29 14:56:47 -0300208 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
209 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400210 return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
Hans Verkuil486c5212018-01-24 04:45:29 -0500211 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200212 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300213 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400214 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
215 aux_buf, aux_space);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200216 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300217 case V4L2_BUF_TYPE_VBI_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400218 return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
Hans Verkuil486c5212018-01-24 04:45:29 -0500219 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300220 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
221 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400222 return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
Hans Verkuil486c5212018-01-24 04:45:29 -0500223 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
Hans Verkuild5beb672015-09-17 06:46:04 -0300224 case V4L2_BUF_TYPE_SDR_CAPTURE:
Antti Palosaari9effc722015-10-10 13:51:00 -0300225 case V4L2_BUF_TYPE_SDR_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400226 return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
Hans Verkuil486c5212018-01-24 04:45:29 -0500227 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
Laurent Pinchartfb9ffa62016-04-12 19:40:46 -0300228 case V4L2_BUF_TYPE_META_CAPTURE:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400229 return copy_in_user(&kp->fmt.meta, &up->fmt.meta,
Hans Verkuil486c5212018-01-24 04:45:29 -0500230 sizeof(kp->fmt.meta)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200231 default:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300232 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200233 }
234}
235
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400236static int get_v4l2_format32(struct v4l2_format __user *kp,
237 struct v4l2_format32 __user *up,
238 void __user *aux_buf, u32 aux_space)
239{
240 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
241 return -EFAULT;
242 return __get_v4l2_format32(kp, up, aux_buf, aux_space);
243}
244
245static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
246 u32 *size)
247{
248 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
249 return -EFAULT;
250 return __bufsize_v4l2_format(&up->format, size);
251}
252
253static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
254 struct v4l2_create_buffers32 __user *up,
255 void __user *aux_buf, u32 aux_space)
256{
257 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
258 copy_in_user(kp, up,
259 offsetof(struct v4l2_create_buffers32, format)))
260 return -EFAULT;
261 return __get_v4l2_format32(&kp->format, &up->format,
262 aux_buf, aux_space);
263}
264
265static int __put_v4l2_format32(struct v4l2_format __user *kp,
266 struct v4l2_format32 __user *up)
267{
268 u32 type;
269
270 if (get_user(type, &kp->type))
271 return -EFAULT;
272
273 switch (type) {
274 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
275 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
276 return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
277 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
278 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
279 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
280 return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
281 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
282 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
283 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
284 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
285 case V4L2_BUF_TYPE_VBI_CAPTURE:
286 case V4L2_BUF_TYPE_VBI_OUTPUT:
287 return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
288 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
289 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
290 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
291 return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
292 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
293 case V4L2_BUF_TYPE_SDR_CAPTURE:
294 case V4L2_BUF_TYPE_SDR_OUTPUT:
295 return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
296 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
297 case V4L2_BUF_TYPE_META_CAPTURE:
298 return copy_in_user(&up->fmt.meta, &kp->fmt.meta,
299 sizeof(kp->fmt.meta)) ? -EFAULT : 0;
300 default:
301 return -EINVAL;
302 }
303}
304
305static int put_v4l2_format32(struct v4l2_format __user *kp,
306 struct v4l2_format32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300307{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500308 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300309 return -EFAULT;
310 return __put_v4l2_format32(kp, up);
311}
312
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400313static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
314 struct v4l2_create_buffers32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300315{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500316 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400317 copy_in_user(up, kp,
318 offsetof(struct v4l2_create_buffers32, format)) ||
319 copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300320 return -EFAULT;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300321 return __put_v4l2_format32(&kp->format, &up->format);
322}
323
Hans Verkuild1f81da2008-10-22 00:04:45 -0300324struct v4l2_standard32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200325 __u32 index;
Andrzej Hajda655e9782015-08-31 08:56:15 -0300326 compat_u64 id;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200327 __u8 name[24];
328 struct v4l2_fract frameperiod; /* Frames, not fields */
329 __u32 framelines;
330 __u32 reserved[4];
331};
332
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400333static int get_v4l2_standard32(struct v4l2_standard __user *kp,
334 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200335{
336 /* other fields are not set by the user, nor used by the driver */
Hans Verkuil333b1e92018-01-24 05:01:31 -0500337 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400338 assign_in_user(&kp->index, &up->index))
Guy Martina113bc72006-01-11 23:40:51 -0200339 return -EFAULT;
340 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200341}
342
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400343static int put_v4l2_standard32(struct v4l2_standard __user *kp,
344 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200345{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500346 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400347 assign_in_user(&up->index, &kp->index) ||
348 assign_in_user(&up->id, &kp->id) ||
349 copy_in_user(up->name, kp->name, sizeof(up->name)) ||
350 copy_in_user(&up->frameperiod, &kp->frameperiod,
351 sizeof(up->frameperiod)) ||
352 assign_in_user(&up->framelines, &kp->framelines) ||
353 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500354 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200355 return 0;
356}
357
Pawel Osciak52a30822010-07-29 14:56:47 -0300358struct v4l2_plane32 {
359 __u32 bytesused;
360 __u32 length;
361 union {
362 __u32 mem_offset;
363 compat_long_t userptr;
Sumit Semwal051c7782012-06-14 10:37:35 -0300364 __s32 fd;
Pawel Osciak52a30822010-07-29 14:56:47 -0300365 } m;
366 __u32 data_offset;
367 __u32 reserved[11];
368};
369
Hans Verkuild1f81da2008-10-22 00:04:45 -0300370struct v4l2_buffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200371 __u32 index;
Sakari Ailus6016af82012-05-10 02:02:07 -0300372 __u32 type; /* enum v4l2_buf_type */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200373 __u32 bytesused;
374 __u32 flags;
Sakari Ailus6016af82012-05-10 02:02:07 -0300375 __u32 field; /* enum v4l2_field */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200376 struct compat_timeval timestamp;
377 struct v4l2_timecode timecode;
378 __u32 sequence;
379
380 /* memory location */
Sakari Ailus6016af82012-05-10 02:02:07 -0300381 __u32 memory; /* enum v4l2_memory */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200382 union {
383 __u32 offset;
384 compat_long_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300385 compat_caddr_t planes;
Sumit Semwal051c7782012-06-14 10:37:35 -0300386 __s32 fd;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200387 } m;
388 __u32 length;
Sakari Ailus2b719d72012-05-02 09:40:03 -0300389 __u32 reserved2;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200390 __u32 reserved;
391};
392
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400393static int get_v4l2_plane32(struct v4l2_plane __user *up,
394 struct v4l2_plane32 __user *up32,
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500395 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300396{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400397 compat_ulong_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300398
399 if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500400 copy_in_user(&up->data_offset, &up32->data_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500401 sizeof(up->data_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300402 return -EFAULT;
403
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500404 switch (memory) {
405 case V4L2_MEMORY_MMAP:
406 case V4L2_MEMORY_OVERLAY:
407 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
408 sizeof(up32->m.mem_offset)))
409 return -EFAULT;
410 break;
411 case V4L2_MEMORY_USERPTR:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400412 if (get_user(p, &up32->m.userptr) ||
413 put_user((unsigned long)compat_ptr(p), &up->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300414 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500415 break;
416 case V4L2_MEMORY_DMABUF:
Hans Verkuil333b1e92018-01-24 05:01:31 -0500417 if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
Sumit Semwal051c7782012-06-14 10:37:35 -0300418 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500419 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300420 }
421
422 return 0;
423}
424
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400425static int put_v4l2_plane32(struct v4l2_plane __user *up,
426 struct v4l2_plane32 __user *up32,
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500427 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300428{
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500429 unsigned long p;
430
Pawel Osciak52a30822010-07-29 14:56:47 -0300431 if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500432 copy_in_user(&up32->data_offset, &up->data_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500433 sizeof(up->data_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300434 return -EFAULT;
435
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500436 switch (memory) {
437 case V4L2_MEMORY_MMAP:
438 case V4L2_MEMORY_OVERLAY:
Pawel Osciak52a30822010-07-29 14:56:47 -0300439 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
Hans Verkuil333b1e92018-01-24 05:01:31 -0500440 sizeof(up->m.mem_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300441 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500442 break;
443 case V4L2_MEMORY_USERPTR:
444 if (get_user(p, &up->m.userptr) ||
445 put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
446 &up32->m.userptr))
447 return -EFAULT;
448 break;
449 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400450 if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
Sumit Semwal051c7782012-06-14 10:37:35 -0300451 return -EFAULT;
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500452 break;
453 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300454
455 return 0;
456}
457
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400458static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200459{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400460 u32 type;
461 u32 length;
462
463 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
464 get_user(type, &up->type) ||
465 get_user(length, &up->length))
466 return -EFAULT;
467
468 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
469 if (length > VIDEO_MAX_PLANES)
470 return -EINVAL;
471
472 /*
473 * We don't really care if userspace decides to kill itself
474 * by passing a very big length value
475 */
476 *size = length * sizeof(struct v4l2_plane);
477 } else {
478 *size = 0;
479 }
480 return 0;
481}
482
483static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
484 struct v4l2_buffer32 __user *up,
485 void __user *aux_buf, u32 aux_space)
486{
487 u32 type;
488 u32 length;
489 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300490 struct v4l2_plane32 __user *uplane32;
491 struct v4l2_plane __user *uplane;
492 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300493 int ret;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200494
Hans Verkuil333b1e92018-01-24 05:01:31 -0500495 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400496 assign_in_user(&kp->index, &up->index) ||
497 get_user(type, &up->type) ||
498 put_user(type, &kp->type) ||
499 assign_in_user(&kp->flags, &up->flags) ||
500 get_user(memory, &up->memory) ||
501 put_user(memory, &kp->memory) ||
502 get_user(length, &up->length) ||
503 put_user(length, &kp->length))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500504 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200505
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400506 if (V4L2_TYPE_IS_OUTPUT(type))
507 if (assign_in_user(&kp->bytesused, &up->bytesused) ||
508 assign_in_user(&kp->field, &up->field) ||
509 assign_in_user(&kp->timestamp.tv_sec,
510 &up->timestamp.tv_sec) ||
511 assign_in_user(&kp->timestamp.tv_usec,
512 &up->timestamp.tv_usec))
Al Viro5b1a43d2006-02-01 05:24:20 -0500513 return -EFAULT;
514
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400515 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
516 u32 num_planes = length;
Sakari Ailusa56bc172016-11-08 14:06:44 -0200517
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400518 if (num_planes == 0) {
519 /*
520 * num_planes == 0 is legal, e.g. when userspace doesn't
521 * need planes array on DQBUF
522 */
523 return put_user(NULL, &kp->m.planes);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200524 }
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400525 if (num_planes > VIDEO_MAX_PLANES)
526 return -EINVAL;
Pawel Osciak52a30822010-07-29 14:56:47 -0300527
528 if (get_user(p, &up->m.planes))
Guy Martina113bc72006-01-11 23:40:51 -0200529 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300530
531 uplane32 = compat_ptr(p);
532 if (!access_ok(VERIFY_READ, uplane32,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400533 num_planes * sizeof(*uplane32)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300534 return -EFAULT;
535
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400536 /*
537 * We don't really care if userspace decides to kill itself
538 * by passing a very big num_planes value
539 */
540 if (aux_space < num_planes * sizeof(*uplane))
541 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300542
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400543 uplane = aux_buf;
544 if (put_user((__force struct v4l2_plane *)uplane,
545 &kp->m.planes))
546 return -EFAULT;
547
548 while (num_planes--) {
549 ret = get_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300550 if (ret)
551 return ret;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400552 uplane++;
553 uplane32++;
Pawel Osciak52a30822010-07-29 14:56:47 -0300554 }
555 } else {
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400556 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300557 case V4L2_MEMORY_MMAP:
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500558 case V4L2_MEMORY_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400559 if (assign_in_user(&kp->m.offset, &up->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300560 return -EFAULT;
561 break;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400562 case V4L2_MEMORY_USERPTR: {
563 compat_ulong_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300564
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400565 if (get_user(userptr, &up->m.userptr) ||
566 put_user((unsigned long)compat_ptr(userptr),
567 &kp->m.userptr))
568 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300569 break;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400570 }
Sumit Semwal051c7782012-06-14 10:37:35 -0300571 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400572 if (assign_in_user(&kp->m.fd, &up->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300573 return -EFAULT;
574 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300575 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200576 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300577
Philippe De Muytercf664a62006-01-09 15:24:59 -0200578 return 0;
579}
580
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400581static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
582 struct v4l2_buffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200583{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400584 u32 type;
585 u32 length;
586 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300587 struct v4l2_plane32 __user *uplane32;
588 struct v4l2_plane __user *uplane;
589 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300590 int ret;
591
Hans Verkuil333b1e92018-01-24 05:01:31 -0500592 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400593 assign_in_user(&up->index, &kp->index) ||
594 get_user(type, &kp->type) ||
595 put_user(type, &up->type) ||
596 assign_in_user(&up->flags, &kp->flags) ||
597 get_user(memory, &kp->memory) ||
598 put_user(memory, &up->memory))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500599 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300600
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400601 if (assign_in_user(&up->bytesused, &kp->bytesused) ||
602 assign_in_user(&up->field, &kp->field) ||
603 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
604 assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
605 copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
606 assign_in_user(&up->sequence, &kp->sequence) ||
607 assign_in_user(&up->reserved2, &kp->reserved2) ||
608 assign_in_user(&up->reserved, &kp->reserved) ||
609 get_user(length, &kp->length) ||
610 put_user(length, &up->length))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500611 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300612
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400613 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
614 u32 num_planes = length;
615
Pawel Osciak52a30822010-07-29 14:56:47 -0300616 if (num_planes == 0)
617 return 0;
618
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400619 if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
620 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300621 if (get_user(p, &up->m.planes))
622 return -EFAULT;
623 uplane32 = compat_ptr(p);
624
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400625 while (num_planes--) {
626 ret = put_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300627 if (ret)
628 return ret;
629 ++uplane;
630 ++uplane32;
631 }
632 } else {
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400633 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300634 case V4L2_MEMORY_MMAP:
Hans Verkuil8ed5a592018-01-24 05:19:59 -0500635 case V4L2_MEMORY_OVERLAY:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400636 if (assign_in_user(&up->m.offset, &kp->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300637 return -EFAULT;
638 break;
639 case V4L2_MEMORY_USERPTR:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400640 if (assign_in_user(&up->m.userptr, &kp->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300641 return -EFAULT;
642 break;
Sumit Semwal051c7782012-06-14 10:37:35 -0300643 case V4L2_MEMORY_DMABUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400644 if (assign_in_user(&up->m.fd, &kp->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300645 return -EFAULT;
646 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300647 }
648 }
649
Philippe De Muytercf664a62006-01-09 15:24:59 -0200650 return 0;
651}
652
Hans Verkuild1f81da2008-10-22 00:04:45 -0300653struct v4l2_framebuffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200654 __u32 capability;
655 __u32 flags;
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500656 compat_caddr_t base;
Laurent Pinchartd52e2382014-05-27 09:41:05 -0300657 struct {
658 __u32 width;
659 __u32 height;
660 __u32 pixelformat;
661 __u32 field;
662 __u32 bytesperline;
663 __u32 sizeimage;
664 __u32 colorspace;
665 __u32 priv;
666 } fmt;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200667};
668
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400669static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
670 struct v4l2_framebuffer32 __user *up)
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200671{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400672 compat_caddr_t tmp;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200673
Hans Verkuil333b1e92018-01-24 05:01:31 -0500674 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500675 get_user(tmp, &up->base) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400676 put_user((__force void *)compat_ptr(tmp), &kp->base) ||
677 assign_in_user(&kp->capability, &up->capability) ||
678 assign_in_user(&kp->flags, &up->flags) ||
679 copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500680 return -EFAULT;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200681 return 0;
682}
683
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400684static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
685 struct v4l2_framebuffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200686{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400687 void *base;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200688
Hans Verkuil333b1e92018-01-24 05:01:31 -0500689 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400690 get_user(base, &kp->base) ||
691 put_user(ptr_to_compat(base), &up->base) ||
692 assign_in_user(&up->capability, &kp->capability) ||
693 assign_in_user(&up->flags, &kp->flags) ||
694 copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500695 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200696 return 0;
697}
698
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300699struct v4l2_input32 {
700 __u32 index; /* Which input */
701 __u8 name[32]; /* Label */
702 __u32 type; /* Type of input */
703 __u32 audioset; /* Associated audios (bitfield) */
704 __u32 tuner; /* Associated tuner */
Andrzej Hajda655e9782015-08-31 08:56:15 -0300705 compat_u64 std;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300706 __u32 status;
Hans Verkuil037e0862017-08-04 07:25:06 -0400707 __u32 capabilities;
708 __u32 reserved[3];
Andrzej Hajda655e9782015-08-31 08:56:15 -0300709};
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300710
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400711/*
712 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
713 * Otherwise it is identical to the 32-bit version.
714 */
715static inline int get_v4l2_input32(struct v4l2_input __user *kp,
716 struct v4l2_input32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200717{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400718 if (copy_in_user(kp, up, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500719 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200720 return 0;
721}
722
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400723static inline int put_v4l2_input32(struct v4l2_input __user *kp,
724 struct v4l2_input32 __user *up)
Guy Martina113bc72006-01-11 23:40:51 -0200725{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400726 if (copy_in_user(up, kp, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500727 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200728 return 0;
729}
730
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300731struct v4l2_ext_controls32 {
Ricardo Ribalda0f8017b2015-10-29 08:10:28 -0200732 __u32 which;
Ricardo Ribalda28c50292015-08-21 10:19:22 -0300733 __u32 count;
734 __u32 error_idx;
735 __u32 reserved[2];
736 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300737};
738
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300739struct v4l2_ext_control32 {
740 __u32 id;
741 __u32 size;
742 __u32 reserved2[1];
743 union {
744 __s32 value;
745 __s64 value64;
746 compat_caddr_t string; /* actually char * */
747 };
748} __attribute__ ((packed));
749
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500750/* Return true if this control is a pointer type. */
751static inline bool ctrl_is_pointer(struct file *file, u32 id)
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300752{
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500753 struct video_device *vdev = video_devdata(file);
754 struct v4l2_fh *fh = NULL;
755 struct v4l2_ctrl_handler *hdl = NULL;
756 struct v4l2_query_ext_ctrl qec = { id };
757 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
758
759 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
760 fh = file->private_data;
761
762 if (fh && fh->ctrl_handler)
763 hdl = fh->ctrl_handler;
764 else if (vdev->ctrl_handler)
765 hdl = vdev->ctrl_handler;
766
767 if (hdl) {
768 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
769
770 return ctrl && ctrl->is_ptr;
Eduardo Valentinfdf82dc2009-08-11 18:49:12 -0300771 }
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500772
773 if (!ops->vidioc_query_ext_ctrl)
774 return false;
775
776 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
777 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300778}
779
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400780static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
781 u32 *size)
782{
783 u32 count;
784
785 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
786 get_user(count, &up->count))
787 return -EFAULT;
788 if (count > V4L2_CID_MAX_CTRLS)
789 return -EINVAL;
790 *size = count * sizeof(struct v4l2_ext_control);
791 return 0;
792}
793
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500794static int get_v4l2_ext_controls32(struct file *file,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400795 struct v4l2_ext_controls __user *kp,
796 struct v4l2_ext_controls32 __user *up,
797 void __user *aux_buf, u32 aux_space)
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300798{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300799 struct v4l2_ext_control32 __user *ucontrols;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300800 struct v4l2_ext_control __user *kcontrols;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400801 u32 count;
802 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300803 compat_caddr_t p;
804
Hans Verkuil333b1e92018-01-24 05:01:31 -0500805 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400806 assign_in_user(&kp->which, &up->which) ||
807 get_user(count, &up->count) ||
808 put_user(count, &kp->count) ||
809 assign_in_user(&kp->error_idx, &up->error_idx) ||
810 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500811 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400812
813 if (count == 0)
814 return put_user(NULL, &kp->controls);
815 if (count > V4L2_CID_MAX_CTRLS)
Sakari Ailusa56bc172016-11-08 14:06:44 -0200816 return -EINVAL;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300817 if (get_user(p, &up->controls))
818 return -EFAULT;
819 ucontrols = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400820 if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300821 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400822 if (aux_space < count * sizeof(*kcontrols))
823 return -EFAULT;
824 kcontrols = aux_buf;
825 if (put_user((__force struct v4l2_ext_control *)kcontrols,
826 &kp->controls))
827 return -EFAULT;
828
829 for (n = 0; n < count; n++) {
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300830 u32 id;
831
Pawel Osciak52a30822010-07-29 14:56:47 -0300832 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300833 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400834
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300835 if (get_user(id, &kcontrols->id))
836 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400837
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500838 if (ctrl_is_pointer(file, id)) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300839 void __user *s;
840
841 if (get_user(p, &ucontrols->string))
842 return -EFAULT;
843 s = compat_ptr(p);
844 if (put_user(s, &kcontrols->string))
845 return -EFAULT;
846 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300847 ucontrols++;
848 kcontrols++;
849 }
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300850 return 0;
851}
852
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500853static int put_v4l2_ext_controls32(struct file *file,
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400854 struct v4l2_ext_controls __user *kp,
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500855 struct v4l2_ext_controls32 __user *up)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200856{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300857 struct v4l2_ext_control32 __user *ucontrols;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400858 struct v4l2_ext_control __user *kcontrols;
859 u32 count;
860 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300861 compat_caddr_t p;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200862
Hans Verkuil333b1e92018-01-24 05:01:31 -0500863 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400864 assign_in_user(&up->which, &kp->which) ||
865 get_user(count, &kp->count) ||
866 put_user(count, &up->count) ||
867 assign_in_user(&up->error_idx, &kp->error_idx) ||
868 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
869 get_user(kcontrols, &kp->controls))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500870 return -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300871
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400872 if (!count)
873 return 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300874 if (get_user(p, &up->controls))
875 return -EFAULT;
876 ucontrols = compat_ptr(p);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400877 if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
Guy Martina113bc72006-01-11 23:40:51 -0200878 return -EFAULT;
879
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400880 for (n = 0; n < count; n++) {
881 unsigned int size = sizeof(*ucontrols);
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300882 u32 id;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300883
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400884 if (get_user(id, &kcontrols->id) ||
885 put_user(id, &ucontrols->id) ||
886 assign_in_user(&ucontrols->size, &kcontrols->size) ||
887 copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
888 sizeof(ucontrols->reserved2)))
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300889 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400890
891 /*
892 * Do not modify the pointer when copying a pointer control.
893 * The contents of the pointer was changed, not the pointer
894 * itself.
895 */
Hans Verkuilb8c601e2018-01-24 05:30:59 -0500896 if (ctrl_is_pointer(file, id))
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300897 size -= sizeof(ucontrols->value64);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400898
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300899 if (copy_in_user(ucontrols, kcontrols, size))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300900 return -EFAULT;
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400901
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300902 ucontrols++;
903 kcontrols++;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200904 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300905 return 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200906}
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300907
Hans Verkuil2330fb82011-06-07 11:43:57 -0300908struct v4l2_event32 {
909 __u32 type;
910 union {
Andrzej Hajda655e9782015-08-31 08:56:15 -0300911 compat_s64 value64;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300912 __u8 data[64];
913 } u;
914 __u32 pending;
915 __u32 sequence;
916 struct compat_timespec timestamp;
917 __u32 id;
918 __u32 reserved[8];
919};
920
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400921static int put_v4l2_event32(struct v4l2_event __user *kp,
922 struct v4l2_event32 __user *up)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300923{
Hans Verkuil333b1e92018-01-24 05:01:31 -0500924 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400925 assign_in_user(&up->type, &kp->type) ||
926 copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
927 assign_in_user(&up->pending, &kp->pending) ||
928 assign_in_user(&up->sequence, &kp->sequence) ||
929 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
930 assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
931 assign_in_user(&up->id, &kp->id) ||
932 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500933 return -EFAULT;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300934 return 0;
935}
936
Hans Verkuildd519bb2014-03-07 07:18:37 -0300937struct v4l2_edid32 {
Hans Verkuiled45ce22012-08-10 06:07:12 -0300938 __u32 pad;
939 __u32 start_block;
940 __u32 blocks;
941 __u32 reserved[5];
942 compat_caddr_t edid;
943};
944
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400945static int get_v4l2_edid32(struct v4l2_edid __user *kp,
946 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300947{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400948 compat_uptr_t tmp;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300949
Hans Verkuil333b1e92018-01-24 05:01:31 -0500950 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400951 assign_in_user(&kp->pad, &up->pad) ||
952 assign_in_user(&kp->start_block, &up->start_block) ||
953 assign_in_user(&kp->blocks, &up->blocks) ||
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500954 get_user(tmp, &up->edid) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400955 put_user(compat_ptr(tmp), &kp->edid) ||
956 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500957 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300958 return 0;
959}
960
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400961static int put_v4l2_edid32(struct v4l2_edid __user *kp,
962 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300963{
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400964 void *edid;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300965
Hans Verkuil333b1e92018-01-24 05:01:31 -0500966 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentza1dfb4c42017-07-19 19:03:19 -0400967 assign_in_user(&up->pad, &kp->pad) ||
968 assign_in_user(&up->start_block, &kp->start_block) ||
969 assign_in_user(&up->blocks, &kp->blocks) ||
970 get_user(edid, &kp->edid) ||
971 put_user(ptr_to_compat(edid), &up->edid) ||
972 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuilb7b957d2018-01-24 04:35:48 -0500973 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300974 return 0;
975}
976
977
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300978#define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
979#define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
980#define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
981#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
982#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
983#define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
984#define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
985#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
986#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
Hans Verkuildd519bb2014-03-07 07:18:37 -0300987#define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
988#define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500989#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300990#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
991#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
992#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300993#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300994#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
995#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300996
997#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300998#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
999#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
1000#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
1001#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
1002#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
1003#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001004
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001005static int alloc_userspace(unsigned int size, u32 aux_space,
1006 void __user **up_native)
1007{
1008 *up_native = compat_alloc_user_space(size + aux_space);
1009 if (!*up_native)
1010 return -ENOMEM;
1011 if (clear_user(*up_native, size))
1012 return -EFAULT;
1013 return 0;
1014}
1015
Hans Verkuil069b7472008-12-30 07:04:34 -03001016static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001017{
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001018 void __user *up = compat_ptr(arg);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001019 void __user *up_native = NULL;
1020 void __user *aux_buf;
1021 u32 aux_space;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001022 int compatible_arg = 1;
Hans Verkuil069b7472008-12-30 07:04:34 -03001023 long err = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001024
1025 /* First, convert the command. */
Hans Verkuild1f81da2008-10-22 00:04:45 -03001026 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001027 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
1028 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
1029 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
1030 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
1031 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
1032 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
1033 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
1034 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
1035 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
1036 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
1037 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
1038 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
1039 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001040 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001041 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001042 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
1043 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
1044 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
1045 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
1046 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
1047 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001048 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
1049 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
Hans Verkuildd519bb2014-03-07 07:18:37 -03001050 case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
1051 case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001052 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001053
Hans Verkuild1f81da2008-10-22 00:04:45 -03001054 switch (cmd) {
Philippe De Muytercf664a62006-01-09 15:24:59 -02001055 case VIDIOC_OVERLAY:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001056 case VIDIOC_STREAMON:
1057 case VIDIOC_STREAMOFF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001058 case VIDIOC_S_INPUT:
1059 case VIDIOC_S_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001060 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
1061 if (!err && assign_in_user((unsigned int __user *)up_native,
1062 (compat_uint_t __user *)up))
1063 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001064 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001065 break;
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001066
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001067 case VIDIOC_G_INPUT:
1068 case VIDIOC_G_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001069 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001070 compatible_arg = 0;
1071 break;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001072
Hans Verkuildd519bb2014-03-07 07:18:37 -03001073 case VIDIOC_G_EDID:
1074 case VIDIOC_S_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001075 err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
1076 if (!err)
1077 err = get_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001078 compatible_arg = 0;
1079 break;
1080
Philippe De Muytercf664a62006-01-09 15:24:59 -02001081 case VIDIOC_G_FMT:
1082 case VIDIOC_S_FMT:
1083 case VIDIOC_TRY_FMT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001084 err = bufsize_v4l2_format(up, &aux_space);
1085 if (!err)
1086 err = alloc_userspace(sizeof(struct v4l2_format),
1087 aux_space, &up_native);
1088 if (!err) {
1089 aux_buf = up_native + sizeof(struct v4l2_format);
1090 err = get_v4l2_format32(up_native, up,
1091 aux_buf, aux_space);
1092 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001093 compatible_arg = 0;
1094 break;
1095
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001096 case VIDIOC_CREATE_BUFS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001097 err = bufsize_v4l2_create(up, &aux_space);
1098 if (!err)
1099 err = alloc_userspace(sizeof(struct v4l2_create_buffers),
1100 aux_space, &up_native);
1101 if (!err) {
1102 aux_buf = up_native + sizeof(struct v4l2_create_buffers);
1103 err = get_v4l2_create32(up_native, up,
1104 aux_buf, aux_space);
1105 }
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001106 compatible_arg = 0;
1107 break;
1108
1109 case VIDIOC_PREPARE_BUF:
Philippe De Muytercf664a62006-01-09 15:24:59 -02001110 case VIDIOC_QUERYBUF:
1111 case VIDIOC_QBUF:
1112 case VIDIOC_DQBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001113 err = bufsize_v4l2_buffer(up, &aux_space);
1114 if (!err)
1115 err = alloc_userspace(sizeof(struct v4l2_buffer),
1116 aux_space, &up_native);
1117 if (!err) {
1118 aux_buf = up_native + sizeof(struct v4l2_buffer);
1119 err = get_v4l2_buffer32(up_native, up,
1120 aux_buf, aux_space);
1121 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001122 compatible_arg = 0;
1123 break;
1124
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001125 case VIDIOC_S_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001126 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1127 &up_native);
1128 if (!err)
1129 err = get_v4l2_framebuffer32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001130 compatible_arg = 0;
1131 break;
1132
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001133 case VIDIOC_G_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001134 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1135 &up_native);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001136 compatible_arg = 0;
1137 break;
1138
1139 case VIDIOC_ENUMSTD:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001140 err = alloc_userspace(sizeof(struct v4l2_standard), 0,
1141 &up_native);
1142 if (!err)
1143 err = get_v4l2_standard32(up_native, up);
Philippe De Muytercf664a62006-01-09 15:24:59 -02001144 compatible_arg = 0;
1145 break;
1146
Guy Martina113bc72006-01-11 23:40:51 -02001147 case VIDIOC_ENUMINPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001148 err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
1149 if (!err)
1150 err = get_v4l2_input32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001151 compatible_arg = 0;
1152 break;
1153
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001154 case VIDIOC_G_EXT_CTRLS:
1155 case VIDIOC_S_EXT_CTRLS:
1156 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001157 err = bufsize_v4l2_ext_controls(up, &aux_space);
1158 if (!err)
1159 err = alloc_userspace(sizeof(struct v4l2_ext_controls),
1160 aux_space, &up_native);
1161 if (!err) {
1162 aux_buf = up_native + sizeof(struct v4l2_ext_controls);
1163 err = get_v4l2_ext_controls32(file, up_native, up,
1164 aux_buf, aux_space);
1165 }
Guy Martina113bc72006-01-11 23:40:51 -02001166 compatible_arg = 0;
1167 break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001168 case VIDIOC_DQEVENT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001169 err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001170 compatible_arg = 0;
1171 break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001172 }
Hans Verkuild1f81da2008-10-22 00:04:45 -03001173 if (err)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001174 return err;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001175
Hans Verkuild1f81da2008-10-22 00:04:45 -03001176 if (compatible_arg)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001177 err = native_ioctl(file, cmd, (unsigned long)up);
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001178 else
1179 err = native_ioctl(file, cmd, (unsigned long)up_native);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001180
Hans Verkuild83a8242018-01-26 03:24:53 -05001181 if (err == -ENOTTY)
1182 return err;
1183
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001184 /*
1185 * Special case: even after an error we need to put the
1186 * results back for these ioctls since the error_idx will
1187 * contain information on which control failed.
1188 */
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001189 switch (cmd) {
1190 case VIDIOC_G_EXT_CTRLS:
1191 case VIDIOC_S_EXT_CTRLS:
1192 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001193 if (put_v4l2_ext_controls32(file, up_native, up))
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001194 err = -EFAULT;
1195 break;
Hans Verkuilba7ed692017-03-30 09:05:25 -03001196 case VIDIOC_S_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001197 if (put_v4l2_edid32(up_native, up))
Hans Verkuilba7ed692017-03-30 09:05:25 -03001198 err = -EFAULT;
1199 break;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001200 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001201 if (err)
1202 return err;
1203
1204 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001205 case VIDIOC_S_INPUT:
1206 case VIDIOC_S_OUTPUT:
1207 case VIDIOC_G_INPUT:
1208 case VIDIOC_G_OUTPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001209 if (assign_in_user((compat_uint_t __user *)up,
1210 ((unsigned int __user *)up_native)))
1211 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001212 break;
1213
1214 case VIDIOC_G_FBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001215 err = put_v4l2_framebuffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001216 break;
1217
Hans Verkuil2330fb82011-06-07 11:43:57 -03001218 case VIDIOC_DQEVENT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001219 err = put_v4l2_event32(up_native, up);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001220 break;
1221
Hans Verkuildd519bb2014-03-07 07:18:37 -03001222 case VIDIOC_G_EDID:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001223 err = put_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001224 break;
1225
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001226 case VIDIOC_G_FMT:
1227 case VIDIOC_S_FMT:
1228 case VIDIOC_TRY_FMT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001229 err = put_v4l2_format32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001230 break;
1231
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001232 case VIDIOC_CREATE_BUFS:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001233 err = put_v4l2_create32(up_native, up);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001234 break;
1235
Hans Verkuil3ee6d042018-01-24 08:37:04 -05001236 case VIDIOC_PREPARE_BUF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001237 case VIDIOC_QUERYBUF:
1238 case VIDIOC_QBUF:
1239 case VIDIOC_DQBUF:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001240 err = put_v4l2_buffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001241 break;
1242
1243 case VIDIOC_ENUMSTD:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001244 err = put_v4l2_standard32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001245 break;
1246
1247 case VIDIOC_ENUMINPUT:
Daniel Mentza1dfb4c42017-07-19 19:03:19 -04001248 err = put_v4l2_input32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001249 break;
1250 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001251 return err;
1252}
1253
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001254long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001255{
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -03001256 struct video_device *vdev = video_devdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03001257 long ret = -ENOIOCTLCMD;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001258
Frederic Weisbeckerc6d7ba82010-08-13 22:29:03 +02001259 if (!file->f_op->unlocked_ioctl)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001260 return ret;
1261
Hans Verkuilab58a302014-02-10 08:08:44 -03001262 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001263 ret = do_video_ioctl(file, cmd, arg);
Hans Verkuilab58a302014-02-10 08:08:44 -03001264 else if (vdev->fops->compat_ioctl32)
1265 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001266
Hans Verkuilab58a302014-02-10 08:08:44 -03001267 if (ret == -ENOIOCTLCMD)
Hans Verkuil9ec32cc2015-09-09 03:40:39 -03001268 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1269 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
Hans Verkuile8efb712006-01-09 15:24:59 -02001270 return ret;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001271}
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001272EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);