1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4 *	Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
5 *
6 * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
7 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
8 * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
9 * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
10 * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
11 * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
12 *
13 * These routines maintain argument size conversion between 32bit and 64bit
14 * ioctls.
15 */
16
17#include <linux/compat.h>
18#include <linux/module.h>
19#include <linux/videodev2.h>
20#include <linux/v4l2-subdev.h>
21#include <media/v4l2-dev.h>
22#include <media/v4l2-fh.h>
23#include <media/v4l2-ctrls.h>
24#include <media/v4l2-ioctl.h>
25
26/*
27 * Per-ioctl data copy handlers.
28 *
29 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
30 * where "v4l2_foo" is the name of the V4L2 struct.
31 *
32 * They basically get two __user pointers, one with a 32-bits struct that
33 * came from the userspace call and a 64-bits struct, also allocated as
34 * userspace, but filled internally by do_video_ioctl().
35 *
36 * For ioctls that have pointers inside it, the functions will also
37 * receive an ancillary buffer with extra space, used to pass extra
38 * data to the routine.
39 */
40
41struct v4l2_window32 {
42	struct v4l2_rect        w;
43	__u32			field;	/* enum v4l2_field */
44	__u32			chromakey;
45	compat_caddr_t		clips; /* always NULL */
46	__u32			clipcount; /* always 0 */
47	compat_caddr_t		bitmap; /* always NULL */
48	__u8                    global_alpha;
49};
50
51static int get_v4l2_window32(struct v4l2_window *p64,
52			     struct v4l2_window32 __user *p32)
53{
54	struct v4l2_window32 w32;
55
56	if (copy_from_user(&w32, p32, sizeof(w32)))
57		return -EFAULT;
58
59	*p64 = (struct v4l2_window) {
60		.w		= w32.w,
61		.field		= w32.field,
62		.chromakey	= w32.chromakey,
63		.clips		= NULL,
64		.clipcount	= 0,
65		.bitmap		= NULL,
66		.global_alpha	= w32.global_alpha,
67	};
68
69	return 0;
70}
71
72static int put_v4l2_window32(struct v4l2_window *p64,
73			     struct v4l2_window32 __user *p32)
74{
75	struct v4l2_window32 w32;
76
77	memset(&w32, 0, sizeof(w32));
78	w32 = (struct v4l2_window32) {
79		.w		= p64->w,
80		.field		= p64->field,
81		.chromakey	= p64->chromakey,
82		.clips		= 0,
83		.clipcount	= 0,
84		.bitmap		= 0,
85		.global_alpha	= p64->global_alpha,
86	};
87
88	if (copy_to_user(p32, &w32, sizeof(w32)))
89		return -EFAULT;
90
91	return 0;
92}
93
94struct v4l2_format32 {
95	__u32	type;	/* enum v4l2_buf_type */
96	union {
97		struct v4l2_pix_format	pix;
98		struct v4l2_pix_format_mplane	pix_mp;
99		struct v4l2_window32	win;
100		struct v4l2_vbi_format	vbi;
101		struct v4l2_sliced_vbi_format	sliced;
102		struct v4l2_sdr_format	sdr;
103		struct v4l2_meta_format	meta;
104		__u8	raw_data[200];        /* user-defined */
105	} fmt;
106};
107
108/**
109 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
110 * @index:	on return, index of the first created buffer
111 * @count:	entry: number of requested buffers,
112 *		return: number of created buffers
113 * @memory:	buffer memory type
114 * @format:	frame format, for which buffers are requested
115 * @capabilities: capabilities of this buffer type.
116 * @flags:	additional buffer management attributes (ignored unless the
117 *		queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
118 *		configured for MMAP streaming I/O).
119 * @reserved:	future extensions
120 */
121struct v4l2_create_buffers32 {
122	__u32			index;
123	__u32			count;
124	__u32			memory;	/* enum v4l2_memory */
125	struct v4l2_format32	format;
126	__u32			capabilities;
127	__u32			flags;
128	__u32			reserved[6];
129};
130
131static int get_v4l2_format32(struct v4l2_format *p64,
132			     struct v4l2_format32 __user *p32)
133{
134	if (get_user(p64->type, &p32->type))
135		return -EFAULT;
136
137	switch (p64->type) {
138	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
139	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
140		return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
141				      sizeof(p64->fmt.pix)) ? -EFAULT : 0;
142	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
143	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
144		return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
145				      sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
146	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
147	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
148		return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
149	case V4L2_BUF_TYPE_VBI_CAPTURE:
150	case V4L2_BUF_TYPE_VBI_OUTPUT:
151		return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
152				      sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
153	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
154	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
155		return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
156				      sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
157	case V4L2_BUF_TYPE_SDR_CAPTURE:
158	case V4L2_BUF_TYPE_SDR_OUTPUT:
159		return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
160				      sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
161	case V4L2_BUF_TYPE_META_CAPTURE:
162	case V4L2_BUF_TYPE_META_OUTPUT:
163		return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
164				      sizeof(p64->fmt.meta)) ? -EFAULT : 0;
165	default:
166		return -EINVAL;
167	}
168}
169
170static int get_v4l2_create32(struct v4l2_create_buffers *p64,
171			     struct v4l2_create_buffers32 __user *p32)
172{
173	if (copy_from_user(p64, p32,
174			   offsetof(struct v4l2_create_buffers32, format)))
175		return -EFAULT;
176	if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
177		return -EFAULT;
178	return get_v4l2_format32(&p64->format, &p32->format);
179}
180
181static int put_v4l2_format32(struct v4l2_format *p64,
182			     struct v4l2_format32 __user *p32)
183{
184	switch (p64->type) {
185	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
186	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
187		return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
188				    sizeof(p64->fmt.pix)) ? -EFAULT : 0;
189	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
190	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
191		return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
192				    sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
193	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
194	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
195		return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
196	case V4L2_BUF_TYPE_VBI_CAPTURE:
197	case V4L2_BUF_TYPE_VBI_OUTPUT:
198		return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
199				    sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
200	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
201	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
202		return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
203				    sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
204	case V4L2_BUF_TYPE_SDR_CAPTURE:
205	case V4L2_BUF_TYPE_SDR_OUTPUT:
206		return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
207				    sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
208	case V4L2_BUF_TYPE_META_CAPTURE:
209	case V4L2_BUF_TYPE_META_OUTPUT:
210		return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
211				    sizeof(p64->fmt.meta)) ? -EFAULT : 0;
212	default:
213		return -EINVAL;
214	}
215}
216
217static int put_v4l2_create32(struct v4l2_create_buffers *p64,
218			     struct v4l2_create_buffers32 __user *p32)
219{
220	if (copy_to_user(p32, p64,
221			 offsetof(struct v4l2_create_buffers32, format)) ||
222	    put_user(p64->capabilities, &p32->capabilities) ||
223	    put_user(p64->flags, &p32->flags) ||
224	    copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
225		return -EFAULT;
226	return put_v4l2_format32(&p64->format, &p32->format);
227}
228
229struct v4l2_standard32 {
230	__u32		     index;
231	compat_u64	     id;
232	__u8		     name[24];
233	struct v4l2_fract    frameperiod; /* Frames, not fields */
234	__u32		     framelines;
235	__u32		     reserved[4];
236};
237
238static int get_v4l2_standard32(struct v4l2_standard *p64,
239			       struct v4l2_standard32 __user *p32)
240{
241	/* other fields are not set by the user, nor used by the driver */
242	return get_user(p64->index, &p32->index);
243}
244
245static int put_v4l2_standard32(struct v4l2_standard *p64,
246			       struct v4l2_standard32 __user *p32)
247{
248	if (put_user(p64->index, &p32->index) ||
249	    put_user(p64->id, &p32->id) ||
250	    copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
251	    copy_to_user(&p32->frameperiod, &p64->frameperiod,
252			 sizeof(p32->frameperiod)) ||
253	    put_user(p64->framelines, &p32->framelines) ||
254	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
255		return -EFAULT;
256	return 0;
257}
258
259struct v4l2_plane32 {
260	__u32			bytesused;
261	__u32			length;
262	union {
263		__u32		mem_offset;
264		compat_long_t	userptr;
265		__s32		fd;
266	} m;
267	__u32			data_offset;
268	__u32			reserved[11];
269};
270
271/*
272 * This is correct for all architectures including i386, but not x32,
273 * which has different alignment requirements for timestamp
274 */
275struct v4l2_buffer32 {
276	__u32			index;
277	__u32			type;	/* enum v4l2_buf_type */
278	__u32			bytesused;
279	__u32			flags;
280	__u32			field;	/* enum v4l2_field */
281	struct {
282		compat_s64	tv_sec;
283		compat_s64	tv_usec;
284	}			timestamp;
285	struct v4l2_timecode	timecode;
286	__u32			sequence;
287
288	/* memory location */
289	__u32			memory;	/* enum v4l2_memory */
290	union {
291		__u32           offset;
292		compat_long_t   userptr;
293		compat_caddr_t  planes;
294		__s32		fd;
295	} m;
296	__u32			length;
297	__u32			reserved2;
298	__s32			request_fd;
299};
300
301#ifdef CONFIG_COMPAT_32BIT_TIME
302struct v4l2_buffer32_time32 {
303	__u32			index;
304	__u32			type;	/* enum v4l2_buf_type */
305	__u32			bytesused;
306	__u32			flags;
307	__u32			field;	/* enum v4l2_field */
308	struct old_timeval32	timestamp;
309	struct v4l2_timecode	timecode;
310	__u32			sequence;
311
312	/* memory location */
313	__u32			memory;	/* enum v4l2_memory */
314	union {
315		__u32           offset;
316		compat_long_t   userptr;
317		compat_caddr_t  planes;
318		__s32		fd;
319	} m;
320	__u32			length;
321	__u32			reserved2;
322	__s32			request_fd;
323};
324#endif
325
326static int get_v4l2_plane32(struct v4l2_plane *p64,
327			    struct v4l2_plane32 __user *p32,
328			    enum v4l2_memory memory)
329{
330	struct v4l2_plane32 plane32;
331	typeof(p64->m) m = {};
332
333	if (copy_from_user(&plane32, p32, sizeof(plane32)))
334		return -EFAULT;
335
336	switch (memory) {
337	case V4L2_MEMORY_MMAP:
338	case V4L2_MEMORY_OVERLAY:
339		m.mem_offset = plane32.m.mem_offset;
340		break;
341	case V4L2_MEMORY_USERPTR:
342		m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
343		break;
344	case V4L2_MEMORY_DMABUF:
345		m.fd = plane32.m.fd;
346		break;
347	}
348
349	memset(p64, 0, sizeof(*p64));
350	*p64 = (struct v4l2_plane) {
351		.bytesused	= plane32.bytesused,
352		.length		= plane32.length,
353		.m		= m,
354		.data_offset	= plane32.data_offset,
355	};
356
357	return 0;
358}
359
360static int put_v4l2_plane32(struct v4l2_plane *p64,
361			    struct v4l2_plane32 __user *p32,
362			    enum v4l2_memory memory)
363{
364	struct v4l2_plane32 plane32;
365
366	memset(&plane32, 0, sizeof(plane32));
367	plane32 = (struct v4l2_plane32) {
368		.bytesused	= p64->bytesused,
369		.length		= p64->length,
370		.data_offset	= p64->data_offset,
371	};
372
373	switch (memory) {
374	case V4L2_MEMORY_MMAP:
375	case V4L2_MEMORY_OVERLAY:
376		plane32.m.mem_offset = p64->m.mem_offset;
377		break;
378	case V4L2_MEMORY_USERPTR:
379		plane32.m.userptr = (uintptr_t)(p64->m.userptr);
380		break;
381	case V4L2_MEMORY_DMABUF:
382		plane32.m.fd = p64->m.fd;
383		break;
384	}
385
386	if (copy_to_user(p32, &plane32, sizeof(plane32)))
387		return -EFAULT;
388
389	return 0;
390}
391
392static int get_v4l2_buffer32(struct v4l2_buffer *vb,
393			     struct v4l2_buffer32 __user *arg)
394{
395	struct v4l2_buffer32 vb32;
396
397	if (copy_from_user(&vb32, arg, sizeof(vb32)))
398		return -EFAULT;
399
400	memset(vb, 0, sizeof(*vb));
401	*vb = (struct v4l2_buffer) {
402		.index		= vb32.index,
403		.type		= vb32.type,
404		.bytesused	= vb32.bytesused,
405		.flags		= vb32.flags,
406		.field		= vb32.field,
407		.timestamp.tv_sec	= vb32.timestamp.tv_sec,
408		.timestamp.tv_usec	= vb32.timestamp.tv_usec,
409		.timecode	= vb32.timecode,
410		.sequence	= vb32.sequence,
411		.memory		= vb32.memory,
412		.m.offset	= vb32.m.offset,
413		.length		= vb32.length,
414		.request_fd	= vb32.request_fd,
415	};
416
417	switch (vb->memory) {
418	case V4L2_MEMORY_MMAP:
419	case V4L2_MEMORY_OVERLAY:
420		vb->m.offset = vb32.m.offset;
421		break;
422	case V4L2_MEMORY_USERPTR:
423		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
424		break;
425	case V4L2_MEMORY_DMABUF:
426		vb->m.fd = vb32.m.fd;
427		break;
428	}
429
430	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
431		vb->m.planes = (void __force *)
432				compat_ptr(vb32.m.planes);
433
434	return 0;
435}
436
437#ifdef CONFIG_COMPAT_32BIT_TIME
438static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
439				    struct v4l2_buffer32_time32 __user *arg)
440{
441	struct v4l2_buffer32_time32 vb32;
442
443	if (copy_from_user(&vb32, arg, sizeof(vb32)))
444		return -EFAULT;
445
446	*vb = (struct v4l2_buffer) {
447		.index		= vb32.index,
448		.type		= vb32.type,
449		.bytesused	= vb32.bytesused,
450		.flags		= vb32.flags,
451		.field		= vb32.field,
452		.timestamp.tv_sec	= vb32.timestamp.tv_sec,
453		.timestamp.tv_usec	= vb32.timestamp.tv_usec,
454		.timecode	= vb32.timecode,
455		.sequence	= vb32.sequence,
456		.memory		= vb32.memory,
457		.m.offset	= vb32.m.offset,
458		.length		= vb32.length,
459		.request_fd	= vb32.request_fd,
460	};
461	switch (vb->memory) {
462	case V4L2_MEMORY_MMAP:
463	case V4L2_MEMORY_OVERLAY:
464		vb->m.offset = vb32.m.offset;
465		break;
466	case V4L2_MEMORY_USERPTR:
467		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
468		break;
469	case V4L2_MEMORY_DMABUF:
470		vb->m.fd = vb32.m.fd;
471		break;
472	}
473
474	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
475		vb->m.planes = (void __force *)
476				compat_ptr(vb32.m.planes);
477
478	return 0;
479}
480#endif
481
482static int put_v4l2_buffer32(struct v4l2_buffer *vb,
483			     struct v4l2_buffer32 __user *arg)
484{
485	struct v4l2_buffer32 vb32;
486
487	memset(&vb32, 0, sizeof(vb32));
488	vb32 = (struct v4l2_buffer32) {
489		.index		= vb->index,
490		.type		= vb->type,
491		.bytesused	= vb->bytesused,
492		.flags		= vb->flags,
493		.field		= vb->field,
494		.timestamp.tv_sec	= vb->timestamp.tv_sec,
495		.timestamp.tv_usec	= vb->timestamp.tv_usec,
496		.timecode	= vb->timecode,
497		.sequence	= vb->sequence,
498		.memory		= vb->memory,
499		.m.offset	= vb->m.offset,
500		.length		= vb->length,
501		.request_fd	= vb->request_fd,
502	};
503
504	switch (vb->memory) {
505	case V4L2_MEMORY_MMAP:
506	case V4L2_MEMORY_OVERLAY:
507		vb32.m.offset = vb->m.offset;
508		break;
509	case V4L2_MEMORY_USERPTR:
510		vb32.m.userptr = (uintptr_t)(vb->m.userptr);
511		break;
512	case V4L2_MEMORY_DMABUF:
513		vb32.m.fd = vb->m.fd;
514		break;
515	}
516
517	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
518		vb32.m.planes = (uintptr_t)vb->m.planes;
519
520	if (copy_to_user(arg, &vb32, sizeof(vb32)))
521		return -EFAULT;
522
523	return 0;
524}
525
526#ifdef CONFIG_COMPAT_32BIT_TIME
527static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
528				    struct v4l2_buffer32_time32 __user *arg)
529{
530	struct v4l2_buffer32_time32 vb32;
531
532	memset(&vb32, 0, sizeof(vb32));
533	vb32 = (struct v4l2_buffer32_time32) {
534		.index		= vb->index,
535		.type		= vb->type,
536		.bytesused	= vb->bytesused,
537		.flags		= vb->flags,
538		.field		= vb->field,
539		.timestamp.tv_sec	= vb->timestamp.tv_sec,
540		.timestamp.tv_usec	= vb->timestamp.tv_usec,
541		.timecode	= vb->timecode,
542		.sequence	= vb->sequence,
543		.memory		= vb->memory,
544		.m.offset	= vb->m.offset,
545		.length		= vb->length,
546		.request_fd	= vb->request_fd,
547	};
548	switch (vb->memory) {
549	case V4L2_MEMORY_MMAP:
550	case V4L2_MEMORY_OVERLAY:
551		vb32.m.offset = vb->m.offset;
552		break;
553	case V4L2_MEMORY_USERPTR:
554		vb32.m.userptr = (uintptr_t)(vb->m.userptr);
555		break;
556	case V4L2_MEMORY_DMABUF:
557		vb32.m.fd = vb->m.fd;
558		break;
559	}
560
561	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
562		vb32.m.planes = (uintptr_t)vb->m.planes;
563
564	if (copy_to_user(arg, &vb32, sizeof(vb32)))
565		return -EFAULT;
566
567	return 0;
568}
569#endif
570
571struct v4l2_framebuffer32 {
572	__u32			capability;
573	__u32			flags;
574	compat_caddr_t		base;
575	struct {
576		__u32		width;
577		__u32		height;
578		__u32		pixelformat;
579		__u32		field;
580		__u32		bytesperline;
581		__u32		sizeimage;
582		__u32		colorspace;
583		__u32		priv;
584	} fmt;
585};
586
587static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
588				  struct v4l2_framebuffer32 __user *p32)
589{
590	if (get_user(p64->capability, &p32->capability) ||
591	    get_user(p64->flags, &p32->flags) ||
592	    copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
593		return -EFAULT;
594	p64->base = NULL;
595
596	return 0;
597}
598
599static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
600				  struct v4l2_framebuffer32 __user *p32)
601{
602	if (put_user((uintptr_t)p64->base, &p32->base) ||
603	    put_user(p64->capability, &p32->capability) ||
604	    put_user(p64->flags, &p32->flags) ||
605	    copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
606		return -EFAULT;
607
608	return 0;
609}
610
611struct v4l2_input32 {
612	__u32	     index;		/*  Which input */
613	__u8	     name[32];		/*  Label */
614	__u32	     type;		/*  Type of input */
615	__u32	     audioset;		/*  Associated audios (bitfield) */
616	__u32        tuner;             /*  Associated tuner */
617	compat_u64   std;
618	__u32	     status;
619	__u32	     capabilities;
620	__u32	     reserved[3];
621};
622
623/*
624 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
625 * Otherwise it is identical to the 32-bit version.
626 */
627static inline int get_v4l2_input32(struct v4l2_input *p64,
628				   struct v4l2_input32 __user *p32)
629{
630	if (copy_from_user(p64, p32, sizeof(*p32)))
631		return -EFAULT;
632	return 0;
633}
634
635static inline int put_v4l2_input32(struct v4l2_input *p64,
636				   struct v4l2_input32 __user *p32)
637{
638	if (copy_to_user(p32, p64, sizeof(*p32)))
639		return -EFAULT;
640	return 0;
641}
642
643struct v4l2_ext_controls32 {
644	__u32 which;
645	__u32 count;
646	__u32 error_idx;
647	__s32 request_fd;
648	__u32 reserved[1];
649	compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
650};
651
652struct v4l2_ext_control32 {
653	__u32 id;
654	__u32 size;
655	__u32 reserved2[1];
656	union {
657		__s32 value;
658		__s64 value64;
659		compat_caddr_t string; /* actually char * */
660	};
661} __attribute__ ((packed));
662
663/* Return true if this control is a pointer type. */
664static inline bool ctrl_is_pointer(struct file *file, u32 id)
665{
666	struct video_device *vdev = video_devdata(file);
667	struct v4l2_fh *fh = NULL;
668	struct v4l2_ctrl_handler *hdl = NULL;
669	struct v4l2_query_ext_ctrl qec = { id };
670	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
671
672	if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
673		fh = file->private_data;
674
675	if (fh && fh->ctrl_handler)
676		hdl = fh->ctrl_handler;
677	else if (vdev->ctrl_handler)
678		hdl = vdev->ctrl_handler;
679
680	if (hdl) {
681		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
682
683		return ctrl && ctrl->is_ptr;
684	}
685
686	if (!ops || !ops->vidioc_query_ext_ctrl)
687		return false;
688
689	return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
690		(qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
691}
692
693static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
694				   struct v4l2_ext_controls32 __user *p32)
695{
696	struct v4l2_ext_controls32 ec32;
697
698	if (copy_from_user(&ec32, p32, sizeof(ec32)))
699		return -EFAULT;
700
701	*p64 = (struct v4l2_ext_controls) {
702		.which		= ec32.which,
703		.count		= ec32.count,
704		.error_idx	= ec32.error_idx,
705		.request_fd	= ec32.request_fd,
706		.reserved[0]	= ec32.reserved[0],
707		.controls	= (void __force *)compat_ptr(ec32.controls),
708	};
709
710	return 0;
711}
712
713static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
714				   struct v4l2_ext_controls32 __user *p32)
715{
716	struct v4l2_ext_controls32 ec32;
717
718	memset(&ec32, 0, sizeof(ec32));
719	ec32 = (struct v4l2_ext_controls32) {
720		.which		= p64->which,
721		.count		= p64->count,
722		.error_idx	= p64->error_idx,
723		.request_fd	= p64->request_fd,
724		.reserved[0]	= p64->reserved[0],
725		.controls	= (uintptr_t)p64->controls,
726	};
727
728	if (copy_to_user(p32, &ec32, sizeof(ec32)))
729		return -EFAULT;
730
731	return 0;
732}
733
734#ifdef CONFIG_X86_64
735/*
736 * x86 is the only compat architecture with different struct alignment
737 * between 32-bit and 64-bit tasks.
738 */
739struct v4l2_event32 {
740	__u32				type;
741	union {
742		compat_s64		value64;
743		__u8			data[64];
744	} u;
745	__u32				pending;
746	__u32				sequence;
747	struct {
748		compat_s64		tv_sec;
749		compat_s64		tv_nsec;
750	} timestamp;
751	__u32				id;
752	__u32				reserved[8];
753};
754
755static int put_v4l2_event32(struct v4l2_event *p64,
756			    struct v4l2_event32 __user *p32)
757{
758	if (put_user(p64->type, &p32->type) ||
759	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
760	    put_user(p64->pending, &p32->pending) ||
761	    put_user(p64->sequence, &p32->sequence) ||
762	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
763	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
764	    put_user(p64->id, &p32->id) ||
765	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
766		return -EFAULT;
767	return 0;
768}
769
770#endif
771
772#ifdef CONFIG_COMPAT_32BIT_TIME
773struct v4l2_event32_time32 {
774	__u32				type;
775	union {
776		compat_s64		value64;
777		__u8			data[64];
778	} u;
779	__u32				pending;
780	__u32				sequence;
781	struct old_timespec32		timestamp;
782	__u32				id;
783	__u32				reserved[8];
784};
785
786static int put_v4l2_event32_time32(struct v4l2_event *p64,
787				   struct v4l2_event32_time32 __user *p32)
788{
789	if (put_user(p64->type, &p32->type) ||
790	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
791	    put_user(p64->pending, &p32->pending) ||
792	    put_user(p64->sequence, &p32->sequence) ||
793	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
794	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
795	    put_user(p64->id, &p32->id) ||
796	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
797		return -EFAULT;
798	return 0;
799}
800#endif
801
802struct v4l2_edid32 {
803	__u32 pad;
804	__u32 start_block;
805	__u32 blocks;
806	__u32 reserved[5];
807	compat_caddr_t edid;
808};
809
810static int get_v4l2_edid32(struct v4l2_edid *p64,
811			   struct v4l2_edid32 __user *p32)
812{
813	compat_uptr_t edid;
814
815	if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
816	    get_user(edid, &p32->edid))
817		return -EFAULT;
818
819	p64->edid = (void __force *)compat_ptr(edid);
820	return 0;
821}
822
823static int put_v4l2_edid32(struct v4l2_edid *p64,
824			   struct v4l2_edid32 __user *p32)
825{
826	if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
827		return -EFAULT;
828	return 0;
829}
830
831/*
832 * List of ioctls that require 32-bits/64-bits conversion
833 *
834 * The V4L2 ioctls that aren't listed there don't have pointer arguments
835 * and the struct size is identical for both 32 and 64 bits versions, so
836 * they don't need translations.
837 */
838
839#define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)
840#define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)
841#define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)
842#define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)
843#define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)
844#define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)
845#define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
846#define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
847#define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
848#define VIDIOC_G_EDID32		_IOWR('V', 40, struct v4l2_edid32)
849#define VIDIOC_S_EDID32		_IOWR('V', 41, struct v4l2_edid32)
850#define VIDIOC_TRY_FMT32	_IOWR('V', 64, struct v4l2_format32)
851#define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
852#define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
853#define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
854#define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
855#define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)
856#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
857
858#ifdef CONFIG_COMPAT_32BIT_TIME
859#define VIDIOC_QUERYBUF32_TIME32	_IOWR('V',  9, struct v4l2_buffer32_time32)
860#define VIDIOC_QBUF32_TIME32		_IOWR('V', 15, struct v4l2_buffer32_time32)
861#define VIDIOC_DQBUF32_TIME32		_IOWR('V', 17, struct v4l2_buffer32_time32)
862#define	VIDIOC_DQEVENT32_TIME32		_IOR ('V', 89, struct v4l2_event32_time32)
863#define VIDIOC_PREPARE_BUF32_TIME32	_IOWR('V', 93, struct v4l2_buffer32_time32)
864#endif
865
866unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
867{
868	switch (cmd) {
869	case VIDIOC_G_FMT32:
870		return VIDIOC_G_FMT;
871	case VIDIOC_S_FMT32:
872		return VIDIOC_S_FMT;
873	case VIDIOC_TRY_FMT32:
874		return VIDIOC_TRY_FMT;
875	case VIDIOC_G_FBUF32:
876		return VIDIOC_G_FBUF;
877	case VIDIOC_S_FBUF32:
878		return VIDIOC_S_FBUF;
879#ifdef CONFIG_COMPAT_32BIT_TIME
880	case VIDIOC_QUERYBUF32_TIME32:
881		return VIDIOC_QUERYBUF;
882	case VIDIOC_QBUF32_TIME32:
883		return VIDIOC_QBUF;
884	case VIDIOC_DQBUF32_TIME32:
885		return VIDIOC_DQBUF;
886	case VIDIOC_PREPARE_BUF32_TIME32:
887		return VIDIOC_PREPARE_BUF;
888#endif
889	case VIDIOC_QUERYBUF32:
890		return VIDIOC_QUERYBUF;
891	case VIDIOC_QBUF32:
892		return VIDIOC_QBUF;
893	case VIDIOC_DQBUF32:
894		return VIDIOC_DQBUF;
895	case VIDIOC_CREATE_BUFS32:
896		return VIDIOC_CREATE_BUFS;
897	case VIDIOC_G_EXT_CTRLS32:
898		return VIDIOC_G_EXT_CTRLS;
899	case VIDIOC_S_EXT_CTRLS32:
900		return VIDIOC_S_EXT_CTRLS;
901	case VIDIOC_TRY_EXT_CTRLS32:
902		return VIDIOC_TRY_EXT_CTRLS;
903	case VIDIOC_PREPARE_BUF32:
904		return VIDIOC_PREPARE_BUF;
905	case VIDIOC_ENUMSTD32:
906		return VIDIOC_ENUMSTD;
907	case VIDIOC_ENUMINPUT32:
908		return VIDIOC_ENUMINPUT;
909	case VIDIOC_G_EDID32:
910		return VIDIOC_G_EDID;
911	case VIDIOC_S_EDID32:
912		return VIDIOC_S_EDID;
913#ifdef CONFIG_X86_64
914	case VIDIOC_DQEVENT32:
915		return VIDIOC_DQEVENT;
916#endif
917#ifdef CONFIG_COMPAT_32BIT_TIME
918	case VIDIOC_DQEVENT32_TIME32:
919		return VIDIOC_DQEVENT;
920#endif
921	}
922	return cmd;
923}
924
925int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
926{
927	switch (cmd) {
928	case VIDIOC_G_FMT32:
929	case VIDIOC_S_FMT32:
930	case VIDIOC_TRY_FMT32:
931		return get_v4l2_format32(parg, arg);
932
933	case VIDIOC_S_FBUF32:
934		return get_v4l2_framebuffer32(parg, arg);
935#ifdef CONFIG_COMPAT_32BIT_TIME
936	case VIDIOC_QUERYBUF32_TIME32:
937	case VIDIOC_QBUF32_TIME32:
938	case VIDIOC_DQBUF32_TIME32:
939	case VIDIOC_PREPARE_BUF32_TIME32:
940		return get_v4l2_buffer32_time32(parg, arg);
941#endif
942	case VIDIOC_QUERYBUF32:
943	case VIDIOC_QBUF32:
944	case VIDIOC_DQBUF32:
945	case VIDIOC_PREPARE_BUF32:
946		return get_v4l2_buffer32(parg, arg);
947
948	case VIDIOC_G_EXT_CTRLS32:
949	case VIDIOC_S_EXT_CTRLS32:
950	case VIDIOC_TRY_EXT_CTRLS32:
951		return get_v4l2_ext_controls32(parg, arg);
952
953	case VIDIOC_CREATE_BUFS32:
954		return get_v4l2_create32(parg, arg);
955
956	case VIDIOC_ENUMSTD32:
957		return get_v4l2_standard32(parg, arg);
958
959	case VIDIOC_ENUMINPUT32:
960		return get_v4l2_input32(parg, arg);
961
962	case VIDIOC_G_EDID32:
963	case VIDIOC_S_EDID32:
964		return get_v4l2_edid32(parg, arg);
965	}
966	return 0;
967}
968
969int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
970{
971	switch (cmd) {
972	case VIDIOC_G_FMT32:
973	case VIDIOC_S_FMT32:
974	case VIDIOC_TRY_FMT32:
975		return put_v4l2_format32(parg, arg);
976
977	case VIDIOC_G_FBUF32:
978		return put_v4l2_framebuffer32(parg, arg);
979#ifdef CONFIG_COMPAT_32BIT_TIME
980	case VIDIOC_QUERYBUF32_TIME32:
981	case VIDIOC_QBUF32_TIME32:
982	case VIDIOC_DQBUF32_TIME32:
983	case VIDIOC_PREPARE_BUF32_TIME32:
984		return put_v4l2_buffer32_time32(parg, arg);
985#endif
986	case VIDIOC_QUERYBUF32:
987	case VIDIOC_QBUF32:
988	case VIDIOC_DQBUF32:
989	case VIDIOC_PREPARE_BUF32:
990		return put_v4l2_buffer32(parg, arg);
991
992	case VIDIOC_G_EXT_CTRLS32:
993	case VIDIOC_S_EXT_CTRLS32:
994	case VIDIOC_TRY_EXT_CTRLS32:
995		return put_v4l2_ext_controls32(parg, arg);
996
997	case VIDIOC_CREATE_BUFS32:
998		return put_v4l2_create32(parg, arg);
999
1000	case VIDIOC_ENUMSTD32:
1001		return put_v4l2_standard32(parg, arg);
1002
1003	case VIDIOC_ENUMINPUT32:
1004		return put_v4l2_input32(parg, arg);
1005
1006	case VIDIOC_G_EDID32:
1007	case VIDIOC_S_EDID32:
1008		return put_v4l2_edid32(parg, arg);
1009#ifdef CONFIG_X86_64
1010	case VIDIOC_DQEVENT32:
1011		return put_v4l2_event32(parg, arg);
1012#endif
1013#ifdef CONFIG_COMPAT_32BIT_TIME
1014	case VIDIOC_DQEVENT32_TIME32:
1015		return put_v4l2_event32_time32(parg, arg);
1016#endif
1017	}
1018	return 0;
1019}
1020
1021int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1022			       void __user *user_ptr, size_t array_size,
1023			       unsigned int cmd, void *arg)
1024{
1025	int err = 0;
1026
1027	memset(mbuf, 0, array_size);
1028
1029	switch (cmd) {
1030#ifdef CONFIG_COMPAT_32BIT_TIME
1031	case VIDIOC_QUERYBUF32_TIME32:
1032	case VIDIOC_QBUF32_TIME32:
1033	case VIDIOC_DQBUF32_TIME32:
1034	case VIDIOC_PREPARE_BUF32_TIME32:
1035#endif
1036	case VIDIOC_QUERYBUF32:
1037	case VIDIOC_QBUF32:
1038	case VIDIOC_DQBUF32:
1039	case VIDIOC_PREPARE_BUF32: {
1040		struct v4l2_buffer *b64 = arg;
1041		struct v4l2_plane *p64 = mbuf;
1042		struct v4l2_plane32 __user *p32 = user_ptr;
1043
1044		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1045			u32 num_planes = b64->length;
1046
1047			if (num_planes == 0)
1048				return 0;
1049
1050			while (num_planes--) {
1051				err = get_v4l2_plane32(p64, p32, b64->memory);
1052				if (err)
1053					return err;
1054				++p64;
1055				++p32;
1056			}
1057		}
1058		break;
1059	}
1060	case VIDIOC_G_EXT_CTRLS32:
1061	case VIDIOC_S_EXT_CTRLS32:
1062	case VIDIOC_TRY_EXT_CTRLS32: {
1063		struct v4l2_ext_controls *ecs64 = arg;
1064		struct v4l2_ext_control *ec64 = mbuf;
1065		struct v4l2_ext_control32 __user *ec32 = user_ptr;
1066		int n;
1067
1068		for (n = 0; n < ecs64->count; n++) {
1069			if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1070				return -EFAULT;
1071
1072			if (ctrl_is_pointer(file, ec64->id)) {
1073				compat_uptr_t p;
1074
1075				if (get_user(p, &ec32->string))
1076					return -EFAULT;
1077				ec64->string = compat_ptr(p);
1078			}
1079			ec32++;
1080			ec64++;
1081		}
1082		break;
1083	}
1084	default:
1085		if (copy_from_user(mbuf, user_ptr, array_size))
1086			err = -EFAULT;
1087		break;
1088	}
1089
1090	return err;
1091}
1092
1093int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1094			       void *mbuf, size_t array_size,
1095			       unsigned int cmd, void *arg)
1096{
1097	int err = 0;
1098
1099	switch (cmd) {
1100#ifdef CONFIG_COMPAT_32BIT_TIME
1101	case VIDIOC_QUERYBUF32_TIME32:
1102	case VIDIOC_QBUF32_TIME32:
1103	case VIDIOC_DQBUF32_TIME32:
1104	case VIDIOC_PREPARE_BUF32_TIME32:
1105#endif
1106	case VIDIOC_QUERYBUF32:
1107	case VIDIOC_QBUF32:
1108	case VIDIOC_DQBUF32:
1109	case VIDIOC_PREPARE_BUF32: {
1110		struct v4l2_buffer *b64 = arg;
1111		struct v4l2_plane *p64 = mbuf;
1112		struct v4l2_plane32 __user *p32 = user_ptr;
1113
1114		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1115			u32 num_planes = b64->length;
1116
1117			if (num_planes == 0)
1118				return 0;
1119
1120			while (num_planes--) {
1121				err = put_v4l2_plane32(p64, p32, b64->memory);
1122				if (err)
1123					return err;
1124				++p64;
1125				++p32;
1126			}
1127		}
1128		break;
1129	}
1130	case VIDIOC_G_EXT_CTRLS32:
1131	case VIDIOC_S_EXT_CTRLS32:
1132	case VIDIOC_TRY_EXT_CTRLS32: {
1133		struct v4l2_ext_controls *ecs64 = arg;
1134		struct v4l2_ext_control *ec64 = mbuf;
1135		struct v4l2_ext_control32 __user *ec32 = user_ptr;
1136		int n;
1137
1138		for (n = 0; n < ecs64->count; n++) {
1139			unsigned int size = sizeof(*ec32);
1140			/*
1141			 * Do not modify the pointer when copying a pointer
1142			 * control.  The contents of the pointer was changed,
1143			 * not the pointer itself.
1144			 * The structures are otherwise compatible.
1145			 */
1146			if (ctrl_is_pointer(file, ec64->id))
1147				size -= sizeof(ec32->value64);
1148
1149			if (copy_to_user(ec32, ec64, size))
1150				return -EFAULT;
1151
1152			ec32++;
1153			ec64++;
1154		}
1155		break;
1156	}
1157	default:
1158		if (copy_to_user(user_ptr, mbuf, array_size))
1159			err = -EFAULT;
1160		break;
1161	}
1162
1163	return err;
1164}
1165
1166/**
1167 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1168 *
1169 * @file: pointer to &struct file with the file handler
1170 * @cmd: ioctl to be called
1171 * @arg: arguments passed from/to the ioctl handler
1172 *
1173 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1174 * in order to deal with 32-bit calls on a 64-bits Kernel.
1175 *
1176 * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1177 * If the function is a private one it calls vdev->fops->compat_ioctl32
1178 * instead.
1179 */
1180long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1181{
1182	struct video_device *vdev = video_devdata(file);
1183	long ret = -ENOIOCTLCMD;
1184
1185	if (!file->f_op->unlocked_ioctl)
1186		return ret;
1187
1188	if (!video_is_registered(vdev))
1189		return -ENODEV;
1190
1191	if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1192		ret = file->f_op->unlocked_ioctl(file, cmd,
1193					(unsigned long)compat_ptr(arg));
1194	else if (vdev->fops->compat_ioctl32)
1195		ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1196
1197	if (ret == -ENOIOCTLCMD)
1198		pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1199			 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1200	return ret;
1201}
1202EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
1203