Blame view

drivers/media/v4l2-core/v4l2-compat-ioctl32.c 28 KB
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
1
2
3
4
5
6
7
  /*
   * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
   *	Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
   *
   * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
   * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
   * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
a2531293d   Pavel Machek   update email address
8
   * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
9
   * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
10
   * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
11
12
13
14
   *
   * These routines maintain argument size conversion between 32bit and 64bit
   * ioctls.
   */
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
15
  #include <linux/compat.h>
133b73541   Nickolay V. Shmyrev   V4L (0972): More ...
16
  #include <linux/module.h>
b9d0aa6e2   Laurent Pinchart   [media] v4l: Add ...
17
  #include <linux/videodev2.h>
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
18
  #include <linux/v4l2-subdev.h>
b9d0aa6e2   Laurent Pinchart   [media] v4l: Add ...
19
  #include <media/v4l2-dev.h>
2864462ea   Mauro Carvalho Chehab   V4L/DVB (8434): F...
20
  #include <media/v4l2-ioctl.h>
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
21

069b74793   Hans Verkuil   V4L/DVB (10138): ...
22
  static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
23
  {
069b74793   Hans Verkuil   V4L/DVB (10138): ...
24
  	long ret = -ENOIOCTLCMD;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
25
26
27
  
  	if (file->f_op->unlocked_ioctl)
  		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
28
29
30
  
  	return ret;
  }
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
31
  struct v4l2_clip32 {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
32
33
34
  	struct v4l2_rect        c;
  	compat_caddr_t 		next;
  };
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
35
  struct v4l2_window32 {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
36
  	struct v4l2_rect        w;
6016af82e   Sakari Ailus   [media] v4l2: use...
37
  	__u32		  	field;	/* enum v4l2_field */
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
38
39
40
41
42
43
44
45
  	__u32			chromakey;
  	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
  	__u32			clipcount;
  	compat_caddr_t		bitmap;
  };
  
  static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
  {
a113bc787   Guy Martin   V4L/DVB (3352): S...
46
47
48
49
50
51
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
  		copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
  		get_user(kp->field, &up->field) ||
  		get_user(kp->chromakey, &up->chromakey) ||
  		get_user(kp->clipcount, &up->clipcount))
  			return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
52
53
54
  	if (kp->clipcount > 2048)
  		return -EINVAL;
  	if (kp->clipcount) {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
55
56
  		struct v4l2_clip32 __user *uclips;
  		struct v4l2_clip __user *kclips;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
57
  		int n = kp->clipcount;
5b1a43d7d   Al Viro   [PATCH] drivers/m...
58
  		compat_caddr_t p;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
59

5b1a43d7d   Al Viro   [PATCH] drivers/m...
60
61
62
  		if (get_user(p, &up->clips))
  			return -EFAULT;
  		uclips = compat_ptr(p);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
63
64
65
  		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
  		kp->clips = kclips;
  		while (--n >= 0) {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
66
67
68
  			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
  				return -EFAULT;
  			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
a113bc787   Guy Martin   V4L/DVB (3352): S...
69
  				return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
70
71
72
73
  			uclips += 1;
  			kclips += 1;
  		}
  	} else
5b1a43d7d   Al Viro   [PATCH] drivers/m...
74
  		kp->clips = NULL;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
75
76
77
78
79
  	return 0;
  }
  
  static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
  {
f2e6c6ad0   Roel Kluin   V4L/DVB: use corr...
80
  	if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
a113bc787   Guy Martin   V4L/DVB (3352): S...
81
82
83
84
  		put_user(kp->field, &up->field) ||
  		put_user(kp->chromakey, &up->chromakey) ||
  		put_user(kp->clipcount, &up->clipcount))
  			return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
85
86
87
88
89
  	return 0;
  }
  
  static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
  {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
90
91
  	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
92
  	return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
93
  }
52a3082fe   Pawel Osciak   [media] v4l: Add ...
94
95
96
97
98
99
100
  static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
  				struct v4l2_pix_format_mplane __user *up)
  {
  	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
  		return -EFAULT;
  	return 0;
  }
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
101
102
  static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
  {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
103
104
  	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
105
  	return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
106
  }
