aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Martin <gmsoft@tuxicoman.be>2006-01-11 20:40:51 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-11 21:11:55 -0500
commita113bc787e9b0e792f316e803b619d31af1397ad (patch)
tree872361a49a080925729c0d0b6b686d894c69a4f6
parentf8bf134d5f697311c04e867b6733d047a4b55a12 (diff)
V4L/DVB (3352): Some fixes to compat_ioctl32
- Adds suppport or fix support for VIDIOC_ENUMSTD, VIDIOC_ENUMINPUT, VIDIOC_G_TUNER and VIDIOC_S_TUNER. - Fix the warnings at compile time and add checks for the pointer validity using access_ok(). - v4l_print_ioctl() has also be added to identify possible missing ioctls. - Has been tested on sparc64 and amd64. Other arches such as mips and hppa are expected to work as sparc, but not tested yet. Signed-off-by: Guy Martin <gmsoft@tuxicoman.be> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/compat_ioctl32.c371
1 files changed, 259 insertions, 112 deletions
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 6194b0125576..297c32ab51e3 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -18,8 +18,11 @@
18#include <linux/videodev2.h> 18#include <linux/videodev2.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/smp_lock.h> 20#include <linux/smp_lock.h>
21#include <media/v4l2-common.h>
21 22
22#ifdef CONFIG_COMPAT 23#ifdef CONFIG_COMPAT
24
25
23struct video_tuner32 { 26struct video_tuner32 {
24 compat_int_t tuner; 27 compat_int_t tuner;
25 char name[32]; 28 char name[32];
@@ -30,27 +33,29 @@ struct video_tuner32 {
30 33
31static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 34static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
32{ 35{
33 if(get_user(kp->tuner, &up->tuner)) 36 if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
37 get_user(kp->tuner, &up->tuner) ||
38 copy_from_user(kp->name, up->name, 32) ||
39 get_user(kp->rangelow, &up->rangelow) ||
40 get_user(kp->rangehigh, &up->rangehigh) ||
41 get_user(kp->flags, &up->flags) ||
42 get_user(kp->mode, &up->mode) ||
43 get_user(kp->signal, &up->signal))
34 return -EFAULT; 44 return -EFAULT;
35 __copy_from_user(kp->name, up->name, 32);
36 __get_user(kp->rangelow, &up->rangelow);
37 __get_user(kp->rangehigh, &up->rangehigh);
38 __get_user(kp->flags, &up->flags);
39 __get_user(kp->mode, &up->mode);
40 __get_user(kp->signal, &up->signal);
41 return 0; 45 return 0;
42} 46}
43 47
44static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 48static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
45{ 49{
46 if(put_user(kp->tuner, &up->tuner)) 50 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
47 return -EFAULT; 51 put_user(kp->tuner, &up->tuner) ||
48 __copy_to_user(up->name, kp->name, 32); 52 copy_to_user(up->name, kp->name, 32) ||
49 __put_user(kp->rangelow, &up->rangelow); 53 put_user(kp->rangelow, &up->rangelow) ||
50 __put_user(kp->rangehigh, &up->rangehigh); 54 put_user(kp->rangehigh, &up->rangehigh) ||
51 __put_user(kp->flags, &up->flags); 55 put_user(kp->flags, &up->flags) ||
52 __put_user(kp->mode, &up->mode); 56 put_user(kp->mode, &up->mode) ||
53 __put_user(kp->signal, &up->signal); 57 put_user(kp->signal, &up->signal))
58 return -EFAULT;
54 return 0; 59 return 0;
55} 60}
56 61
@@ -63,18 +68,19 @@ static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __u
63{ 68{
64 u32 tmp; 69 u32 tmp;
65 70
66 if (get_user(tmp, &up->base)) 71 if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
67 return -EFAULT; 72 get_user(tmp, &up->base) ||
73 get_user(kp->height, &up->height) ||
74 get_user(kp->width, &up->width) ||
75 get_user(kp->depth, &up->depth) ||
76 get_user(kp->bytesperline, &up->bytesperline))
77 return -EFAULT;
68 78
69 /* This is actually a physical address stored 79 /* This is actually a physical address stored
70 * as a void pointer. 80 * as a void pointer.
71 */ 81 */
72 kp->base = (void *)(unsigned long) tmp; 82 kp->base = (void *)(unsigned long) tmp;
73 83
74 __get_user(kp->height, &up->height);
75 __get_user(kp->width, &up->width);
76 __get_user(kp->depth, &up->depth);
77 __get_user(kp->bytesperline, &up->bytesperline);
78 return 0; 84 return 0;
79} 85}
80 86
@@ -82,12 +88,13 @@ static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __u
82{ 88{
83 u32 tmp = (u32)((unsigned long)kp->base); 89 u32 tmp = (u32)((unsigned long)kp->base);
84 90
85 if(put_user(tmp, &up->base)) 91 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
86 return -EFAULT; 92 put_user(tmp, &up->base) ||
87 __put_user(kp->height, &up->height); 93 put_user(kp->height, &up->height) ||
88 __put_user(kp->width, &up->width); 94 put_user(kp->width, &up->width) ||
89 __put_user(kp->depth, &up->depth); 95 put_user(kp->depth, &up->depth) ||
90 __put_user(kp->bytesperline, &up->bytesperline); 96 put_user(kp->bytesperline, &up->bytesperline))
97 return -EFAULT;
91 return 0; 98 return 0;
92} 99}
93 100
@@ -121,14 +128,15 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
121/* You get back everything except the clips... */ 128/* You get back everything except the clips... */
122static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) 129static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
123{ 130{
124 if(put_user(kp->x, &up->x)) 131 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
125 return -EFAULT; 132 put_user(kp->x, &up->x) ||
126 __put_user(kp->y, &up->y); 133 put_user(kp->y, &up->y) ||
127 __put_user(kp->width, &up->width); 134 put_user(kp->width, &up->width) ||
128 __put_user(kp->height, &up->height); 135 put_user(kp->height, &up->height) ||
129 __put_user(kp->chromakey, &up->chromakey); 136 put_user(kp->chromakey, &up->chromakey) ||
130 __put_user(kp->flags, &up->flags); 137 put_user(kp->flags, &up->flags) ||
131 __put_user(kp->clipcount, &up->clipcount); 138 put_user(kp->clipcount, &up->clipcount))
139 return -EFAULT;
132 return 0; 140 return 0;
133} 141}
134 142
@@ -150,11 +158,12 @@ struct v4l2_window32
150 158
151static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 159static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
152{ 160{
153 if (copy_from_user(&kp->w, &up->w, sizeof(up->w))) 161 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
154 return -EFAULT; 162 copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
155 __get_user(kp->field, &up->field); 163 get_user(kp->field, &up->field) ||
156 __get_user(kp->chromakey, &up->chromakey); 164 get_user(kp->chromakey, &up->chromakey) ||
157 __get_user(kp->clipcount, &up->clipcount); 165 get_user(kp->clipcount, &up->clipcount))
166 return -EFAULT;
158 if (kp->clipcount > 2048) 167 if (kp->clipcount > 2048)
159 return -EINVAL; 168 return -EINVAL;
160 if (kp->clipcount) { 169 if (kp->clipcount) {
@@ -165,7 +174,9 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
165 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 174 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
166 kp->clips = kclips; 175 kp->clips = kclips;
167 while (--n >= 0) { 176 while (--n >= 0) {
168 copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)); 177 if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
178 copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
179 return -EFAULT;
169 kclips->next = n ? kclips + 1 : 0; 180 kclips->next = n ? kclips + 1 : 0;
170 uclips += 1; 181 uclips += 1;
171 kclips += 1; 182 kclips += 1;
@@ -177,32 +188,45 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
177 188
178static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 189static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
179{ 190{
180 if (copy_to_user(&up->w, &kp->w, sizeof(up->w))) 191 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
181 return -EFAULT; 192 copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
182 __put_user(kp->field, &up->field); 193 put_user(kp->field, &up->field) ||
183 __put_user(kp->chromakey, &up->chromakey); 194 put_user(kp->chromakey, &up->chromakey) ||
184 __put_user(kp->clipcount, &up->clipcount); 195 put_user(kp->clipcount, &up->clipcount))
196 return -EFAULT;
185 return 0; 197 return 0;
186} 198}
187 199
188static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 200static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
189{ 201{
190 return copy_from_user(kp, up, sizeof(struct v4l2_pix_format)); 202 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
203 copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
204 return -EFAULT;
205 return 0;
191} 206}
192 207
193static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 208static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
194{ 209{
195 return copy_to_user(up, kp, sizeof(struct v4l2_pix_format)); 210 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
211 copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
212 return -EFAULT;
213 return 0;
196} 214}
197 215
198static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 216static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
199{ 217{
200 return copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)); 218 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
219 copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
220 return -EFAULT;
221 return 0;
201} 222}
202 223
203static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 224static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
204{ 225{
205 return copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)); 226 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
227 copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
228 return -EFAULT;
229 return 0;
206} 230}
207 231
208struct v4l2_format32 232struct v4l2_format32
@@ -219,8 +243,9 @@ struct v4l2_format32
219 243
220static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 244static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
221{ 245{
222 if(get_user(kp->type, &up->type)) 246 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
223 return -EFAULT; 247 get_user(kp->type, &up->type))
248 return -EFAULT;
224 switch (kp->type) { 249 switch (kp->type) {
225 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 250 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
226 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 251 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
@@ -237,7 +262,8 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
237 262
238static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 263static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
239{ 264{
240 if(put_user(kp->type, &up->type)) 265 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
266 put_user(kp->type, &up->type))
241 return -EFAULT; 267 return -EFAULT;
242 switch (kp->type) { 268 switch (kp->type) {
243 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 269 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -251,6 +277,23 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
251 } 277 }
252} 278}
253 279
280static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
281{
282 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
283 copy_from_user(kp, up, sizeof(struct v4l2_standard)))
284 return -EFAULT;
285 return 0;
286
287}
288
289static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
290{
291 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
292 copy_to_user(up, kp, sizeof(struct v4l2_standard)))
293 return -EFAULT;
294 return 0;
295}
296
254struct v4l2_standard32 297struct v4l2_standard32
255{ 298{
256 __u32 index; 299 __u32 index;
@@ -264,18 +307,39 @@ struct v4l2_standard32
264static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 307static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
265{ 308{
266 /* other fields are not set by the user, nor used by the driver */ 309 /* other fields are not set by the user, nor used by the driver */
267 return get_user(kp->index, &up->index); 310 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
311 get_user(kp->index, &up->index))
312 return -EFAULT;
313 return 0;
268} 314}
269 315
270static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 316static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
271{ 317{
272 if(put_user(kp->index, &up->index)) 318 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
273 return -EFAULT; 319 put_user(kp->index, &up->index) ||
274 __copy_to_user(up->id, &kp->id, sizeof(__u64)); 320 copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
275 __copy_to_user(up->name, kp->name, 24); 321 copy_to_user(up->name, kp->name, 24) ||
276 __put_user(kp->frameperiod, &up->frameperiod); 322 copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
277 __put_user(kp->framelines, &up->framelines); 323 put_user(kp->framelines, &up->framelines) ||
278 __copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)); 324 copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
325 return -EFAULT;
326 return 0;
327}
328
329static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
330{
331 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
332 copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
333 return -EFAULT;
334 return 0;
335
336}
337
338static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
339{
340 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
341 copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
342 return -EFAULT;
279 return 0; 343 return 0;
280} 344}
281 345
@@ -304,12 +368,13 @@ struct v4l2_buffer32
304static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 368static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
305{ 369{
306 370
307 if (get_user(kp->index, &up->index)) 371 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
308 return -EFAULT; 372 get_user(kp->index, &up->index) ||
309 __get_user(kp->type, &up->type); 373 get_user(kp->type, &up->type) ||
310 __get_user(kp->flags, &up->flags); 374 get_user(kp->flags, &up->flags) ||
311 __get_user(kp->memory, &up->memory); 375 get_user(kp->memory, &up->memory) ||
312 __get_user(kp->input, &up->input); 376 get_user(kp->input, &up->input))
377 return -EFAULT;
313 switch(kp->memory) { 378 switch(kp->memory) {
314 case V4L2_MEMORY_MMAP: 379 case V4L2_MEMORY_MMAP:
315 break; 380 break;
@@ -317,12 +382,14 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
317 { 382 {
318 unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); 383 unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
319 384
320 __get_user(kp->length, &up->length); 385 if(get_user(kp->length, &up->length) ||
321 __get_user(kp->m.userptr, &tmp); 386 get_user(kp->m.userptr, &tmp))
387 return -EFAULT;
322 } 388 }
323 break; 389 break;
324 case V4L2_MEMORY_OVERLAY: 390 case V4L2_MEMORY_OVERLAY:
325 __get_user(kp->m.offset, &up->m.offset); 391 if(get_user(kp->m.offset, &up->m.offset))
392 return -EFAULT;
326 break; 393 break;
327 } 394 }
328 return 0; 395 return 0;
@@ -330,32 +397,37 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
330 397
331static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 398static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
332{ 399{
333 if (put_user(kp->index, &up->index)) 400 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
334 return -EFAULT; 401 put_user(kp->index, &up->index) ||
335 __put_user(kp->type, &up->type); 402 put_user(kp->type, &up->type) ||
336 __put_user(kp->flags, &up->flags); 403 put_user(kp->flags, &up->flags) ||
337 __put_user(kp->memory, &up->memory); 404 put_user(kp->memory, &up->memory) ||
338 __put_user(kp->input, &up->input); 405 put_user(kp->input, &up->input))
406 return -EFAULT;
339 switch(kp->memory) { 407 switch(kp->memory) {
340 case V4L2_MEMORY_MMAP: 408 case V4L2_MEMORY_MMAP:
341 __put_user(kp->length, &up->length); 409 if (put_user(kp->length, &up->length) ||
342 __put_user(kp->m.offset, &up->m.offset); 410 put_user(kp->m.offset, &up->m.offset))
411 return -EFAULT;
343 break; 412 break;
344 case V4L2_MEMORY_USERPTR: 413 case V4L2_MEMORY_USERPTR:
345 __put_user(kp->length, &up->length); 414 if (put_user(kp->length, &up->length) ||
346 __put_user(kp->m.userptr, &up->m.userptr); 415 put_user(kp->m.userptr, &up->m.userptr))
416 return -EFAULT;
347 break; 417 break;
348 case V4L2_MEMORY_OVERLAY: 418 case V4L2_MEMORY_OVERLAY:
349 __put_user(kp->m.offset, &up->m.offset); 419 if (put_user(kp->m.offset, &up->m.offset))
420 return -EFAULT;
350 break; 421 break;
351 } 422 }
352 __put_user(kp->bytesused, &up->bytesused); 423 if (put_user(kp->bytesused, &up->bytesused) ||
353 __put_user(kp->field, &up->field); 424 put_user(kp->field, &up->field) ||
354 __put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec); 425 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
355 __put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec); 426 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
356 __copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)); 427 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
357 __put_user(kp->sequence, &up->sequence); 428 put_user(kp->sequence, &up->sequence) ||
358 __put_user(kp->reserved, &up->reserved); 429 put_user(kp->reserved, &up->reserved))
430 return -EFAULT;
359 return 0; 431 return 0;
360} 432}
361 433
@@ -371,11 +443,12 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
371{ 443{
372 u32 tmp; 444 u32 tmp;
373 445
374 if (get_user(tmp, &up->base)) 446 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
375 return -EFAULT; 447 get_user(tmp, &up->base) ||
448 get_user(kp->capability, &up->capability) ||
449 get_user(kp->flags, &up->flags))
450 return -EFAULT;
376 kp->base = compat_ptr(tmp); 451 kp->base = compat_ptr(tmp);
377 __get_user(kp->capability, &up->capability);
378 __get_user(kp->flags, &up->flags);
379 get_v4l2_pix_format(&kp->fmt, &up->fmt); 452 get_v4l2_pix_format(&kp->fmt, &up->fmt);
380 return 0; 453 return 0;
381} 454}
@@ -384,25 +457,46 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
384{ 457{
385 u32 tmp = (u32)((unsigned long)kp->base); 458 u32 tmp = (u32)((unsigned long)kp->base);
386 459
387 if(put_user(tmp, &up->base)) 460 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
388 return -EFAULT; 461 put_user(tmp, &up->base) ||
389 __put_user(kp->capability, &up->capability); 462 put_user(kp->capability, &up->capability) ||
390 __put_user(kp->flags, &up->flags); 463 put_user(kp->flags, &up->flags))
464 return -EFAULT;
391 put_v4l2_pix_format(&kp->fmt, &up->fmt); 465 put_v4l2_pix_format(&kp->fmt, &up->fmt);
392 return 0; 466 return 0;
393} 467}
394 468
395struct v4l2_input32 /* identical layout, but different size */ 469static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
396{ 470{
397 __u32 index; /* Which input */ 471 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
398 __u8 name[32]; /* Label */ 472 copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
399 __u32 type; /* Type of input */ 473 return -EFAULT;
400 __u32 audioset; /* Associated audios (bitfield) */ 474 return 0;
401 __u32 tuner; /* Associated tuner */ 475}
402 __u32 std[2]; /* __u64 would get the padding wrong */ 476
403 __u32 status; 477static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
404 __u32 reserved[4]; 478{
405}; 479 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
480 copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
481 return -EFAULT;
482 return 0;
483}
484
485static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
486{
487 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
488 copy_from_user(kp, up, sizeof(struct v4l2_input)))
489 return -EFAULT;
490 return 0;
491}
492
493static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
494{
495 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
496 copy_to_user(up, kp, sizeof(struct v4l2_input)))
497 return -EFAULT;
498 return 0;
499}
406 500
407#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) 501#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
408#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) 502#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
@@ -413,6 +507,8 @@ struct v4l2_input32 /* identical layout, but different size */
413#define VIDIOCGFREQ32 _IOR('v',14, u32) 507#define VIDIOCGFREQ32 _IOR('v',14, u32)
414#define VIDIOCSFREQ32 _IOW('v',15, u32) 508#define VIDIOCSFREQ32 _IOW('v',15, u32)
415 509
510/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
511#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
416#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) 512#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32)
417#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) 513#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32)
418#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) 514#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32)
@@ -425,7 +521,6 @@ struct v4l2_input32 /* identical layout, but different size */
425#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) 521#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t)
426#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) 522#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t)
427#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) 523#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32)
428#define VIDIOC_ENUMINPUT32 _IOWR ('V', 26, struct v4l2_input32)
429/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ 524/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */
430#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) 525#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control)
431#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) 526#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t)
@@ -444,6 +539,9 @@ static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
444 int nclips; 539 int nclips;
445 u32 n; 540 u32 n;
446 541
542 if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
543 return -EFAULT;
544
447 if (get_user(nclips, &up->clipcount)) 545 if (get_user(nclips, &up->clipcount))
448 return -EFAULT; 546 return -EFAULT;
449 547
@@ -476,7 +574,9 @@ static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
476 return -EINVAL; 574 return -EINVAL;
477 for (i = 0; i < nclips; i++, u++, p++) { 575 for (i = 0; i < nclips; i++, u++, p++) {
478 s32 v; 576 s32 v;
479 if (get_user(v, &u->x) || 577 if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) ||
578 !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) ||
579 get_user(v, &u->x) ||
480 put_user(v, &p->x) || 580 put_user(v, &p->x) ||
481 get_user(v, &u->y) || 581 get_user(v, &u->y) ||
482 put_user(v, &p->y) || 582 put_user(v, &p->y) ||
@@ -502,11 +602,14 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
502 struct v4l2_buffer v2b; 602 struct v4l2_buffer v2b;
503 struct v4l2_framebuffer v2fb; 603 struct v4l2_framebuffer v2fb;
504 struct v4l2_standard v2s; 604 struct v4l2_standard v2s;
605 struct v4l2_input v2i;
606 struct v4l2_tuner v2t;
505 unsigned long vx; 607 unsigned long vx;
506 } karg; 608 } karg;
507 void __user *up = compat_ptr(arg); 609 void __user *up = compat_ptr(arg);
508 int compatible_arg = 1; 610 int compatible_arg = 1;
509 int err = 0; 611 int err = 0;
612 int realcmd = cmd;
510 613
511 /* First, convert the command. */ 614 /* First, convert the command. */
512 switch(cmd) { 615 switch(cmd) {
@@ -527,8 +630,8 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
527 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 630 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
528 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 631 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
529 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 632 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
530 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; 633 case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
531 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; 634 case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
532 case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break; 635 case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;
533 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 636 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
534 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; 637 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
@@ -577,10 +680,31 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
577 break; 680 break;
578 681
579 case VIDIOC_ENUMSTD: 682 case VIDIOC_ENUMSTD:
683 err = get_v4l2_standard(&karg.v2s, up);
684 compatible_arg = 0;
685 break;
686
687 case VIDIOC_ENUMSTD32:
580 err = get_v4l2_standard32(&karg.v2s, up); 688 err = get_v4l2_standard32(&karg.v2s, up);
581 compatible_arg = 0; 689 compatible_arg = 0;
582 break; 690 break;
583 691
692 case VIDIOC_ENUMINPUT:
693 err = get_v4l2_input(&karg.v2i, up);
694 compatible_arg = 0;
695 break;
696
697 case VIDIOC_ENUMINPUT32:
698 err = get_v4l2_input32(&karg.v2i, up);
699 compatible_arg = 0;
700 break;
701
702 case VIDIOC_G_TUNER:
703 case VIDIOC_S_TUNER:
704 err = get_v4l2_tuner(&karg.v2t, up);
705 compatible_arg = 0;
706 break;
707
584 case VIDIOCGWIN: 708 case VIDIOCGWIN:
585 case VIDIOCGFBUF: 709 case VIDIOCGFBUF:
586 case VIDIOCGFREQ: 710 case VIDIOCGFREQ:
@@ -593,12 +717,12 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
593 goto out; 717 goto out;
594 718
595 if(compatible_arg) 719 if(compatible_arg)
596 err = native_ioctl(file, cmd, (unsigned long)up); 720 err = native_ioctl(file, realcmd, (unsigned long)up);
597 else { 721 else {
598 mm_segment_t old_fs = get_fs(); 722 mm_segment_t old_fs = get_fs();
599 723
600 set_fs(KERNEL_DS); 724 set_fs(KERNEL_DS);
601 err = native_ioctl(file, cmd, (unsigned long)&karg); 725 err = native_ioctl(file, realcmd, (unsigned long)&karg);
602 set_fs(old_fs); 726 set_fs(old_fs);
603 } 727 }
604 if(err == 0) { 728 if(err == 0) {
@@ -632,9 +756,26 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
632 break; 756 break;
633 757
634 case VIDIOC_ENUMSTD: 758 case VIDIOC_ENUMSTD:
759 err = put_v4l2_standard(&karg.v2s, up);
760 break;
761
762 case VIDIOC_ENUMSTD32:
635 err = put_v4l2_standard32(&karg.v2s, up); 763 err = put_v4l2_standard32(&karg.v2s, up);
636 break; 764 break;
637 765
766 case VIDIOC_G_TUNER:
767 case VIDIOC_S_TUNER:
768 err = put_v4l2_tuner(&karg.v2t, up);
769 break;
770
771 case VIDIOC_ENUMINPUT:
772 err = put_v4l2_input(&karg.v2i, up);
773 break;
774
775 case VIDIOC_ENUMINPUT32:
776 err = put_v4l2_input32(&karg.v2i, up);
777 break;
778
638 case VIDIOCGFREQ: 779 case VIDIOCGFREQ:
639 case VIDIOC_G_INPUT: 780 case VIDIOC_G_INPUT:
640 err = put_user(((u32)karg.vx), (u32 __user *)up); 781 err = put_user(((u32)karg.vx), (u32 __user *)up);
@@ -679,7 +820,11 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
679 case VIDIOC_G_PARM: 820 case VIDIOC_G_PARM:
680 case VIDIOC_G_STD: 821 case VIDIOC_G_STD:
681 case VIDIOC_S_STD: 822 case VIDIOC_S_STD:
823 case VIDIOC_G_TUNER:
824 case VIDIOC_S_TUNER:
825 case VIDIOC_ENUMSTD:
682 case VIDIOC_ENUMSTD32: 826 case VIDIOC_ENUMSTD32:
827 case VIDIOC_ENUMINPUT:
683 case VIDIOC_ENUMINPUT32: 828 case VIDIOC_ENUMINPUT32:
684 case VIDIOC_G_CTRL: 829 case VIDIOC_G_CTRL:
685 case VIDIOC_S_CTRL32: 830 case VIDIOC_S_CTRL32:
@@ -718,6 +863,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
718 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): 863 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
719 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 864 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
720 break; 865 break;
866 default:
867 v4l_print_ioctl("compat_ioctl32", cmd);
721 } 868 }
722 return ret; 869 return ret;
723} 870}