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