52a3082fe   Pawel Osciak   [media] v4l: Add ...
107
108
109
110
111
112
113
  static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
  				struct v4l2_pix_format_mplane __user *up)
  {
  	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
  		return -EFAULT;
  	return 0;
  }
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
114
115
  static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
  {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
116
117
  	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
118
  	return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
119
120
121
122
  }
  
  static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
  {
5b1a43d7d   Al Viro   [PATCH] drivers/m...
123
124
  	if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
125
  	return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
126
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
127
128
129
130
131
132
133
134
135
136
137
138
139
  static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
  {
  	if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
  		return -EFAULT;
  	return 0;
  }
  
  static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
  {
  	if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
  		return -EFAULT;
  	return 0;
  }
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
140
  struct v4l2_format32 {
6016af82e   Sakari Ailus   [media] v4l2: use...
141
  	__u32	type;	/* enum v4l2_buf_type */
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
142
  	union {
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
143
  		struct v4l2_pix_format	pix;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
144
  		struct v4l2_pix_format_mplane	pix_mp;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
145
146
147
  		struct v4l2_window32	win;
  		struct v4l2_vbi_format	vbi;
  		struct v4l2_sliced_vbi_format	sliced;
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
148
  		__u8	raw_data[200];        /* user-defined */
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
149
150
  	} fmt;
  };
09362ec25   Guennadi Liakhovetski   [media] V4L: docb...
151
152
153
154
155
156
157
158
159
  /**
   * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
   * @index:	on return, index of the first created buffer
   * @count:	entry: number of requested buffers,
   *		return: number of created buffers
   * @memory:	buffer memory type
   * @format:	frame format, for which buffers are requested
   * @reserved:	future extensions
   */
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
160
  struct v4l2_create_buffers32 {
09362ec25   Guennadi Liakhovetski   [media] V4L: docb...
161
  	__u32			index;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
162
  	__u32			count;
6016af82e   Sakari Ailus   [media] v4l2: use...
163
  	__u32			memory;	/* enum v4l2_memory */
09362ec25   Guennadi Liakhovetski   [media] V4L: docb...
164
  	struct v4l2_format32	format;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
165
166
167
168
  	__u32			reserved[8];
  };
  
  static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
169
  {
97d9d23dd   Guennadi Liakhovetski   [media] V4L2: fix...
170
171
  	if (get_user(kp->type, &up->type))
  		return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
172
173
  	switch (kp->type) {
  	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
174
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
175
  		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
52a3082fe   Pawel Osciak   [media] v4l: Add ...
176
177
178
179
  	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
  		return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
  						  &up->fmt.pix_mp);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
180
  	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
181
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
182
183
  		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
  	case V4L2_BUF_TYPE_VBI_CAPTURE:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
184
  	case V4L2_BUF_TYPE_VBI_OUTPUT:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
185
  		return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
186
187
188
  	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  		return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
189
  	default:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
190
191
  		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d
  ",
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
192
  								kp->type);
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
193
  		return -EINVAL;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
194
195
  	}
  }
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
196
197
  static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  {
97d9d23dd   Guennadi Liakhovetski   [media] V4L2: fix...
198
199
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
  		return -EFAULT;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
200
201
202
203
204
205
  	return __get_v4l2_format32(kp, up);
  }
  
  static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
  {
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
97d9d23dd   Guennadi Liakhovetski   [media] V4L2: fix...
206
207
  	    copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
  		return -EFAULT;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
208
209
210
211
  	return __get_v4l2_format32(&kp->format, &up->format);
  }
  
  static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
212
  {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
213
214
  	switch (kp->type) {
  	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
215
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
216
  		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
52a3082fe   Pawel Osciak   [media] v4l: Add ...
217
218
219
220
  	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
  		return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
  						  &up->fmt.pix_mp);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
221
  	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
222
  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
223
224
  		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
  	case V4L2_BUF_TYPE_VBI_CAPTURE:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
225
  	case V4L2_BUF_TYPE_VBI_OUTPUT:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
226
  		return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
227
228
229
  	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  		return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
230
  	default:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
231
232
233
234
  		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d
  ",
  								kp->type);
  		return -EINVAL;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
235
236
  	}
  }
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  {
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
  		put_user(kp->type, &up->type))
  		return -EFAULT;
  	return __put_v4l2_format32(kp, up);
  }
  
  static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
  {
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
  	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
  			return -EFAULT;
  	return __put_v4l2_format32(&kp->format, &up->format);
  }
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
252
  struct v4l2_standard32 {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
253
254
255
256
257
258
259
260
261
262
263
  	__u32		     index;
  	__u32		     id[2]; /* __u64 would get the alignment wrong */
  	__u8		     name[24];
  	struct v4l2_fract    frameperiod; /* Frames, not fields */
  	__u32		     framelines;
  	__u32		     reserved[4];
  };
  
  static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
  {
  	/* other fields are not set by the user, nor used by the driver */
a113bc787   Guy Martin   V4L/DVB (3352): S...
264
265
266
267
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
  		get_user(kp->index, &up->index))
  		return -EFAULT;
  	return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
268
269
270
271
  }
  
  static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
  {
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
272
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
a113bc787   Guy Martin   V4L/DVB (3352): S...
273
274
275
276
277
278
279
280
281
  		put_user(kp->index, &up->index) ||
  		copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
  		copy_to_user(up->name, kp->name, 24) ||
  		copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
  		put_user(kp->framelines, &up->framelines) ||
  		copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
  			return -EFAULT;
  	return 0;
  }
