• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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
8  * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
9  * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
10  * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
11  *
12  * These routines maintain argument size conversion between 32bit and 64bit
13  * ioctls.
14  */
15 
16 #include <linux/compat.h>
17 #include <linux/module.h>
18 #include <linux/videodev2.h>
19 #include <media/v4l2-dev.h>
20 #include <media/v4l2-ioctl.h>
21 
native_ioctl(struct file * file,unsigned int cmd,unsigned long arg)22 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
23 {
24 	long ret = -ENOIOCTLCMD;
25 
26 	if (file->f_op->unlocked_ioctl)
27 		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
28 
29 	return ret;
30 }
31 
32 
33 struct v4l2_clip32 {
34 	struct v4l2_rect        c;
35 	compat_caddr_t 		next;
36 };
37 
38 struct v4l2_window32 {
39 	struct v4l2_rect        w;
40 	enum v4l2_field  	field;
41 	__u32			chromakey;
42 	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
43 	__u32			clipcount;
44 	compat_caddr_t		bitmap;
45 };
46 
get_v4l2_window32(struct v4l2_window * kp,struct v4l2_window32 __user * up)47 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
48 {
49 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
50 		copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
51 		get_user(kp->field, &up->field) ||
52 		get_user(kp->chromakey, &up->chromakey) ||
53 		get_user(kp->clipcount, &up->clipcount))
54 			return -EFAULT;
55 	if (kp->clipcount > 2048)
56 		return -EINVAL;
57 	if (kp->clipcount) {
58 		struct v4l2_clip32 __user *uclips;
59 		struct v4l2_clip __user *kclips;
60 		int n = kp->clipcount;
61 		compat_caddr_t p;
62 
63 		if (get_user(p, &up->clips))
64 			return -EFAULT;
65 		uclips = compat_ptr(p);
66 		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
67 		kp->clips = kclips;
68 		while (--n >= 0) {
69 			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
70 				return -EFAULT;
71 			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
72 				return -EFAULT;
73 			uclips += 1;
74 			kclips += 1;
75 		}
76 	} else
77 		kp->clips = NULL;
78 	return 0;
79 }
80 
put_v4l2_window32(struct v4l2_window * kp,struct v4l2_window32 __user * up)81 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
82 {
83 	if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
84 		put_user(kp->field, &up->field) ||
85 		put_user(kp->chromakey, &up->chromakey) ||
86 		put_user(kp->clipcount, &up->clipcount))
87 			return -EFAULT;
88 	return 0;
89 }
90 
get_v4l2_pix_format(struct v4l2_pix_format * kp,struct v4l2_pix_format __user * up)91 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
92 {
93 	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
94 		return -EFAULT;
95 	return 0;
96 }
97 
get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane * kp,struct v4l2_pix_format_mplane __user * up)98 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
99 				struct v4l2_pix_format_mplane __user *up)
100 {
101 	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
102 		return -EFAULT;
103 	return 0;
104 }
105 
put_v4l2_pix_format(struct v4l2_pix_format * kp,struct v4l2_pix_format __user * up)106 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
107 {
108 	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
109 		return -EFAULT;
110 	return 0;
111 }
112 
put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane * kp,struct v4l2_pix_format_mplane __user * up)113 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
114 				struct v4l2_pix_format_mplane __user *up)
115 {
116 	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
117 		return -EFAULT;
118 	return 0;
119 }
120 
get_v4l2_vbi_format(struct v4l2_vbi_format * kp,struct v4l2_vbi_format __user * up)121 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
122 {
123 	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
124 		return -EFAULT;
125 	return 0;
126 }
127 
put_v4l2_vbi_format(struct v4l2_vbi_format * kp,struct v4l2_vbi_format __user * up)128 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
129 {
130 	if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
131 		return -EFAULT;
132 	return 0;
133 }
134 
get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format * kp,struct v4l2_sliced_vbi_format __user * up)135 static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
136 {
137 	if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
138 		return -EFAULT;
139 	return 0;
140 }
141 
put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format * kp,struct v4l2_sliced_vbi_format __user * up)142 static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
143 {
144 	if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
145 		return -EFAULT;
146 	return 0;
147 }
148 
149 struct v4l2_format32 {
150 	enum v4l2_buf_type type;
151 	union {
152 		struct v4l2_pix_format	pix;
153 		struct v4l2_pix_format_mplane	pix_mp;
154 		struct v4l2_window32	win;
155 		struct v4l2_vbi_format	vbi;
156 		struct v4l2_sliced_vbi_format	sliced;
157 		__u8	raw_data[200];        /* user-defined */
158 	} fmt;
159 };
160 
161 /**
162  * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
163  * @index:	on return, index of the first created buffer
164  * @count:	entry: number of requested buffers,
165  *		return: number of created buffers
166  * @memory:	buffer memory type
167  * @format:	frame format, for which buffers are requested
168  * @reserved:	future extensions
169  */
170 struct v4l2_create_buffers32 {
171 	__u32			index;
172 	__u32			count;
173 	enum v4l2_memory        memory;
174 	struct v4l2_format32	format;
175 	__u32			reserved[8];
176 };
177 
__get_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)178 static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
179 {
180 	switch (kp->type) {
181 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
182 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
183 		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
184 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
185 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
186 		return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
187 						  &up->fmt.pix_mp);
188 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
189 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
190 		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
191 	case V4L2_BUF_TYPE_VBI_CAPTURE:
192 	case V4L2_BUF_TYPE_VBI_OUTPUT:
193 		return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
194 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
195 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
196 		return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
197 	case V4L2_BUF_TYPE_PRIVATE:
198 		if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
199 			return -EFAULT;
200 		return 0;
201 	default:
202 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
203 								kp->type);
204 		return -EINVAL;
205 	}
206 }
207 
get_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)208 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
209 {
210 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
211 			get_user(kp->type, &up->type))
212 			return -EFAULT;
213 	return __get_v4l2_format32(kp, up);
214 }
215 
get_v4l2_create32(struct v4l2_create_buffers * kp,struct v4l2_create_buffers32 __user * up)216 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
217 {
218 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
219 	    copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
220 			return -EFAULT;
221 	return __get_v4l2_format32(&kp->format, &up->format);
222 }
223 
__put_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)224 static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
225 {
226 	switch (kp->type) {
227 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
228 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
229 		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
230 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
231 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
232 		return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
233 						  &up->fmt.pix_mp);
234 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
235 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
236 		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
237 	case V4L2_BUF_TYPE_VBI_CAPTURE:
238 	case V4L2_BUF_TYPE_VBI_OUTPUT:
239 		return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
240 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
241 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
242 		return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
243 	case V4L2_BUF_TYPE_PRIVATE:
244 		if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
245 			return -EFAULT;
246 		return 0;
247 	default:
248 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
249 								kp->type);
250 		return -EINVAL;
251 	}
252 }
253 
put_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)254 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
255 {
256 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
257 		put_user(kp->type, &up->type))
258 		return -EFAULT;
259 	return __put_v4l2_format32(kp, up);
260 }
261 
put_v4l2_create32(struct v4l2_create_buffers * kp,struct v4l2_create_buffers32 __user * up)262 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
263 {
264 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
265 	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
266 			return -EFAULT;
267 	return __put_v4l2_format32(&kp->format, &up->format);
268 }
269 
270 struct v4l2_standard32 {
271 	__u32		     index;
272 	__u32		     id[2]; /* __u64 would get the alignment wrong */
273 	__u8		     name[24];
274 	struct v4l2_fract    frameperiod; /* Frames, not fields */
275 	__u32		     framelines;
276 	__u32		     reserved[4];
277 };
278 
get_v4l2_standard32(struct v4l2_standard * kp,struct v4l2_standard32 __user * up)279 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
280 {
281 	/* other fields are not set by the user, nor used by the driver */
282 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
283 		get_user(kp->index, &up->index))
284 		return -EFAULT;
285 	return 0;
286 }
287 
put_v4l2_standard32(struct v4l2_standard * kp,struct v4l2_standard32 __user * up)288 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
289 {
290 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
291 		put_user(kp->index, &up->index) ||
292 		copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
293 		copy_to_user(up->name, kp->name, 24) ||
294 		copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
295 		put_user(kp->framelines, &up->framelines) ||
296 		copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
297 			return -EFAULT;
298 	return 0;
299 }
300 
301 struct v4l2_plane32 {
302 	__u32			bytesused;
303 	__u32			length;
304 	union {
305 		__u32		mem_offset;
306 		compat_long_t	userptr;
307 	} m;
308 	__u32			data_offset;
309 	__u32			reserved[11];
310 };
311 
312 struct v4l2_buffer32 {
313 	__u32			index;
314 	enum v4l2_buf_type      type;
315 	__u32			bytesused;
316 	__u32			flags;
317 	enum v4l2_field		field;
318 	struct compat_timeval	timestamp;
319 	struct v4l2_timecode	timecode;
320 	__u32			sequence;
321 
322 	/* memory location */
323 	enum v4l2_memory        memory;
324 	union {
325 		__u32           offset;
326 		compat_long_t   userptr;
327 		compat_caddr_t  planes;
328 	} m;
329 	__u32			length;
330 	__u32			input;
331 	__u32			reserved;
332 };
333 
get_v4l2_plane32(struct v4l2_plane * up,struct v4l2_plane32 * up32,enum v4l2_memory memory)334 static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
335 				enum v4l2_memory memory)
336 {
337 	void __user *up_pln;
338 	compat_long_t p;
339 
340 	if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
341 		copy_in_user(&up->data_offset, &up32->data_offset,
342 				sizeof(__u32)))
343 		return -EFAULT;
344 
345 	if (memory == V4L2_MEMORY_USERPTR) {
346 		if (get_user(p, &up32->m.userptr))
347 			return -EFAULT;
348 		up_pln = compat_ptr(p);
349 		if (put_user((unsigned long)up_pln, &up->m.userptr))
350 			return -EFAULT;
351 	} else {
352 		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
353 					sizeof(__u32)))
354 			return -EFAULT;
355 	}
356 
357 	return 0;
358 }
359 
put_v4l2_plane32(struct v4l2_plane * up,struct v4l2_plane32 * up32,enum v4l2_memory memory)360 static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
361 				enum v4l2_memory memory)
362 {
363 	if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
364 		copy_in_user(&up32->data_offset, &up->data_offset,
365 				sizeof(__u32)))
366 		return -EFAULT;
367 
368 	/* For MMAP, driver might've set up the offset, so copy it back.
369 	 * USERPTR stays the same (was userspace-provided), so no copying. */
370 	if (memory == V4L2_MEMORY_MMAP)
371 		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
372 					sizeof(__u32)))
373 			return -EFAULT;
374 
375 	return 0;
376 }
377 
get_v4l2_buffer32(struct v4l2_buffer * kp,struct v4l2_buffer32 __user * up)378 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
379 {
380 	struct v4l2_plane32 __user *uplane32;
381 	struct v4l2_plane __user *uplane;
382 	compat_caddr_t p;
383 	int num_planes;
384 	int ret;
385 
386 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
387 		get_user(kp->index, &up->index) ||
388 		get_user(kp->type, &up->type) ||
389 		get_user(kp->flags, &up->flags) ||
390 		get_user(kp->memory, &up->memory) ||
391 		get_user(kp->input, &up->input))
392 			return -EFAULT;
393 
394 	if (V4L2_TYPE_IS_OUTPUT(kp->type))
395 		if (get_user(kp->bytesused, &up->bytesused) ||
396 			get_user(kp->field, &up->field) ||
397 			get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
398 			get_user(kp->timestamp.tv_usec,
399 					&up->timestamp.tv_usec))
400 			return -EFAULT;
401 
402 	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
403 		if (get_user(kp->length, &up->length))
404 			return -EFAULT;
405 
406 		num_planes = kp->length;
407 		if (num_planes == 0) {
408 			kp->m.planes = NULL;
409 			/* num_planes == 0 is legal, e.g. when userspace doesn't
410 			 * need planes array on DQBUF*/
411 			return 0;
412 		}
413 
414 		if (get_user(p, &up->m.planes))
415 			return -EFAULT;
416 
417 		uplane32 = compat_ptr(p);
418 		if (!access_ok(VERIFY_READ, uplane32,
419 				num_planes * sizeof(struct v4l2_plane32)))
420 			return -EFAULT;
421 
422 		/* We don't really care if userspace decides to kill itself
423 		 * by passing a very big num_planes value */
424 		uplane = compat_alloc_user_space(num_planes *
425 						sizeof(struct v4l2_plane));
426 		kp->m.planes = uplane;
427 
428 		while (--num_planes >= 0) {
429 			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
430 			if (ret)
431 				return ret;
432 			++uplane;
433 			++uplane32;
434 		}
435 	} else {
436 		switch (kp->memory) {
437 		case V4L2_MEMORY_MMAP:
438 			if (get_user(kp->length, &up->length) ||
439 				get_user(kp->m.offset, &up->m.offset))
440 				return -EFAULT;
441 			break;
442 		case V4L2_MEMORY_USERPTR:
443 			{
444 			compat_long_t tmp;
445 
446 			if (get_user(kp->length, &up->length) ||
447 			    get_user(tmp, &up->m.userptr))
448 				return -EFAULT;
449 
450 			kp->m.userptr = (unsigned long)compat_ptr(tmp);
451 			}
452 			break;
453 		case V4L2_MEMORY_OVERLAY:
454 			if (get_user(kp->m.offset, &up->m.offset))
455 				return -EFAULT;
456 			break;
457 		}
458 	}
459 
460 	return 0;
461 }
462 
put_v4l2_buffer32(struct v4l2_buffer * kp,struct v4l2_buffer32 __user * up)463 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
464 {
465 	struct v4l2_plane32 __user *uplane32;
466 	struct v4l2_plane __user *uplane;
467 	compat_caddr_t p;
468 	int num_planes;
469 	int ret;
470 
471 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
472 		put_user(kp->index, &up->index) ||
473 		put_user(kp->type, &up->type) ||
474 		put_user(kp->flags, &up->flags) ||
475 		put_user(kp->memory, &up->memory) ||
476 		put_user(kp->input, &up->input))
477 			return -EFAULT;
478 
479 	if (put_user(kp->bytesused, &up->bytesused) ||
480 		put_user(kp->field, &up->field) ||
481 		put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
482 		put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
483 		copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
484 		put_user(kp->sequence, &up->sequence) ||
485 		put_user(kp->reserved, &up->reserved))
486 			return -EFAULT;
487 
488 	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
489 		num_planes = kp->length;
490 		if (num_planes == 0)
491 			return 0;
492 
493 		uplane = kp->m.planes;
494 		if (get_user(p, &up->m.planes))
495 			return -EFAULT;
496 		uplane32 = compat_ptr(p);
497 
498 		while (--num_planes >= 0) {
499 			ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
500 			if (ret)
501 				return ret;
502 			++uplane;
503 			++uplane32;
504 		}
505 	} else {
506 		switch (kp->memory) {
507 		case V4L2_MEMORY_MMAP:
508 			if (put_user(kp->length, &up->length) ||
509 				put_user(kp->m.offset, &up->m.offset))
510 				return -EFAULT;
511 			break;
512 		case V4L2_MEMORY_USERPTR:
513 			if (put_user(kp->length, &up->length) ||
514 				put_user(kp->m.userptr, &up->m.userptr))
515 				return -EFAULT;
516 			break;
517 		case V4L2_MEMORY_OVERLAY:
518 			if (put_user(kp->m.offset, &up->m.offset))
519 				return -EFAULT;
520 			break;
521 		}
522 	}
523 
524 	return 0;
525 }
526 
527 struct v4l2_framebuffer32 {
528 	__u32			capability;
529 	__u32			flags;
530 	compat_caddr_t 		base;
531 	struct v4l2_pix_format	fmt;
532 };
533 
get_v4l2_framebuffer32(struct v4l2_framebuffer * kp,struct v4l2_framebuffer32 __user * up)534 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
535 {
536 	u32 tmp;
537 
538 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
539 		get_user(tmp, &up->base) ||
540 		get_user(kp->capability, &up->capability) ||
541 		get_user(kp->flags, &up->flags))
542 			return -EFAULT;
543 	kp->base = compat_ptr(tmp);
544 	get_v4l2_pix_format(&kp->fmt, &up->fmt);
545 	return 0;
546 }
547 
put_v4l2_framebuffer32(struct v4l2_framebuffer * kp,struct v4l2_framebuffer32 __user * up)548 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
549 {
550 	u32 tmp = (u32)((unsigned long)kp->base);
551 
552 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
553 		put_user(tmp, &up->base) ||
554 		put_user(kp->capability, &up->capability) ||
555 		put_user(kp->flags, &up->flags))
556 			return -EFAULT;
557 	put_v4l2_pix_format(&kp->fmt, &up->fmt);
558 	return 0;
559 }
560 
561 struct v4l2_input32 {
562 	__u32	     index;		/*  Which input */
563 	__u8	     name[32];		/*  Label */
564 	__u32	     type;		/*  Type of input */
565 	__u32	     audioset;		/*  Associated audios (bitfield) */
566 	__u32        tuner;             /*  Associated tuner */
567 	v4l2_std_id  std;
568 	__u32	     status;
569 	__u32	     reserved[4];
570 } __attribute__ ((packed));
571 
572 /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
573    Otherwise it is identical to the 32-bit version. */
get_v4l2_input32(struct v4l2_input * kp,struct v4l2_input32 __user * up)574 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
575 {
576 	if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
577 		return -EFAULT;
578 	return 0;
579 }
580 
put_v4l2_input32(struct v4l2_input * kp,struct v4l2_input32 __user * up)581 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
582 {
583 	if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
584 		return -EFAULT;
585 	return 0;
586 }
587 
588 struct v4l2_ext_controls32 {
589        __u32 ctrl_class;
590        __u32 count;
591        __u32 error_idx;
592        __u32 reserved[2];
593        compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
594 };
595 
596 struct v4l2_ext_control32 {
597 	__u32 id;
598 	__u32 size;
599 	__u32 reserved2[1];
600 	union {
601 		__s32 value;
602 		__s64 value64;
603 		compat_caddr_t string; /* actually char * */
604 	};
605 } __attribute__ ((packed));
606 
607 /* The following function really belong in v4l2-common, but that causes
608    a circular dependency between modules. We need to think about this, but
609    for now this will do. */
610 
611 /* Return non-zero if this control is a pointer type. Currently only
612    type STRING is a pointer type. */
ctrl_is_pointer(u32 id)613 static inline int ctrl_is_pointer(u32 id)
614 {
615 	switch (id) {
616 	case V4L2_CID_RDS_TX_PS_NAME:
617 	case V4L2_CID_RDS_TX_RADIO_TEXT:
618 		return 1;
619 	default:
620 		return 0;
621 	}
622 }
623 
get_v4l2_ext_controls32(struct v4l2_ext_controls * kp,struct v4l2_ext_controls32 __user * up)624 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
625 {
626 	struct v4l2_ext_control32 __user *ucontrols;
627 	struct v4l2_ext_control __user *kcontrols;
628 	int n;
629 	compat_caddr_t p;
630 
631 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
632 		get_user(kp->ctrl_class, &up->ctrl_class) ||
633 		get_user(kp->count, &up->count) ||
634 		get_user(kp->error_idx, &up->error_idx) ||
635 		copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
636 			return -EFAULT;
637 	n = kp->count;
638 	if (n == 0) {
639 		kp->controls = NULL;
640 		return 0;
641 	}
642 	if (get_user(p, &up->controls))
643 		return -EFAULT;
644 	ucontrols = compat_ptr(p);
645 	if (!access_ok(VERIFY_READ, ucontrols,
646 			n * sizeof(struct v4l2_ext_control32)))
647 		return -EFAULT;
648 	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
649 	kp->controls = kcontrols;
650 	while (--n >= 0) {
651 		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
652 			return -EFAULT;
653 		if (ctrl_is_pointer(kcontrols->id)) {
654 			void __user *s;
655 
656 			if (get_user(p, &ucontrols->string))
657 				return -EFAULT;
658 			s = compat_ptr(p);
659 			if (put_user(s, &kcontrols->string))
660 				return -EFAULT;
661 		}
662 		ucontrols++;
663 		kcontrols++;
664 	}
665 	return 0;
666 }
667 
put_v4l2_ext_controls32(struct v4l2_ext_controls * kp,struct v4l2_ext_controls32 __user * up)668 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
669 {
670 	struct v4l2_ext_control32 __user *ucontrols;
671 	struct v4l2_ext_control __user *kcontrols = kp->controls;
672 	int n = kp->count;
673 	compat_caddr_t p;
674 
675 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
676 		put_user(kp->ctrl_class, &up->ctrl_class) ||
677 		put_user(kp->count, &up->count) ||
678 		put_user(kp->error_idx, &up->error_idx) ||
679 		copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
680 			return -EFAULT;
681 	if (!kp->count)
682 		return 0;
683 
684 	if (get_user(p, &up->controls))
685 		return -EFAULT;
686 	ucontrols = compat_ptr(p);
687 	if (!access_ok(VERIFY_WRITE, ucontrols,
688 			n * sizeof(struct v4l2_ext_control32)))
689 		return -EFAULT;
690 
691 	while (--n >= 0) {
692 		unsigned size = sizeof(*ucontrols);
693 
694 		/* Do not modify the pointer when copying a pointer control.
695 		   The contents of the pointer was changed, not the pointer
696 		   itself. */
697 		if (ctrl_is_pointer(kcontrols->id))
698 			size -= sizeof(ucontrols->value64);
699 		if (copy_in_user(ucontrols, kcontrols, size))
700 			return -EFAULT;
701 		ucontrols++;
702 		kcontrols++;
703 	}
704 	return 0;
705 }
706 
707 struct v4l2_event32 {
708 	__u32				type;
709 	union {
710 		__u8			data[64];
711 	} u;
712 	__u32				pending;
713 	__u32				sequence;
714 	struct compat_timespec		timestamp;
715 	__u32				id;
716 	__u32				reserved[8];
717 };
718 
put_v4l2_event32(struct v4l2_event * kp,struct v4l2_event32 __user * up)719 static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
720 {
721 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
722 		put_user(kp->type, &up->type) ||
723 		copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
724 		put_user(kp->pending, &up->pending) ||
725 		put_user(kp->sequence, &up->sequence) ||
726 		put_compat_timespec(&kp->timestamp, &up->timestamp) ||
727 		put_user(kp->id, &up->id) ||
728 		copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
729 			return -EFAULT;
730 	return 0;
731 }
732 
733 #define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)
734 #define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)
735 #define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)
736 #define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)
737 #define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)
738 #define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)
739 #define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
740 #define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
741 #define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
742 #define VIDIOC_TRY_FMT32      	_IOWR('V', 64, struct v4l2_format32)
743 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
744 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
745 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
746 #define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
747 #define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)
748 #define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
749 
750 #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
751 #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
752 #define VIDIOC_STREAMOFF32	_IOW ('V', 19, s32)
753 #define VIDIOC_G_INPUT32	_IOR ('V', 38, s32)
754 #define VIDIOC_S_INPUT32	_IOWR('V', 39, s32)
755 #define VIDIOC_G_OUTPUT32	_IOR ('V', 46, s32)
756 #define VIDIOC_S_OUTPUT32	_IOWR('V', 47, s32)
757 
do_video_ioctl(struct file * file,unsigned int cmd,unsigned long arg)758 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
759 {
760 	union {
761 		struct v4l2_format v2f;
762 		struct v4l2_buffer v2b;
763 		struct v4l2_framebuffer v2fb;
764 		struct v4l2_input v2i;
765 		struct v4l2_standard v2s;
766 		struct v4l2_ext_controls v2ecs;
767 		struct v4l2_event v2ev;
768 		struct v4l2_create_buffers v2crt;
769 		unsigned long vx;
770 		int vi;
771 	} karg;
772 	void __user *up = compat_ptr(arg);
773 	int compatible_arg = 1;
774 	long err = 0;
775 
776 	/* First, convert the command. */
777 	switch (cmd) {
778 	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
779 	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
780 	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
781 	case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
782 	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
783 	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
784 	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
785 	case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
786 	case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
787 	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
788 	case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
789 	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
790 	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
791 	case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
792 	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
793 	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
794 	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
795 	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
796 	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
797 	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
798 	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
799 	case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
800 	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
801 	}
802 
803 	switch (cmd) {
804 	case VIDIOC_OVERLAY:
805 	case VIDIOC_STREAMON:
806 	case VIDIOC_STREAMOFF:
807 	case VIDIOC_S_INPUT:
808 	case VIDIOC_S_OUTPUT:
809 		err = get_user(karg.vi, (s32 __user *)up);
810 		compatible_arg = 0;
811 		break;
812 
813 	case VIDIOC_G_INPUT:
814 	case VIDIOC_G_OUTPUT:
815 		compatible_arg = 0;
816 		break;
817 
818 	case VIDIOC_G_FMT:
819 	case VIDIOC_S_FMT:
820 	case VIDIOC_TRY_FMT:
821 		err = get_v4l2_format32(&karg.v2f, up);
822 		compatible_arg = 0;
823 		break;
824 
825 	case VIDIOC_CREATE_BUFS:
826 		err = get_v4l2_create32(&karg.v2crt, up);
827 		compatible_arg = 0;
828 		break;
829 
830 	case VIDIOC_PREPARE_BUF:
831 	case VIDIOC_QUERYBUF:
832 	case VIDIOC_QBUF:
833 	case VIDIOC_DQBUF:
834 		err = get_v4l2_buffer32(&karg.v2b, up);
835 		compatible_arg = 0;
836 		break;
837 
838 	case VIDIOC_S_FBUF:
839 		err = get_v4l2_framebuffer32(&karg.v2fb, up);
840 		compatible_arg = 0;
841 		break;
842 
843 	case VIDIOC_G_FBUF:
844 		compatible_arg = 0;
845 		break;
846 
847 	case VIDIOC_ENUMSTD:
848 		err = get_v4l2_standard32(&karg.v2s, up);
849 		compatible_arg = 0;
850 		break;
851 
852 	case VIDIOC_ENUMINPUT:
853 		err = get_v4l2_input32(&karg.v2i, up);
854 		compatible_arg = 0;
855 		break;
856 
857 	case VIDIOC_G_EXT_CTRLS:
858 	case VIDIOC_S_EXT_CTRLS:
859 	case VIDIOC_TRY_EXT_CTRLS:
860 		err = get_v4l2_ext_controls32(&karg.v2ecs, up);
861 		compatible_arg = 0;
862 		break;
863 	case VIDIOC_DQEVENT:
864 		compatible_arg = 0;
865 		break;
866 	}
867 	if (err)
868 		return err;
869 
870 	if (compatible_arg)
871 		err = native_ioctl(file, cmd, (unsigned long)up);
872 	else {
873 		mm_segment_t old_fs = get_fs();
874 
875 		set_fs(KERNEL_DS);
876 		err = native_ioctl(file, cmd, (unsigned long)&karg);
877 		set_fs(old_fs);
878 	}
879 
880 	/* Special case: even after an error we need to put the
881 	   results back for these ioctls since the error_idx will
882 	   contain information on which control failed. */
883 	switch (cmd) {
884 	case VIDIOC_G_EXT_CTRLS:
885 	case VIDIOC_S_EXT_CTRLS:
886 	case VIDIOC_TRY_EXT_CTRLS:
887 		if (put_v4l2_ext_controls32(&karg.v2ecs, up))
888 			err = -EFAULT;
889 		break;
890 	}
891 	if (err)
892 		return err;
893 
894 	switch (cmd) {
895 	case VIDIOC_S_INPUT:
896 	case VIDIOC_S_OUTPUT:
897 	case VIDIOC_G_INPUT:
898 	case VIDIOC_G_OUTPUT:
899 		err = put_user(((s32)karg.vi), (s32 __user *)up);
900 		break;
901 
902 	case VIDIOC_G_FBUF:
903 		err = put_v4l2_framebuffer32(&karg.v2fb, up);
904 		break;
905 
906 	case VIDIOC_DQEVENT:
907 		err = put_v4l2_event32(&karg.v2ev, up);
908 		break;
909 
910 	case VIDIOC_G_FMT:
911 	case VIDIOC_S_FMT:
912 	case VIDIOC_TRY_FMT:
913 		err = put_v4l2_format32(&karg.v2f, up);
914 		break;
915 
916 	case VIDIOC_CREATE_BUFS:
917 		err = put_v4l2_create32(&karg.v2crt, up);
918 		break;
919 
920 	case VIDIOC_QUERYBUF:
921 	case VIDIOC_QBUF:
922 	case VIDIOC_DQBUF:
923 		err = put_v4l2_buffer32(&karg.v2b, up);
924 		break;
925 
926 	case VIDIOC_ENUMSTD:
927 		err = put_v4l2_standard32(&karg.v2s, up);
928 		break;
929 
930 	case VIDIOC_ENUMINPUT:
931 		err = put_v4l2_input32(&karg.v2i, up);
932 		break;
933 	}
934 	return err;
935 }
936 
v4l2_compat_ioctl32(struct file * file,unsigned int cmd,unsigned long arg)937 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
938 {
939 	struct video_device *vdev = video_devdata(file);
940 	long ret = -ENOIOCTLCMD;
941 
942 	if (!file->f_op->unlocked_ioctl)
943 		return ret;
944 
945 	switch (cmd) {
946 	case VIDIOC_QUERYCAP:
947 	case VIDIOC_RESERVED:
948 	case VIDIOC_ENUM_FMT:
949 	case VIDIOC_G_FMT32:
950 	case VIDIOC_S_FMT32:
951 	case VIDIOC_REQBUFS:
952 	case VIDIOC_QUERYBUF32:
953 	case VIDIOC_G_FBUF32:
954 	case VIDIOC_S_FBUF32:
955 	case VIDIOC_OVERLAY32:
956 	case VIDIOC_QBUF32:
957 	case VIDIOC_DQBUF32:
958 	case VIDIOC_STREAMON32:
959 	case VIDIOC_STREAMOFF32:
960 	case VIDIOC_G_PARM:
961 	case VIDIOC_S_PARM:
962 	case VIDIOC_G_STD:
963 	case VIDIOC_S_STD:
964 	case VIDIOC_ENUMSTD32:
965 	case VIDIOC_ENUMINPUT32:
966 	case VIDIOC_G_CTRL:
967 	case VIDIOC_S_CTRL:
968 	case VIDIOC_G_TUNER:
969 	case VIDIOC_S_TUNER:
970 	case VIDIOC_G_AUDIO:
971 	case VIDIOC_S_AUDIO:
972 	case VIDIOC_QUERYCTRL:
973 	case VIDIOC_QUERYMENU:
974 	case VIDIOC_G_INPUT32:
975 	case VIDIOC_S_INPUT32:
976 	case VIDIOC_G_OUTPUT32:
977 	case VIDIOC_S_OUTPUT32:
978 	case VIDIOC_ENUMOUTPUT:
979 	case VIDIOC_G_AUDOUT:
980 	case VIDIOC_S_AUDOUT:
981 	case VIDIOC_G_MODULATOR:
982 	case VIDIOC_S_MODULATOR:
983 	case VIDIOC_S_FREQUENCY:
984 	case VIDIOC_G_FREQUENCY:
985 	case VIDIOC_CROPCAP:
986 	case VIDIOC_G_CROP:
987 	case VIDIOC_S_CROP:
988 	case VIDIOC_G_SELECTION:
989 	case VIDIOC_S_SELECTION:
990 	case VIDIOC_G_JPEGCOMP:
991 	case VIDIOC_S_JPEGCOMP:
992 	case VIDIOC_QUERYSTD:
993 	case VIDIOC_TRY_FMT32:
994 	case VIDIOC_ENUMAUDIO:
995 	case VIDIOC_ENUMAUDOUT:
996 	case VIDIOC_G_PRIORITY:
997 	case VIDIOC_S_PRIORITY:
998 	case VIDIOC_G_SLICED_VBI_CAP:
999 	case VIDIOC_LOG_STATUS:
1000 	case VIDIOC_G_EXT_CTRLS32:
1001 	case VIDIOC_S_EXT_CTRLS32:
1002 	case VIDIOC_TRY_EXT_CTRLS32:
1003 	case VIDIOC_ENUM_FRAMESIZES:
1004 	case VIDIOC_ENUM_FRAMEINTERVALS:
1005 	case VIDIOC_G_ENC_INDEX:
1006 	case VIDIOC_ENCODER_CMD:
1007 	case VIDIOC_TRY_ENCODER_CMD:
1008 	case VIDIOC_DECODER_CMD:
1009 	case VIDIOC_TRY_DECODER_CMD:
1010 	case VIDIOC_DBG_S_REGISTER:
1011 	case VIDIOC_DBG_G_REGISTER:
1012 	case VIDIOC_DBG_G_CHIP_IDENT:
1013 	case VIDIOC_S_HW_FREQ_SEEK:
1014 	case VIDIOC_ENUM_DV_PRESETS:
1015 	case VIDIOC_S_DV_PRESET:
1016 	case VIDIOC_G_DV_PRESET:
1017 	case VIDIOC_QUERY_DV_PRESET:
1018 	case VIDIOC_S_DV_TIMINGS:
1019 	case VIDIOC_G_DV_TIMINGS:
1020 	case VIDIOC_DQEVENT:
1021 	case VIDIOC_DQEVENT32:
1022 	case VIDIOC_SUBSCRIBE_EVENT:
1023 	case VIDIOC_UNSUBSCRIBE_EVENT:
1024 	case VIDIOC_CREATE_BUFS32:
1025 	case VIDIOC_PREPARE_BUF32:
1026 		ret = do_video_ioctl(file, cmd, arg);
1027 		break;
1028 
1029 	default:
1030 		if (vdev->fops->compat_ioctl32)
1031 			ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1032 
1033 		if (ret == -ENOIOCTLCMD)
1034 			printk(KERN_WARNING "compat_ioctl32: "
1035 				"unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1036 				_IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd),
1037 				cmd);
1038 		break;
1039 	}
1040 	return ret;
1041 }
1042 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
1043