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>

authored by Guy Martin and committed by Mauro Carvalho Chehab a113bc78 f8bf134d

+259 -112
+259 -112
drivers/media/video/compat_ioctl32.c
··· 18 #include <linux/videodev2.h> 19 #include <linux/module.h> 20 #include <linux/smp_lock.h> 21 22 #ifdef CONFIG_COMPAT 23 struct video_tuner32 { 24 compat_int_t tuner; 25 char name[32]; ··· 33 34 static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 35 { 36 - if(get_user(kp->tuner, &up->tuner)) 37 return -EFAULT; 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); 44 return 0; 45 } 46 47 static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 48 { 49 - if(put_user(kp->tuner, &up->tuner)) 50 - return -EFAULT; 51 - __copy_to_user(up->name, kp->name, 32); 52 - __put_user(kp->rangelow, &up->rangelow); 53 - __put_user(kp->rangehigh, &up->rangehigh); 54 - __put_user(kp->flags, &up->flags); 55 - __put_user(kp->mode, &up->mode); 56 - __put_user(kp->signal, &up->signal); 57 return 0; 58 } 59 ··· 68 { 69 u32 tmp; 70 71 - if (get_user(tmp, &up->base)) 72 - return -EFAULT; 73 74 /* This is actually a physical address stored 75 * as a void pointer. 76 */ 77 kp->base = (void *)(unsigned long) tmp; 78 79 - __get_user(kp->height, &up->height); 80 - __get_user(kp->width, &up->width); 81 - __get_user(kp->depth, &up->depth); 82 - __get_user(kp->bytesperline, &up->bytesperline); 83 return 0; 84 } 85 ··· 88 { 89 u32 tmp = (u32)((unsigned long)kp->base); 90 91 - if(put_user(tmp, &up->base)) 92 - return -EFAULT; 93 - __put_user(kp->height, &up->height); 94 - __put_user(kp->width, &up->width); 95 - __put_user(kp->depth, &up->depth); 96 - __put_user(kp->bytesperline, &up->bytesperline); 97 return 0; 98 } 99 ··· 128 /* You get back everything except the clips... */ 129 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) 130 { 131 - if(put_user(kp->x, &up->x)) 132 - return -EFAULT; 133 - __put_user(kp->y, &up->y); 134 - __put_user(kp->width, &up->width); 135 - __put_user(kp->height, &up->height); 136 - __put_user(kp->chromakey, &up->chromakey); 137 - __put_user(kp->flags, &up->flags); 138 - __put_user(kp->clipcount, &up->clipcount); 139 return 0; 140 } 141 ··· 158 159 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 160 { 161 - if (copy_from_user(&kp->w, &up->w, sizeof(up->w))) 162 - return -EFAULT; 163 - __get_user(kp->field, &up->field); 164 - __get_user(kp->chromakey, &up->chromakey); 165 - __get_user(kp->clipcount, &up->clipcount); 166 if (kp->clipcount > 2048) 167 return -EINVAL; 168 if (kp->clipcount) { ··· 174 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 175 kp->clips = kclips; 176 while (--n >= 0) { 177 - copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)); 178 kclips->next = n ? kclips + 1 : 0; 179 uclips += 1; 180 kclips += 1; ··· 188 189 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 190 { 191 - if (copy_to_user(&up->w, &kp->w, sizeof(up->w))) 192 - return -EFAULT; 193 - __put_user(kp->field, &up->field); 194 - __put_user(kp->chromakey, &up->chromakey); 195 - __put_user(kp->clipcount, &up->clipcount); 196 return 0; 197 } 198 199 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 200 { 201 - return copy_from_user(kp, up, sizeof(struct v4l2_pix_format)); 202 } 203 204 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 205 { 206 - return copy_to_user(up, kp, sizeof(struct v4l2_pix_format)); 207 } 208 209 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 210 { 211 - return copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)); 212 } 213 214 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 215 { 216 - return copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)); 217 } 218 219 struct v4l2_format32 ··· 243 244 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 245 { 246 - if(get_user(kp->type, &up->type)) 247 - return -EFAULT; 248 switch (kp->type) { 249 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 250 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ··· 262 263 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 264 { 265 - if(put_user(kp->type, &up->type)) 266 return -EFAULT; 267 switch (kp->type) { 268 case V4L2_BUF_TYPE_VIDEO_CAPTURE: ··· 275 default: 276 return -ENXIO; 277 } 278 } 279 280 struct v4l2_standard32 ··· 307 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 308 { 309 /* other fields are not set by the user, nor used by the driver */ 310 - return get_user(kp->index, &up->index); 311 } 312 313 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 314 { 315 - if(put_user(kp->index, &up->index)) 316 - return -EFAULT; 317 - __copy_to_user(up->id, &kp->id, sizeof(__u64)); 318 - __copy_to_user(up->name, kp->name, 24); 319 - __put_user(kp->frameperiod, &up->frameperiod); 320 - __put_user(kp->framelines, &up->framelines); 321 - __copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)); 322 return 0; 323 } 324 ··· 368 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 369 { 370 371 - if (get_user(kp->index, &up->index)) 372 - return -EFAULT; 373 - __get_user(kp->type, &up->type); 374 - __get_user(kp->flags, &up->flags); 375 - __get_user(kp->memory, &up->memory); 376 - __get_user(kp->input, &up->input); 377 switch(kp->memory) { 378 case V4L2_MEMORY_MMAP: 379 break; ··· 382 { 383 unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); 384 385 - __get_user(kp->length, &up->length); 386 - __get_user(kp->m.userptr, &tmp); 387 } 388 break; 389 case V4L2_MEMORY_OVERLAY: 390 - __get_user(kp->m.offset, &up->m.offset); 391 break; 392 } 393 return 0; ··· 397 398 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 399 { 400 - if (put_user(kp->index, &up->index)) 401 - return -EFAULT; 402 - __put_user(kp->type, &up->type); 403 - __put_user(kp->flags, &up->flags); 404 - __put_user(kp->memory, &up->memory); 405 - __put_user(kp->input, &up->input); 406 switch(kp->memory) { 407 case V4L2_MEMORY_MMAP: 408 - __put_user(kp->length, &up->length); 409 - __put_user(kp->m.offset, &up->m.offset); 410 break; 411 case V4L2_MEMORY_USERPTR: 412 - __put_user(kp->length, &up->length); 413 - __put_user(kp->m.userptr, &up->m.userptr); 414 break; 415 case V4L2_MEMORY_OVERLAY: 416 - __put_user(kp->m.offset, &up->m.offset); 417 break; 418 } 419 - __put_user(kp->bytesused, &up->bytesused); 420 - __put_user(kp->field, &up->field); 421 - __put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec); 422 - __put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec); 423 - __copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)); 424 - __put_user(kp->sequence, &up->sequence); 425 - __put_user(kp->reserved, &up->reserved); 426 return 0; 427 } 428 ··· 443 { 444 u32 tmp; 445 446 - if (get_user(tmp, &up->base)) 447 - return -EFAULT; 448 kp->base = compat_ptr(tmp); 449 - __get_user(kp->capability, &up->capability); 450 - __get_user(kp->flags, &up->flags); 451 get_v4l2_pix_format(&kp->fmt, &up->fmt); 452 return 0; 453 } ··· 457 { 458 u32 tmp = (u32)((unsigned long)kp->base); 459 460 - if(put_user(tmp, &up->base)) 461 - return -EFAULT; 462 - __put_user(kp->capability, &up->capability); 463 - __put_user(kp->flags, &up->flags); 464 put_v4l2_pix_format(&kp->fmt, &up->fmt); 465 return 0; 466 } 467 468 - struct v4l2_input32 /* identical layout, but different size */ 469 { 470 - __u32 index; /* Which input */ 471 - __u8 name[32]; /* Label */ 472 - __u32 type; /* Type of input */ 473 - __u32 audioset; /* Associated audios (bitfield) */ 474 - __u32 tuner; /* Associated tuner */ 475 - __u32 std[2]; /* __u64 would get the padding wrong */ 476 - __u32 status; 477 - __u32 reserved[4]; 478 - }; 479 480 #define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) 481 #define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) ··· 507 #define VIDIOCGFREQ32 _IOR('v',14, u32) 508 #define VIDIOCSFREQ32 _IOW('v',15, u32) 509 510 #define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) 511 #define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) 512 #define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) ··· 521 #define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) 522 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) 523 #define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) 524 - #define VIDIOC_ENUMINPUT32 _IOWR ('V', 26, struct v4l2_input32) 525 /* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ 526 #define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) 527 #define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) ··· 538 struct video_clip __user *p; 539 int nclips; 540 u32 n; 541 542 if (get_user(nclips, &up->clipcount)) 543 return -EFAULT; ··· 574 return -EINVAL; 575 for (i = 0; i < nclips; i++, u++, p++) { 576 s32 v; 577 - if (get_user(v, &u->x) || 578 put_user(v, &p->x) || 579 get_user(v, &u->y) || 580 put_user(v, &p->y) || ··· 602 struct v4l2_buffer v2b; 603 struct v4l2_framebuffer v2fb; 604 struct v4l2_standard v2s; 605 unsigned long vx; 606 } karg; 607 void __user *up = compat_ptr(arg); 608 int compatible_arg = 1; 609 int err = 0; 610 611 /* First, convert the command. */ 612 switch(cmd) { ··· 630 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 631 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 632 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 633 - case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; 634 - case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; 635 case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break; 636 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 637 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; ··· 680 break; 681 682 case VIDIOC_ENUMSTD: 683 err = get_v4l2_standard32(&karg.v2s, up); 684 compatible_arg = 0; 685 break; 686 ··· 717 goto out; 718 719 if(compatible_arg) 720 - err = native_ioctl(file, cmd, (unsigned long)up); 721 else { 722 mm_segment_t old_fs = get_fs(); 723 724 set_fs(KERNEL_DS); 725 - err = native_ioctl(file, cmd, (unsigned long)&karg); 726 set_fs(old_fs); 727 } 728 if(err == 0) { ··· 756 break; 757 758 case VIDIOC_ENUMSTD: 759 err = put_v4l2_standard32(&karg.v2s, up); 760 break; 761 762 case VIDIOCGFREQ: ··· 820 case VIDIOC_G_PARM: 821 case VIDIOC_G_STD: 822 case VIDIOC_S_STD: 823 case VIDIOC_ENUMSTD32: 824 case VIDIOC_ENUMINPUT32: 825 case VIDIOC_G_CTRL: 826 case VIDIOC_S_CTRL32: ··· 863 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): 864 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 865 break; 866 } 867 return ret; 868 }
··· 18 #include <linux/videodev2.h> 19 #include <linux/module.h> 20 #include <linux/smp_lock.h> 21 + #include <media/v4l2-common.h> 22 23 #ifdef CONFIG_COMPAT 24 + 25 + 26 struct video_tuner32 { 27 compat_int_t tuner; 28 char name[32]; ··· 30 31 static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 32 { 33 + if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || 34 + get_user(kp->tuner, &up->tuner) || 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 -EFAULT; 42 return 0; 43 } 44 45 static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 46 { 47 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || 48 + put_user(kp->tuner, &up->tuner) || 49 + copy_to_user(up->name, kp->name, 32) || 50 + put_user(kp->rangelow, &up->rangelow) || 51 + put_user(kp->rangehigh, &up->rangehigh) || 52 + put_user(kp->flags, &up->flags) || 53 + put_user(kp->mode, &up->mode) || 54 + put_user(kp->signal, &up->signal)) 55 + return -EFAULT; 56 return 0; 57 } 58 ··· 63 { 64 u32 tmp; 65 66 + if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || 67 + get_user(tmp, &up->base) || 68 + get_user(kp->height, &up->height) || 69 + get_user(kp->width, &up->width) || 70 + get_user(kp->depth, &up->depth) || 71 + get_user(kp->bytesperline, &up->bytesperline)) 72 + return -EFAULT; 73 74 /* This is actually a physical address stored 75 * as a void pointer. 76 */ 77 kp->base = (void *)(unsigned long) tmp; 78 79 return 0; 80 } 81 ··· 82 { 83 u32 tmp = (u32)((unsigned long)kp->base); 84 85 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || 86 + put_user(tmp, &up->base) || 87 + put_user(kp->height, &up->height) || 88 + put_user(kp->width, &up->width) || 89 + put_user(kp->depth, &up->depth) || 90 + put_user(kp->bytesperline, &up->bytesperline)) 91 + return -EFAULT; 92 return 0; 93 } 94 ··· 121 /* You get back everything except the clips... */ 122 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) 123 { 124 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || 125 + put_user(kp->x, &up->x) || 126 + put_user(kp->y, &up->y) || 127 + put_user(kp->width, &up->width) || 128 + put_user(kp->height, &up->height) || 129 + put_user(kp->chromakey, &up->chromakey) || 130 + put_user(kp->flags, &up->flags) || 131 + put_user(kp->clipcount, &up->clipcount)) 132 + return -EFAULT; 133 return 0; 134 } 135 ··· 150 151 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 152 { 153 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || 154 + copy_from_user(&kp->w, &up->w, sizeof(up->w)) || 155 + get_user(kp->field, &up->field) || 156 + get_user(kp->chromakey, &up->chromakey) || 157 + get_user(kp->clipcount, &up->clipcount)) 158 + return -EFAULT; 159 if (kp->clipcount > 2048) 160 return -EINVAL; 161 if (kp->clipcount) { ··· 165 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 166 kp->clips = kclips; 167 while (--n >= 0) { 168 + if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) || 169 + copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c))) 170 + return -EFAULT; 171 kclips->next = n ? kclips + 1 : 0; 172 uclips += 1; 173 kclips += 1; ··· 177 178 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 179 { 180 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) || 181 + copy_to_user(&up->w, &kp->w, sizeof(up->w)) || 182 + put_user(kp->field, &up->field) || 183 + put_user(kp->chromakey, &up->chromakey) || 184 + put_user(kp->clipcount, &up->clipcount)) 185 + return -EFAULT; 186 return 0; 187 } 188 189 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 190 { 191 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) || 192 + copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) 193 + return -EFAULT; 194 + return 0; 195 } 196 197 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 198 { 199 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) || 200 + copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) 201 + return -EFAULT; 202 + return 0; 203 } 204 205 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 206 { 207 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) || 208 + copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) 209 + return -EFAULT; 210 + return 0; 211 } 212 213 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 214 { 215 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) || 216 + copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) 217 + return -EFAULT; 218 + return 0; 219 } 220 221 struct v4l2_format32 ··· 219 220 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 221 { 222 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || 223 + get_user(kp->type, &up->type)) 224 + return -EFAULT; 225 switch (kp->type) { 226 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 227 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ··· 237 238 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 239 { 240 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || 241 + put_user(kp->type, &up->type)) 242 return -EFAULT; 243 switch (kp->type) { 244 case V4L2_BUF_TYPE_VIDEO_CAPTURE: ··· 249 default: 250 return -ENXIO; 251 } 252 + } 253 + 254 + static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 255 + { 256 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) || 257 + copy_from_user(kp, up, sizeof(struct v4l2_standard))) 258 + return -EFAULT; 259 + return 0; 260 + 261 + } 262 + 263 + static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 264 + { 265 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) || 266 + copy_to_user(up, kp, sizeof(struct v4l2_standard))) 267 + return -EFAULT; 268 + return 0; 269 } 270 271 struct v4l2_standard32 ··· 264 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 265 { 266 /* other fields are not set by the user, nor used by the driver */ 267 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || 268 + get_user(kp->index, &up->index)) 269 + return -EFAULT; 270 + return 0; 271 } 272 273 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 274 { 275 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || 276 + put_user(kp->index, &up->index) || 277 + copy_to_user(up->id, &kp->id, sizeof(__u64)) || 278 + copy_to_user(up->name, kp->name, 24) || 279 + copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || 280 + put_user(kp->framelines, &up->framelines) || 281 + copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) 282 + return -EFAULT; 283 + return 0; 284 + } 285 + 286 + static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) 287 + { 288 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) || 289 + copy_from_user(kp, up, sizeof(struct v4l2_tuner))) 290 + return -EFAULT; 291 + return 0; 292 + 293 + } 294 + 295 + static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) 296 + { 297 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) || 298 + copy_to_user(up, kp, sizeof(struct v4l2_tuner))) 299 + return -EFAULT; 300 return 0; 301 } 302 ··· 304 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 305 { 306 307 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 308 + get_user(kp->index, &up->index) || 309 + get_user(kp->type, &up->type) || 310 + get_user(kp->flags, &up->flags) || 311 + get_user(kp->memory, &up->memory) || 312 + get_user(kp->input, &up->input)) 313 + return -EFAULT; 314 switch(kp->memory) { 315 case V4L2_MEMORY_MMAP: 316 break; ··· 317 { 318 unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); 319 320 + if(get_user(kp->length, &up->length) || 321 + get_user(kp->m.userptr, &tmp)) 322 + return -EFAULT; 323 } 324 break; 325 case V4L2_MEMORY_OVERLAY: 326 + if(get_user(kp->m.offset, &up->m.offset)) 327 + return -EFAULT; 328 break; 329 } 330 return 0; ··· 330 331 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 332 { 333 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 334 + put_user(kp->index, &up->index) || 335 + put_user(kp->type, &up->type) || 336 + put_user(kp->flags, &up->flags) || 337 + put_user(kp->memory, &up->memory) || 338 + put_user(kp->input, &up->input)) 339 + return -EFAULT; 340 switch(kp->memory) { 341 case V4L2_MEMORY_MMAP: 342 + if (put_user(kp->length, &up->length) || 343 + put_user(kp->m.offset, &up->m.offset)) 344 + return -EFAULT; 345 break; 346 case V4L2_MEMORY_USERPTR: 347 + if (put_user(kp->length, &up->length) || 348 + put_user(kp->m.userptr, &up->m.userptr)) 349 + return -EFAULT; 350 break; 351 case V4L2_MEMORY_OVERLAY: 352 + if (put_user(kp->m.offset, &up->m.offset)) 353 + return -EFAULT; 354 break; 355 } 356 + if (put_user(kp->bytesused, &up->bytesused) || 357 + put_user(kp->field, &up->field) || 358 + put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 359 + put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || 360 + copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || 361 + put_user(kp->sequence, &up->sequence) || 362 + put_user(kp->reserved, &up->reserved)) 363 + return -EFAULT; 364 return 0; 365 } 366 ··· 371 { 372 u32 tmp; 373 374 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || 375 + get_user(tmp, &up->base) || 376 + get_user(kp->capability, &up->capability) || 377 + get_user(kp->flags, &up->flags)) 378 + return -EFAULT; 379 kp->base = compat_ptr(tmp); 380 get_v4l2_pix_format(&kp->fmt, &up->fmt); 381 return 0; 382 } ··· 384 { 385 u32 tmp = (u32)((unsigned long)kp->base); 386 387 + if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || 388 + put_user(tmp, &up->base) || 389 + put_user(kp->capability, &up->capability) || 390 + put_user(kp->flags, &up->flags)) 391 + return -EFAULT; 392 put_v4l2_pix_format(&kp->fmt, &up->fmt); 393 return 0; 394 } 395 396 + static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) 397 { 398 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) || 399 + copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) 400 + return -EFAULT; 401 + return 0; 402 + } 403 + 404 + static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) 405 + { 406 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) || 407 + copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) 408 + return -EFAULT; 409 + return 0; 410 + } 411 + 412 + static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 413 + { 414 + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) || 415 + copy_from_user(kp, up, sizeof(struct v4l2_input))) 416 + return -EFAULT; 417 + return 0; 418 + } 419 + 420 + static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 421 + { 422 + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) || 423 + copy_to_user(up, kp, sizeof(struct v4l2_input))) 424 + return -EFAULT; 425 + return 0; 426 + } 427 428 #define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) 429 #define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) ··· 413 #define VIDIOCGFREQ32 _IOR('v',14, u32) 414 #define VIDIOCSFREQ32 _IOW('v',15, u32) 415 416 + /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ 417 + #define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4) 418 #define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) 419 #define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) 420 #define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) ··· 425 #define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) 426 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) 427 #define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) 428 /* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ 429 #define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) 430 #define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) ··· 443 struct video_clip __user *p; 444 int nclips; 445 u32 n; 446 + 447 + if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) 448 + return -EFAULT; 449 450 if (get_user(nclips, &up->clipcount)) 451 return -EFAULT; ··· 476 return -EINVAL; 477 for (i = 0; i < nclips; i++, u++, p++) { 478 s32 v; 479 + if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) || 480 + !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) || 481 + get_user(v, &u->x) || 482 put_user(v, &p->x) || 483 get_user(v, &u->y) || 484 put_user(v, &p->y) || ··· 502 struct v4l2_buffer v2b; 503 struct v4l2_framebuffer v2fb; 504 struct v4l2_standard v2s; 505 + struct v4l2_input v2i; 506 + struct v4l2_tuner v2t; 507 unsigned long vx; 508 } karg; 509 void __user *up = compat_ptr(arg); 510 int compatible_arg = 1; 511 int err = 0; 512 + int realcmd = cmd; 513 514 /* First, convert the command. */ 515 switch(cmd) { ··· 527 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 528 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 529 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 530 + case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break; 531 + case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break; 532 case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break; 533 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 534 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; ··· 577 break; 578 579 case VIDIOC_ENUMSTD: 580 + err = get_v4l2_standard(&karg.v2s, up); 581 + compatible_arg = 0; 582 + break; 583 + 584 + case VIDIOC_ENUMSTD32: 585 err = get_v4l2_standard32(&karg.v2s, up); 586 + compatible_arg = 0; 587 + break; 588 + 589 + case VIDIOC_ENUMINPUT: 590 + err = get_v4l2_input(&karg.v2i, up); 591 + compatible_arg = 0; 592 + break; 593 + 594 + case VIDIOC_ENUMINPUT32: 595 + err = get_v4l2_input32(&karg.v2i, up); 596 + compatible_arg = 0; 597 + break; 598 + 599 + case VIDIOC_G_TUNER: 600 + case VIDIOC_S_TUNER: 601 + err = get_v4l2_tuner(&karg.v2t, up); 602 compatible_arg = 0; 603 break; 604 ··· 593 goto out; 594 595 if(compatible_arg) 596 + err = native_ioctl(file, realcmd, (unsigned long)up); 597 else { 598 mm_segment_t old_fs = get_fs(); 599 600 set_fs(KERNEL_DS); 601 + err = native_ioctl(file, realcmd, (unsigned long)&karg); 602 set_fs(old_fs); 603 } 604 if(err == 0) { ··· 632 break; 633 634 case VIDIOC_ENUMSTD: 635 + err = put_v4l2_standard(&karg.v2s, up); 636 + break; 637 + 638 + case VIDIOC_ENUMSTD32: 639 err = put_v4l2_standard32(&karg.v2s, up); 640 + break; 641 + 642 + case VIDIOC_G_TUNER: 643 + case VIDIOC_S_TUNER: 644 + err = put_v4l2_tuner(&karg.v2t, up); 645 + break; 646 + 647 + case VIDIOC_ENUMINPUT: 648 + err = put_v4l2_input(&karg.v2i, up); 649 + break; 650 + 651 + case VIDIOC_ENUMINPUT32: 652 + err = put_v4l2_input32(&karg.v2i, up); 653 break; 654 655 case VIDIOCGFREQ: ··· 679 case VIDIOC_G_PARM: 680 case VIDIOC_G_STD: 681 case VIDIOC_S_STD: 682 + case VIDIOC_G_TUNER: 683 + case VIDIOC_S_TUNER: 684 + case VIDIOC_ENUMSTD: 685 case VIDIOC_ENUMSTD32: 686 + case VIDIOC_ENUMINPUT: 687 case VIDIOC_ENUMINPUT32: 688 case VIDIOC_G_CTRL: 689 case VIDIOC_S_CTRL32: ··· 718 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): 719 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 720 break; 721 + default: 722 + v4l_print_ioctl("compat_ioctl32", cmd); 723 } 724 return ret; 725 }