52a3082fe   Pawel Osciak   [media] v4l: Add ...
282
283
284
285
286
287
  struct v4l2_plane32 {
  	__u32			bytesused;
  	__u32			length;
  	union {
  		__u32		mem_offset;
  		compat_long_t	userptr;
051c7788b   Sumit Semwal   [media] v4l: Add ...
288
  		__s32		fd;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
289
290
291
292
  	} m;
  	__u32			data_offset;
  	__u32			reserved[11];
  };
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
293
  struct v4l2_buffer32 {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
294
  	__u32			index;
6016af82e   Sakari Ailus   [media] v4l2: use...
295
  	__u32			type;	/* enum v4l2_buf_type */
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
296
297
  	__u32			bytesused;
  	__u32			flags;
6016af82e   Sakari Ailus   [media] v4l2: use...
298
  	__u32			field;	/* enum v4l2_field */
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
299
300
301
302
303
  	struct compat_timeval	timestamp;
  	struct v4l2_timecode	timecode;
  	__u32			sequence;
  
  	/* memory location */
6016af82e   Sakari Ailus   [media] v4l2: use...
304
  	__u32			memory;	/* enum v4l2_memory */
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
305
306
307
  	union {
  		__u32           offset;
  		compat_long_t   userptr;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
308
  		compat_caddr_t  planes;
051c7788b   Sumit Semwal   [media] v4l: Add ...
309
  		__s32		fd;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
310
311
  	} m;
  	__u32			length;
2b719d7ba   Sakari Ailus   [media] v4l: drop...
312
  	__u32			reserved2;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
313
314
  	__u32			reserved;
  };
52a3082fe   Pawel Osciak   [media] v4l: Add ...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
  				enum v4l2_memory memory)
  {
  	void __user *up_pln;
  	compat_long_t p;
  
  	if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
  		copy_in_user(&up->data_offset, &up32->data_offset,
  				sizeof(__u32)))
  		return -EFAULT;
  
  	if (memory == V4L2_MEMORY_USERPTR) {
  		if (get_user(p, &up32->m.userptr))
  			return -EFAULT;
  		up_pln = compat_ptr(p);
  		if (put_user((unsigned long)up_pln, &up->m.userptr))
  			return -EFAULT;
051c7788b   Sumit Semwal   [media] v4l: Add ...
332
333
334
  	} else if (memory == V4L2_MEMORY_DMABUF) {
  		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  	} else {
  		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
  					sizeof(__u32)))
  			return -EFAULT;
  	}
  
  	return 0;
  }
  
  static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
  				enum v4l2_memory memory)
  {
  	if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
  		copy_in_user(&up32->data_offset, &up->data_offset,
  				sizeof(__u32)))
  		return -EFAULT;
  
  	/* For MMAP, driver might've set up the offset, so copy it back.
  	 * USERPTR stays the same (was userspace-provided), so no copying. */
  	if (memory == V4L2_MEMORY_MMAP)
  		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
  					sizeof(__u32)))
  			return -EFAULT;
051c7788b   Sumit Semwal   [media] v4l: Add ...
358
359
360
361
362
  	/* For DMABUF, driver might've set up the fd, so copy it back. */
  	if (memory == V4L2_MEMORY_DMABUF)
  		if (copy_in_user(&up32->m.fd, &up->m.fd,
  					sizeof(int)))
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
363
364
365
  
  	return 0;
  }
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
366
367
  static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
  {
52a3082fe   Pawel Osciak   [media] v4l: Add ...
368
369
370
371
372
  	struct v4l2_plane32 __user *uplane32;
  	struct v4l2_plane __user *uplane;
  	compat_caddr_t p;
  	int num_planes;
  	int ret;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
373

a113bc787   Guy Martin   V4L/DVB (3352): S...
374
375
376
377
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
  		get_user(kp->index, &up->index) ||
  		get_user(kp->type, &up->type) ||
  		get_user(kp->flags, &up->flags) ||
cc831f843   Mauro Carvalho Chehab   [media] v4l2-comp...
378
  		get_user(kp->memory, &up->memory))
a113bc787   Guy Martin   V4L/DVB (3352): S...
379
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
380
381
382
383
384
385
386
  
  	if (V4L2_TYPE_IS_OUTPUT(kp->type))
  		if (get_user(kp->bytesused, &up->bytesused) ||
  			get_user(kp->field, &up->field) ||
  			get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
  			get_user(kp->timestamp.tv_usec,
  					&up->timestamp.tv_usec))
22c859faf   Arnaud Patard   V4L/DVB: Fix VIDI...
387
  			return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
388

52a3082fe   Pawel Osciak   [media] v4l: Add ...
389
390
  	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
  		if (get_user(kp->length, &up->length))
5b1a43d7d   Al Viro   [PATCH] drivers/m...
391
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
392
393
394
395
396
397
  		num_planes = kp->length;
  		if (num_planes == 0) {
  			kp->m.planes = NULL;
  			/* num_planes == 0 is legal, e.g. when userspace doesn't
  			 * need planes array on DQBUF*/
  			return 0;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
398
  		}
52a3082fe   Pawel Osciak   [media] v4l: Add ...
399
400
  
  		if (get_user(p, &up->m.planes))
a113bc787   Guy Martin   V4L/DVB (3352): S...
401
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  
  		uplane32 = compat_ptr(p);
  		if (!access_ok(VERIFY_READ, uplane32,
  				num_planes * sizeof(struct v4l2_plane32)))
  			return -EFAULT;
  
  		/* We don't really care if userspace decides to kill itself
  		 * by passing a very big num_planes value */
  		uplane = compat_alloc_user_space(num_planes *
  						sizeof(struct v4l2_plane));
  		kp->m.planes = uplane;
  
  		while (--num_planes >= 0) {
  			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
  			if (ret)
  				return ret;
  			++uplane;
  			++uplane32;
  		}
  	} else {
  		switch (kp->memory) {
  		case V4L2_MEMORY_MMAP:
  			if (get_user(kp->length, &up->length) ||
  				get_user(kp->m.offset, &up->m.offset))
  				return -EFAULT;
  			break;
  		case V4L2_MEMORY_USERPTR:
  			{
  			compat_long_t tmp;
  
  			if (get_user(kp->length, &up->length) ||
  			    get_user(tmp, &up->m.userptr))
  				return -EFAULT;
  
  			kp->m.userptr = (unsigned long)compat_ptr(tmp);
  			}
  			break;
  		case V4L2_MEMORY_OVERLAY:
  			if (get_user(kp->m.offset, &up->m.offset))
  				return -EFAULT;
  			break;
051c7788b   Sumit Semwal   [media] v4l: Add ...
443
444
445
446
  		case V4L2_MEMORY_DMABUF:
  			if (get_user(kp->m.fd, &up->m.fd))
  				return -EFAULT;
  			break;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
447
  		}
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
448
  	}
52a3082fe   Pawel Osciak   [media] v4l: Add ...
449

cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
450
451
452
453
454
  	return 0;
  }
  
  static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
  {
52a3082fe   Pawel Osciak   [media] v4l: Add ...
455
456
457
458
459
  	struct v4l2_plane32 __user *uplane32;
  	struct v4l2_plane __user *uplane;
  	compat_caddr_t p;
  	int num_planes;
  	int ret;
a113bc787   Guy Martin   V4L/DVB (3352): S...
460
461
462
463
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
  		put_user(kp->index, &up->index) ||
  		put_user(kp->type, &up->type) ||
  		put_user(kp->flags, &up->flags) ||
cc831f843   Mauro Carvalho Chehab   [media] v4l2-comp...
464
  		put_user(kp->memory, &up->memory))
a113bc787   Guy Martin   V4L/DVB (3352): S...
465
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
466

a113bc787   Guy Martin   V4L/DVB (3352): S...
467
468
469
470
471
472
  	if (put_user(kp->bytesused, &up->bytesused) ||
  		put_user(kp->field, &up->field) ||
  		put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
  		put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
  		copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
  		put_user(kp->sequence, &up->sequence) ||
2b719d7ba   Sakari Ailus   [media] v4l: drop...
473
  		put_user(kp->reserved2, &up->reserved2) ||
cc831f843   Mauro Carvalho Chehab   [media] v4l2-comp...
474
  		put_user(kp->reserved, &up->reserved))
a113bc787   Guy Martin   V4L/DVB (3352): S...
475
  			return -EFAULT;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  
  	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
  		num_planes = kp->length;
  		if (num_planes == 0)
  			return 0;
  
  		uplane = kp->m.planes;
  		if (get_user(p, &up->m.planes))
  			return -EFAULT;
  		uplane32 = compat_ptr(p);
  
  		while (--num_planes >= 0) {
  			ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
  			if (ret)
  				return ret;
  			++uplane;
  			++uplane32;
  		}
  	} else {
  		switch (kp->memory) {
  		case V4L2_MEMORY_MMAP:
  			if (put_user(kp->length, &up->length) ||
  				put_user(kp->m.offset, &up->m.offset))
  				return -EFAULT;
  			break;
  		case V4L2_MEMORY_USERPTR:
  			if (put_user(kp->length, &up->length) ||
  				put_user(kp->m.userptr, &up->m.userptr))
  				return -EFAULT;
  			break;
  		case V4L2_MEMORY_OVERLAY:
  			if (put_user(kp->m.offset, &up->m.offset))
  				return -EFAULT;
  			break;
051c7788b   Sumit Semwal   [media] v4l: Add ...
510
511
512
513
  		case V4L2_MEMORY_DMABUF:
  			if (put_user(kp->m.fd, &up->m.fd))
  				return -EFAULT;
  			break;
52a3082fe   Pawel Osciak   [media] v4l: Add ...
514
515
  		}
  	}
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
516
517
  	return 0;
  }
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
518
  struct v4l2_framebuffer32 {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
519
520
521
522
523
  	__u32			capability;
  	__u32			flags;
  	compat_caddr_t 		base;
  	struct v4l2_pix_format	fmt;
  };
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
524
525
526
  static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
  {
  	u32 tmp;
a113bc787   Guy Martin   V4L/DVB (3352): S...
527
528
529
530
531
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
  		get_user(tmp, &up->base) ||
  		get_user(kp->capability, &up->capability) ||
  		get_user(kp->flags, &up->flags))
  			return -EFAULT;
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
532
  	kp->base = compat_ptr(tmp);
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
533
534
535
  	get_v4l2_pix_format(&kp->fmt, &up->fmt);
  	return 0;
  }
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
536
537
538
  static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
  {
  	u32 tmp = (u32)((unsigned long)kp->base);
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
539
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
a113bc787   Guy Martin   V4L/DVB (3352): S...
540
541
542
543
  		put_user(tmp, &up->base) ||
  		put_user(kp->capability, &up->capability) ||
  		put_user(kp->flags, &up->flags))
  			return -EFAULT;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
544
545
546
  	put_v4l2_pix_format(&kp->fmt, &up->fmt);
  	return 0;
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  struct v4l2_input32 {
  	__u32	     index;		/*  Which input */
  	__u8	     name[32];		/*  Label */
  	__u32	     type;		/*  Type of input */
  	__u32	     audioset;		/*  Associated audios (bitfield) */
  	__u32        tuner;             /*  Associated tuner */
  	v4l2_std_id  std;
  	__u32	     status;
  	__u32	     reserved[4];
  } __attribute__ ((packed));
  
  /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
     Otherwise it is identical to the 32-bit version. */
  static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
a113bc787   Guy Martin   V4L/DVB (3352): S...
561
  {
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
562
  	if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
5b1a43d7d   Al Viro   [PATCH] drivers/m...
563
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
564
565
  	return 0;
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
566
  static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
a113bc787   Guy Martin   V4L/DVB (3352): S...
567
  {
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
568
  	if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
5b1a43d7d   Al Viro   [PATCH] drivers/m...
569
  		return -EFAULT;
a113bc787   Guy Martin   V4L/DVB (3352): S...
570
571
  	return 0;
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
572
573
574
575
576
577
  struct v4l2_ext_controls32 {
         __u32 ctrl_class;
         __u32 count;
         __u32 error_idx;
         __u32 reserved[2];
         compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
eb4eeccc1   Mauro Carvalho Chehab   V4L/DVB (4341): V...
578
  };
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  struct v4l2_ext_control32 {
  	__u32 id;
  	__u32 size;
  	__u32 reserved2[1];
  	union {
  		__s32 value;
  		__s64 value64;
  		compat_caddr_t string; /* actually char * */
  	};
  } __attribute__ ((packed));
  
  /* The following function really belong in v4l2-common, but that causes
     a circular dependency between modules. We need to think about this, but
     for now this will do. */
  
  /* Return non-zero if this control is a pointer type. Currently only
fdf82dc2e   Eduardo Valentin   V4L/DVB (12549): ...
595
     type STRING is a pointer type. */
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
596
597
  static inline int ctrl_is_pointer(u32 id)
  {
fdf82dc2e   Eduardo Valentin   V4L/DVB (12549): ...
598
599
600
601
602
603
604
  	switch (id) {
  	case V4L2_CID_RDS_TX_PS_NAME:
  	case V4L2_CID_RDS_TX_RADIO_TEXT:
  		return 1;
  	default:
  		return 0;
  	}
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
605
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
606
  static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
eb4eeccc1   Mauro Carvalho Chehab   V4L/DVB (4341): V...
607
  {
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
608
  	struct v4l2_ext_control32 __user *ucontrols;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  	struct v4l2_ext_control __user *kcontrols;
  	int n;
  	compat_caddr_t p;
  
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
  		get_user(kp->ctrl_class, &up->ctrl_class) ||
  		get_user(kp->count, &up->count) ||
  		get_user(kp->error_idx, &up->error_idx) ||
  		copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
  			return -EFAULT;
  	n = kp->count;
  	if (n == 0) {
  		kp->controls = NULL;
  		return 0;
  	}
  	if (get_user(p, &up->controls))
  		return -EFAULT;
  	ucontrols = compat_ptr(p);
52a3082fe   Pawel Osciak   [media] v4l: Add ...
627
628
  	if (!access_ok(VERIFY_READ, ucontrols,
  			n * sizeof(struct v4l2_ext_control32)))
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
629
630
631
632
  		return -EFAULT;
  	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
  	kp->controls = kcontrols;
  	while (--n >= 0) {
52a3082fe   Pawel Osciak   [media] v4l: Add ...
633
  		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
634
  			return -EFAULT;
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
635
636
637
638
639
640
641
642
643
  		if (ctrl_is_pointer(kcontrols->id)) {
  			void __user *s;
  
  			if (get_user(p, &ucontrols->string))
  				return -EFAULT;
  			s = compat_ptr(p);
  			if (put_user(s, &kcontrols->string))
  				return -EFAULT;
  		}
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
644
645
646
  		ucontrols++;
  		kcontrols++;
  	}
eb4eeccc1   Mauro Carvalho Chehab   V4L/DVB (4341): V...
647
648
  	return 0;
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
649
  static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
650
  {
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
651
  	struct v4l2_ext_control32 __user *ucontrols;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
652
653
654
655
656
657
658
659
660
661
662
663
  	struct v4l2_ext_control __user *kcontrols = kp->controls;
  	int n = kp->count;
  	compat_caddr_t p;
  
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
  		put_user(kp->ctrl_class, &up->ctrl_class) ||
  		put_user(kp->count, &up->count) ||
  		put_user(kp->error_idx, &up->error_idx) ||
  		copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
  			return -EFAULT;
  	if (!kp->count)
  		return 0;
a113bc787   Guy Martin   V4L/DVB (3352): S...
664

92f45badb   Hans Verkuil   V4L/DVB (9932): v...
665
  	if (get_user(p, &up->controls))
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
666
  		return -EFAULT;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
667
  	ucontrols = compat_ptr(p);
52a3082fe   Pawel Osciak   [media] v4l: Add ...
668
669
  	if (!access_ok(VERIFY_WRITE, ucontrols,
  			n * sizeof(struct v4l2_ext_control32)))
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
670
  		return -EFAULT;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
671
  	while (--n >= 0) {
6b5a9492c   Hans Verkuil   V4L/DVB (12543): ...
672
673
674
675
676
677
678
679
  		unsigned size = sizeof(*ucontrols);
  
  		/* Do not modify the pointer when copying a pointer control.
  		   The contents of the pointer was changed, not the pointer
  		   itself. */
  		if (ctrl_is_pointer(kcontrols->id))
  			size -= sizeof(ucontrols->value64);
  		if (copy_in_user(ucontrols, kcontrols, size))
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
680
681
682
  			return -EFAULT;
  		ucontrols++;
  		kcontrols++;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
683
  	}
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
684
  	return 0;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
685
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
686

2330fb824   Hans Verkuil   [media] v4l2-comp...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  struct v4l2_event32 {
  	__u32				type;
  	union {
  		__u8			data[64];
  	} u;
  	__u32				pending;
  	__u32				sequence;
  	struct compat_timespec		timestamp;
  	__u32				id;
  	__u32				reserved[8];
  };
  
  static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
  {
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
  		put_user(kp->type, &up->type) ||
  		copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
  		put_user(kp->pending, &up->pending) ||
  		put_user(kp->sequence, &up->sequence) ||
81993e81a   H. Peter Anvin   compat: Get rid o...
706
  		compat_put_timespec(&kp->timestamp, &up->timestamp) ||
2330fb824   Hans Verkuil   [media] v4l2-comp...
707
708
709
710
711
  		put_user(kp->id, &up->id) ||
  		copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
  			return -EFAULT;
  	return 0;
  }
dd519bb34   Hans Verkuil   [media] v4l2: add...
712
  struct v4l2_edid32 {
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
713
714
715
716
717
718
  	__u32 pad;
  	__u32 start_block;
  	__u32 blocks;
  	__u32 reserved[5];
  	compat_caddr_t edid;
  };
dd519bb34   Hans Verkuil   [media] v4l2: add...
719
  static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
720
721
  {
  	u32 tmp;
dd519bb34   Hans Verkuil   [media] v4l2: add...
722
  	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
723
724
725
726
727
728
729
730
731
  		get_user(kp->pad, &up->pad) ||
  		get_user(kp->start_block, &up->start_block) ||
  		get_user(kp->blocks, &up->blocks) ||
  		get_user(tmp, &up->edid) ||
  		copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
  			return -EFAULT;
  	kp->edid = compat_ptr(tmp);
  	return 0;
  }
dd519bb34   Hans Verkuil   [media] v4l2: add...
732
  static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
733
734
  {
  	u32 tmp = (u32)((unsigned long)kp->edid);
dd519bb34   Hans Verkuil   [media] v4l2: add...
735
  	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
736
737
738
739
740
741
742
743
  		put_user(kp->pad, &up->pad) ||
  		put_user(kp->start_block, &up->start_block) ||
  		put_user(kp->blocks, &up->blocks) ||
  		put_user(tmp, &up->edid) ||
  		copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
  			return -EFAULT;
  	return 0;
  }
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
744
745
746
747
748
749
750
751
752
  #define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)
  #define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)
  #define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)
  #define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)
  #define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)
  #define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)
  #define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
  #define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
  #define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
dd519bb34   Hans Verkuil   [media] v4l2: add...
753
754
  #define VIDIOC_G_EDID32		_IOWR('V', 40, struct v4l2_edid32)
  #define VIDIOC_S_EDID32		_IOWR('V', 41, struct v4l2_edid32)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
755
756
757
758
  #define VIDIOC_TRY_FMT32      	_IOWR('V', 64, struct v4l2_format32)
  #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
  #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
  #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
2330fb824   Hans Verkuil   [media] v4l2-comp...
759
  #define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
760
761
  #define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)
  #define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
762
763
  
  #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
764
765
766
767
768
769
  #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
  #define VIDIOC_STREAMOFF32	_IOW ('V', 19, s32)
  #define VIDIOC_G_INPUT32	_IOR ('V', 38, s32)
  #define VIDIOC_S_INPUT32	_IOWR('V', 39, s32)
  #define VIDIOC_G_OUTPUT32	_IOR ('V', 46, s32)
  #define VIDIOC_S_OUTPUT32	_IOWR('V', 47, s32)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
770

069b74793   Hans Verkuil   V4L/DVB (10138): ...
771
  static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
772
773
  {
  	union {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
774
775
776
  		struct v4l2_format v2f;
  		struct v4l2_buffer v2b;
  		struct v4l2_framebuffer v2fb;
a113bc787   Guy Martin   V4L/DVB (3352): S...
777
  		struct v4l2_input v2i;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
778
779
  		struct v4l2_standard v2s;
  		struct v4l2_ext_controls v2ecs;
2330fb824   Hans Verkuil   [media] v4l2-comp...
780
  		struct v4l2_event v2ev;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
781
  		struct v4l2_create_buffers v2crt;
dd519bb34   Hans Verkuil   [media] v4l2: add...
782
  		struct v4l2_edid v2edid;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
783
  		unsigned long vx;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
784
  		int vi;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
785
  	} karg;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
786
  	void __user *up = compat_ptr(arg);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
787
  	int compatible_arg = 1;
069b74793   Hans Verkuil   V4L/DVB (10138): ...
788
  	long err = 0;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
789
790
  
  	/* First, convert the command. */
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
791
  	switch (cmd) {
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
792
793
794
795
796
797
798
799
800
801
802
803
804
  	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
  	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
  	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
  	case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
  	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
  	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
  	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
  	case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
  	case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
  	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
  	case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
  	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
  	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
2330fb824   Hans Verkuil   [media] v4l2-comp...
805
  	case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
806
  	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
807
808
809
810
811
812
  	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
  	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
  	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
  	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
  	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
  	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
813
814
  	case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
  	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
dd519bb34   Hans Verkuil   [media] v4l2: add...
815
816
  	case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
  	case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
817
  	}
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
818

d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
819
  	switch (cmd) {
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
820
  	case VIDIOC_OVERLAY:
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
821
822
  	case VIDIOC_STREAMON:
  	case VIDIOC_STREAMOFF:
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
823
824
825
826
  	case VIDIOC_S_INPUT:
  	case VIDIOC_S_OUTPUT:
  		err = get_user(karg.vi, (s32 __user *)up);
  		compatible_arg = 0;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
827
  		break;
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
828

92f45badb   Hans Verkuil   V4L/DVB (9932): v...
829
830
  	case VIDIOC_G_INPUT:
  	case VIDIOC_G_OUTPUT:
13d133bc6   Philippe De Muyter   V4L/DVB (3152): F...
831
832
  		compatible_arg = 0;
  		break;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
833

dd519bb34   Hans Verkuil   [media] v4l2: add...
834
835
836
  	case VIDIOC_G_EDID:
  	case VIDIOC_S_EDID:
  		err = get_v4l2_edid32(&karg.v2edid, up);
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
837
838
  		compatible_arg = 0;
  		break;
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
839
840
841
842
843
844
  	case VIDIOC_G_FMT:
  	case VIDIOC_S_FMT:
  	case VIDIOC_TRY_FMT:
  		err = get_v4l2_format32(&karg.v2f, up);
  		compatible_arg = 0;
  		break;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
845
846
847
848
849
850
  	case VIDIOC_CREATE_BUFS:
  		err = get_v4l2_create32(&karg.v2crt, up);
  		compatible_arg = 0;
  		break;
  
  	case VIDIOC_PREPARE_BUF:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
851
852
853
854
855
856
  	case VIDIOC_QUERYBUF:
  	case VIDIOC_QBUF:
  	case VIDIOC_DQBUF:
  		err = get_v4l2_buffer32(&karg.v2b, up);
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
857
858
  	case VIDIOC_S_FBUF:
  		err = get_v4l2_framebuffer32(&karg.v2fb, up);
a113bc787   Guy Martin   V4L/DVB (3352): S...
859
860
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
861
  	case VIDIOC_G_FBUF:
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
862
863
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
864
865
  	case VIDIOC_ENUMSTD:
  		err = get_v4l2_standard32(&karg.v2s, up);
a113bc787   Guy Martin   V4L/DVB (3352): S...
866
867
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
868
  	case VIDIOC_ENUMINPUT:
a113bc787   Guy Martin   V4L/DVB (3352): S...
869
870
871
  		err = get_v4l2_input32(&karg.v2i, up);
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
872
873
874
875
  	case VIDIOC_G_EXT_CTRLS:
  	case VIDIOC_S_EXT_CTRLS:
  	case VIDIOC_TRY_EXT_CTRLS:
  		err = get_v4l2_ext_controls32(&karg.v2ecs, up);
a113bc787   Guy Martin   V4L/DVB (3352): S...
876
877
  		compatible_arg = 0;
  		break;
2330fb824   Hans Verkuil   [media] v4l2-comp...
878
879
880
  	case VIDIOC_DQEVENT:
  		compatible_arg = 0;
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
881
  	}
d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
882
  	if (err)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
883
  		return err;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
884

d1f81da23   Hans Verkuil   V4L/DVB (9484): v...
885
  	if (compatible_arg)
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
886
  		err = native_ioctl(file, cmd, (unsigned long)up);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
887
888
  	else {
  		mm_segment_t old_fs = get_fs();
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
889

cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
890
  		set_fs(KERNEL_DS);
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
891
  		err = native_ioctl(file, cmd, (unsigned long)&karg);
cf664a645   Philippe De Muyter   V4L/DVB (3120): A...
892
893
  		set_fs(old_fs);
  	}
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
  
  	/* Special case: even after an error we need to put the
  	   results back for these ioctls since the error_idx will
  	   contain information on which control failed. */
  	switch (cmd) {
  	case VIDIOC_G_EXT_CTRLS:
  	case VIDIOC_S_EXT_CTRLS:
  	case VIDIOC_TRY_EXT_CTRLS:
  		if (put_v4l2_ext_controls32(&karg.v2ecs, up))
  			err = -EFAULT;
  		break;
  	}
  	if (err)
  		return err;
  
  	switch (cmd) {
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
910
911
912
913
914
915
  	case VIDIOC_S_INPUT:
  	case VIDIOC_S_OUTPUT:
  	case VIDIOC_G_INPUT:
  	case VIDIOC_G_OUTPUT:
  		err = put_user(((s32)karg.vi), (s32 __user *)up);
  		break;
a113bc787   Guy Martin   V4L/DVB (3352): S...
916

92f45badb   Hans Verkuil   V4L/DVB (9932): v...
917
918
919
  	case VIDIOC_G_FBUF:
  		err = put_v4l2_framebuffer32(&karg.v2fb, up);
  		break;
2330fb824   Hans Verkuil   [media] v4l2-comp...
920
921
922
  	case VIDIOC_DQEVENT:
  		err = put_v4l2_event32(&karg.v2ev, up);
  		break;
dd519bb34   Hans Verkuil   [media] v4l2: add...
923
924
925
  	case VIDIOC_G_EDID:
  	case VIDIOC_S_EDID:
  		err = put_v4l2_edid32(&karg.v2edid, up);
ed45ce2cc   Hans Verkuil   [media] v4l2-subd...
926
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
927
928
929
930
931
  	case VIDIOC_G_FMT:
  	case VIDIOC_S_FMT:
  	case VIDIOC_TRY_FMT:
  		err = put_v4l2_format32(&karg.v2f, up);
  		break;
2150158b3   Guennadi Liakhovetski   [media] V4L: add ...
932
933
934
  	case VIDIOC_CREATE_BUFS:
  		err = put_v4l2_create32(&karg.v2crt, up);
  		break;
92f45badb   Hans Verkuil   V4L/DVB (9932): v...
935
936
937
938
939
940
941
942
943
944
945
946
947
  	case VIDIOC_QUERYBUF:
  	case VIDIOC_QBUF:
  	case VIDIOC_DQBUF:
  		err = put_v4l2_buffer32(&karg.v2b, up);
  		break;
  
  	case VIDIOC_ENUMSTD:
  		err = put_v4l2_standard32(&karg.v2s, up);
  		break;
  
  	case VIDIOC_ENUMINPUT:
  		err = put_v4l2_input32(&karg.v2i, up);
  		break;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
948
  	}
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
949
950
  	return err;
  }
9bb7cde79   Hans Verkuil   V4L/DVB (10139): ...
951
  long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
952
  {
b9d0aa6e2   Laurent Pinchart   [media] v4l: Add ...
953
  	struct video_device *vdev = video_devdata(file);
069b74793   Hans Verkuil   V4L/DVB (10138): ...
954
  	long ret = -ENOIOCTLCMD;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
955

c6d7ba8b1   Frederic Weisbecker   v4l: Remove refer...
956
  	if (!file->f_op->unlocked_ioctl)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
957
  		return ret;
ab58a3016   Hans Verkuil   [media] v4l2-subd...
958
  	if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
959
  		ret = do_video_ioctl(file, cmd, arg);
ab58a3016   Hans Verkuil   [media] v4l2-subd...
960
961
  	else if (vdev->fops->compat_ioctl32)
  		ret = vdev->fops->compat_ioctl32(file, cmd, arg);
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
962

ab58a3016   Hans Verkuil   [media] v4l2-subd...
963
964
965
966
  	if (ret == -ENOIOCTLCMD)
  		pr_warn("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)
  ",
  			_IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
e8efb71d0   Hans Verkuil   V4L (0978): 64-bi...
967
  	return ret;
0d0fbf815   Arnd Bergmann   V4L (926_2): Move...
968
  }
9bb7cde79   Hans Verkuil   V4L/DVB (10139): ...
969
  EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);