1 /* 2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls. 3 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de> 4 * 5 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) 6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 7 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs 8 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) 9 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) 10 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> 11 * 12 * These routines maintain argument size conversion between 32bit and 64bit 13 * ioctls. 14 */ 15 16 #include <linux/compat.h> 17 #include <linux/module.h> 18 #include <linux/videodev2.h> 19 #include <linux/v4l2-subdev.h> 20 #include <media/v4l2-dev.h> 21 #include <media/v4l2-ioctl.h> 22 23 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 24 { 25 long ret = -ENOIOCTLCMD; 26 27 if (file->f_op->unlocked_ioctl) 28 ret = file->f_op->unlocked_ioctl(file, cmd, arg); 29 30 return ret; 31 } 32 33 34 struct v4l2_clip32 { 35 struct v4l2_rect c; 36 compat_caddr_t next; 37 }; 38 39 struct v4l2_window32 { 40 struct v4l2_rect w; 41 __u32 field; /* enum v4l2_field */ 42 __u32 chromakey; 43 compat_caddr_t clips; /* actually struct v4l2_clip32 * */ 44 __u32 clipcount; 45 compat_caddr_t bitmap; 46 }; 47 48 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 49 { 50 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || 51 copy_from_user(&kp->w, &up->w, sizeof(up->w)) || 52 get_user(kp->field, &up->field) || 53 get_user(kp->chromakey, &up->chromakey) || 54 get_user(kp->clipcount, &up->clipcount)) 55 return -EFAULT; 56 if (kp->clipcount > 2048) 57 return -EINVAL; 58 if (kp->clipcount) { 59 struct v4l2_clip32 __user *uclips; 60 struct v4l2_clip __user *kclips; 61 int n = kp->clipcount; 62 compat_caddr_t p; 63 64 if (get_user(p, &up->clips)) 65 return -EFAULT; 66 uclips = compat_ptr(p); 67 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 68 kp->clips = kclips; 69 while (--n >= 0) { 70 if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) 71 return -EFAULT; 72 if (put_user(n ? kclips + 1 : NULL, &kclips->next)) 73 return -EFAULT; 74 uclips += 1; 75 kclips += 1; 76 } 77 } else 78 kp->clips = NULL; 79 return 0; 80 } 81 82 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 83 { 84 if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || 85 put_user(kp->field, &up->field) || 86 put_user(kp->chromakey, &up->chromakey) || 87 put_user(kp->clipcount, &up->clipcount)) 88 return -EFAULT; 89 return 0; 90 } 91 92 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 93 { 94 if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) 95 return -EFAULT; 96 return 0; 97 } 98 99 static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, 100 struct v4l2_pix_format_mplane __user *up) 101 { 102 if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) 103 return -EFAULT; 104 return 0; 105 } 106 107 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 108 { 109 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) 110 return -EFAULT; 111 return 0; 112 } 113 114 static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, 115 struct v4l2_pix_format_mplane __user *up) 116 { 117 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) 118 return -EFAULT; 119 return 0; 120 } 121 122 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 123 { 124 if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) 125 return -EFAULT; 126 return 0; 127 } 128 129 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 130 { 131 if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) 132 return -EFAULT; 133 return 0; 134 } 135 136 static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) 137 { 138 if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) 139 return -EFAULT; 140 return 0; 141 } 142 143 static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) 144 { 145 if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) 146 return -EFAULT; 147 return 0; 148 } 149 150 struct v4l2_format32 { 151 __u32 type; /* enum v4l2_buf_type */ 152 union { 153 struct v4l2_pix_format pix; 154 struct v4l2_pix_format_mplane pix_mp; 155 struct v4l2_window32 win; 156 struct v4l2_vbi_format vbi; 157 struct v4l2_sliced_vbi_format sliced; 158 __u8 raw_data[200]; /* user-defined */ 159 } fmt; 160 }; 161 162 /** 163 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument 164 * @index: on return, index of the first created buffer 165 * @count: entry: number of requested buffers, 166 * return: number of created buffers 167 * @memory: buffer memory type 168 * @format: frame format, for which buffers are requested 169 * @reserved: future extensions 170 */ 171 struct v4l2_create_buffers32 { 172 __u32 index; 173 __u32 count; 174 __u32 memory; /* enum v4l2_memory */ 175 struct v4l2_format32 format; 176 __u32 reserved[8]; 177 }; 178 179 static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 180 { 181 switch (kp->type) { 182 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 183 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 184 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 185 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 186 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 187 return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, 188 &up->fmt.pix_mp); 189 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 190 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 191 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); 192 case V4L2_BUF_TYPE_VBI_CAPTURE: 193 case V4L2_BUF_TYPE_VBI_OUTPUT: 194 return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 195 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 196 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 197 return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); 198 default: 199 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", 200 kp->type); 201 return -EINVAL; 202 } 203 } 204 205 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 206 { 207 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || 208 get_user(kp->type, &up->type)) 209 return -EFAULT; 210 return __get_v4l2_format32(kp, up); 211 } 212 213 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) 214 { 215 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || 216 copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt))) 217 return -EFAULT; 218 return __get_v4l2_format32(&kp->format, &up->format); 219 } 220 221 static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 222 { 223 switch (kp->type) { 224 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 225 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 226 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 227 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 228 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 229 return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp, 230 &up->fmt.pix_mp); 231 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 232 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 233 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); 234 case V4L2_BUF_TYPE_VBI_CAPTURE: 235 case V4L2_BUF_TYPE_VBI_OUTPUT: 236 return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 237 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 238 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 239 return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); 240 default: 241 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", 242 kp->type); 243 return -EINVAL; 244 } 245 } 246 247 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 248 { 249 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || 250 put_user(kp->type, &up->type)) 251 return -EFAULT; 252 return __put_v4l2_format32(kp, up); 253 } 254 255 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) 256 { 257 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || 258 copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt))) 259 return -EFAULT; 260 return __put_v4l2_format32(&kp->format, &up->format); 261 } 262 263 struct v4l2_standard32 { 264 __u32 index; 265 __u32 id[2]; /* __u64 would get the alignment wrong */ 266 __u8 name[24]; 267 struct v4l2_fract frameperiod; /* Frames, not fields */ 268 __u32 framelines; 269 __u32 reserved[4]; 270 }; 271 272 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 273 { 274 /* other fields are not set by the user, nor used by the driver */ 275 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || 276 get_user(kp->index, &up->index)) 277 return -EFAULT; 278 return 0; 279 } 280 281 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 282 { 283 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || 284 put_user(kp->index, &up->index) || 285 copy_to_user(up->id, &kp->id, sizeof(__u64)) || 286 copy_to_user(up->name, kp->name, 24) || 287 copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || 288 put_user(kp->framelines, &up->framelines) || 289 copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) 290 return -EFAULT; 291 return 0; 292 } 293 294 struct v4l2_plane32 { 295 __u32 bytesused; 296 __u32 length; 297 union { 298 __u32 mem_offset; 299 compat_long_t userptr; 300 } m; 301 __u32 data_offset; 302 __u32 reserved[11]; 303 }; 304 305 struct v4l2_buffer32 { 306 __u32 index; 307 __u32 type; /* enum v4l2_buf_type */ 308 __u32 bytesused; 309 __u32 flags; 310 __u32 field; /* enum v4l2_field */ 311 struct compat_timeval timestamp; 312 struct v4l2_timecode timecode; 313 __u32 sequence; 314 315 /* memory location */ 316 __u32 memory; /* enum v4l2_memory */ 317 union { 318 __u32 offset; 319 compat_long_t userptr; 320 compat_caddr_t planes; 321 } m; 322 __u32 length; 323 __u32 reserved2; 324 __u32 reserved; 325 }; 326 327 static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, 328 enum v4l2_memory memory) 329 { 330 void __user *up_pln; 331 compat_long_t p; 332 333 if (copy_in_user(up, up32, 2 * sizeof(__u32)) || 334 copy_in_user(&up->data_offset, &up32->data_offset, 335 sizeof(__u32))) 336 return -EFAULT; 337 338 if (memory == V4L2_MEMORY_USERPTR) { 339 if (get_user(p, &up32->m.userptr)) 340 return -EFAULT; 341 up_pln = compat_ptr(p); 342 if (put_user((unsigned long)up_pln, &up->m.userptr)) 343 return -EFAULT; 344 } else { 345 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, 346 sizeof(__u32))) 347 return -EFAULT; 348 } 349 350 return 0; 351 } 352 353 static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, 354 enum v4l2_memory memory) 355 { 356 if (copy_in_user(up32, up, 2 * sizeof(__u32)) || 357 copy_in_user(&up32->data_offset, &up->data_offset, 358 sizeof(__u32))) 359 return -EFAULT; 360 361 /* For MMAP, driver might've set up the offset, so copy it back. 362 * USERPTR stays the same (was userspace-provided), so no copying. */ 363 if (memory == V4L2_MEMORY_MMAP) 364 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, 365 sizeof(__u32))) 366 return -EFAULT; 367 368 return 0; 369 } 370 371 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 372 { 373 struct v4l2_plane32 __user *uplane32; 374 struct v4l2_plane __user *uplane; 375 compat_caddr_t p; 376 int num_planes; 377 int ret; 378 379 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 380 get_user(kp->index, &up->index) || 381 get_user(kp->type, &up->type) || 382 get_user(kp->flags, &up->flags) || 383 get_user(kp->memory, &up->memory)) 384 return -EFAULT; 385 386 if (V4L2_TYPE_IS_OUTPUT(kp->type)) 387 if (get_user(kp->bytesused, &up->bytesused) || 388 get_user(kp->field, &up->field) || 389 get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 390 get_user(kp->timestamp.tv_usec, 391 &up->timestamp.tv_usec)) 392 return -EFAULT; 393 394 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 395 if (get_user(kp->length, &up->length)) 396 return -EFAULT; 397 398 num_planes = kp->length; 399 if (num_planes == 0) { 400 kp->m.planes = NULL; 401 /* num_planes == 0 is legal, e.g. when userspace doesn't 402 * need planes array on DQBUF*/ 403 return 0; 404 } 405 406 if (get_user(p, &up->m.planes)) 407 return -EFAULT; 408 409 uplane32 = compat_ptr(p); 410 if (!access_ok(VERIFY_READ, uplane32, 411 num_planes * sizeof(struct v4l2_plane32))) 412 return -EFAULT; 413 414 /* We don't really care if userspace decides to kill itself 415 * by passing a very big num_planes value */ 416 uplane = compat_alloc_user_space(num_planes * 417 sizeof(struct v4l2_plane)); 418 kp->m.planes = uplane; 419 420 while (--num_planes >= 0) { 421 ret = get_v4l2_plane32(uplane, uplane32, kp->memory); 422 if (ret) 423 return ret; 424 ++uplane; 425 ++uplane32; 426 } 427 } else { 428 switch (kp->memory) { 429 case V4L2_MEMORY_MMAP: 430 if (get_user(kp->length, &up->length) || 431 get_user(kp->m.offset, &up->m.offset)) 432 return -EFAULT; 433 break; 434 case V4L2_MEMORY_USERPTR: 435 { 436 compat_long_t tmp; 437 438 if (get_user(kp->length, &up->length) || 439 get_user(tmp, &up->m.userptr)) 440 return -EFAULT; 441 442 kp->m.userptr = (unsigned long)compat_ptr(tmp); 443 } 444 break; 445 case V4L2_MEMORY_OVERLAY: 446 if (get_user(kp->m.offset, &up->m.offset)) 447 return -EFAULT; 448 break; 449 } 450 } 451 452 return 0; 453 } 454 455 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 456 { 457 struct v4l2_plane32 __user *uplane32; 458 struct v4l2_plane __user *uplane; 459 compat_caddr_t p; 460 int num_planes; 461 int ret; 462 463 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 464 put_user(kp->index, &up->index) || 465 put_user(kp->type, &up->type) || 466 put_user(kp->flags, &up->flags) || 467 put_user(kp->memory, &up->memory)) 468 return -EFAULT; 469 470 if (put_user(kp->bytesused, &up->bytesused) || 471 put_user(kp->field, &up->field) || 472 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 473 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || 474 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || 475 put_user(kp->sequence, &up->sequence) || 476 put_user(kp->reserved2, &up->reserved2) || 477 put_user(kp->reserved, &up->reserved)) 478 return -EFAULT; 479 480 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 481 num_planes = kp->length; 482 if (num_planes == 0) 483 return 0; 484 485 uplane = kp->m.planes; 486 if (get_user(p, &up->m.planes)) 487 return -EFAULT; 488 uplane32 = compat_ptr(p); 489 490 while (--num_planes >= 0) { 491 ret = put_v4l2_plane32(uplane, uplane32, kp->memory); 492 if (ret) 493 return ret; 494 ++uplane; 495 ++uplane32; 496 } 497 } else { 498 switch (kp->memory) { 499 case V4L2_MEMORY_MMAP: 500 if (put_user(kp->length, &up->length) || 501 put_user(kp->m.offset, &up->m.offset)) 502 return -EFAULT; 503 break; 504 case V4L2_MEMORY_USERPTR: 505 if (put_user(kp->length, &up->length) || 506 put_user(kp->m.userptr, &up->m.userptr)) 507 return -EFAULT; 508 break; 509 case V4L2_MEMORY_OVERLAY: 510 if (put_user(kp->m.offset, &up->m.offset)) 511 return -EFAULT; 512 break; 513 } 514 } 515 516 return 0; 517 } 518 519 struct v4l2_framebuffer32 { 520 __u32 capability; 521 __u32 flags; 522 compat_caddr_t base; 523 struct v4l2_pix_format fmt; 524 }; 525 526 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 527 { 528 u32 tmp; 529 530 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || 531 get_user(tmp, &up->base) || 532 get_user(kp->capability, &up->capability) || 533 get_user(kp->flags, &up->flags)) 534 return -EFAULT; 535 kp->base = compat_ptr(tmp); 536 get_v4l2_pix_format(&kp->fmt, &up->fmt); 537 return 0; 538 } 539 540 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 541 { 542 u32 tmp = (u32)((unsigned long)kp->base); 543 544 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || 545 put_user(tmp, &up->base) || 546 put_user(kp->capability, &up->capability) || 547 put_user(kp->flags, &up->flags)) 548 return -EFAULT; 549 put_v4l2_pix_format(&kp->fmt, &up->fmt); 550 return 0; 551 } 552 553 struct v4l2_input32 { 554 __u32 index; /* Which input */ 555 __u8 name[32]; /* Label */ 556 __u32 type; /* Type of input */ 557 __u32 audioset; /* Associated audios (bitfield) */ 558 __u32 tuner; /* Associated tuner */ 559 v4l2_std_id std; 560 __u32 status; 561 __u32 reserved[4]; 562 } __attribute__ ((packed)); 563 564 /* The 64-bit v4l2_input struct has extra padding at the end of the struct. 565 Otherwise it is identical to the 32-bit version. */ 566 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 567 { 568 if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) 569 return -EFAULT; 570 return 0; 571 } 572 573 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 574 { 575 if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) 576 return -EFAULT; 577 return 0; 578 } 579 580 struct v4l2_ext_controls32 { 581 __u32 ctrl_class; 582 __u32 count; 583 __u32 error_idx; 584 __u32 reserved[2]; 585 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 586 }; 587 588 struct v4l2_ext_control32 { 589 __u32 id; 590 __u32 size; 591 __u32 reserved2[1]; 592 union { 593 __s32 value; 594 __s64 value64; 595 compat_caddr_t string; /* actually char * */ 596 }; 597 } __attribute__ ((packed)); 598 599 /* The following function really belong in v4l2-common, but that causes 600 a circular dependency between modules. We need to think about this, but 601 for now this will do. */ 602 603 /* Return non-zero if this control is a pointer type. Currently only 604 type STRING is a pointer type. */ 605 static inline int ctrl_is_pointer(u32 id) 606 { 607 switch (id) { 608 case V4L2_CID_RDS_TX_PS_NAME: 609 case V4L2_CID_RDS_TX_RADIO_TEXT: 610 return 1; 611 default: 612 return 0; 613 } 614 } 615 616 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 617 { 618 struct v4l2_ext_control32 __user *ucontrols; 619 struct v4l2_ext_control __user *kcontrols; 620 int n; 621 compat_caddr_t p; 622 623 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || 624 get_user(kp->ctrl_class, &up->ctrl_class) || 625 get_user(kp->count, &up->count) || 626 get_user(kp->error_idx, &up->error_idx) || 627 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 628 return -EFAULT; 629 n = kp->count; 630 if (n == 0) { 631 kp->controls = NULL; 632 return 0; 633 } 634 if (get_user(p, &up->controls)) 635 return -EFAULT; 636 ucontrols = compat_ptr(p); 637 if (!access_ok(VERIFY_READ, ucontrols, 638 n * sizeof(struct v4l2_ext_control32))) 639 return -EFAULT; 640 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); 641 kp->controls = kcontrols; 642 while (--n >= 0) { 643 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) 644 return -EFAULT; 645 if (ctrl_is_pointer(kcontrols->id)) { 646 void __user *s; 647 648 if (get_user(p, &ucontrols->string)) 649 return -EFAULT; 650 s = compat_ptr(p); 651 if (put_user(s, &kcontrols->string)) 652 return -EFAULT; 653 } 654 ucontrols++; 655 kcontrols++; 656 } 657 return 0; 658 } 659 660 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 661 { 662 struct v4l2_ext_control32 __user *ucontrols; 663 struct v4l2_ext_control __user *kcontrols = kp->controls; 664 int n = kp->count; 665 compat_caddr_t p; 666 667 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || 668 put_user(kp->ctrl_class, &up->ctrl_class) || 669 put_user(kp->count, &up->count) || 670 put_user(kp->error_idx, &up->error_idx) || 671 copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) 672 return -EFAULT; 673 if (!kp->count) 674 return 0; 675 676 if (get_user(p, &up->controls)) 677 return -EFAULT; 678 ucontrols = compat_ptr(p); 679 if (!access_ok(VERIFY_WRITE, ucontrols, 680 n * sizeof(struct v4l2_ext_control32))) 681 return -EFAULT; 682 683 while (--n >= 0) { 684 unsigned size = sizeof(*ucontrols); 685 686 /* Do not modify the pointer when copying a pointer control. 687 The contents of the pointer was changed, not the pointer 688 itself. */ 689 if (ctrl_is_pointer(kcontrols->id)) 690 size -= sizeof(ucontrols->value64); 691 if (copy_in_user(ucontrols, kcontrols, size)) 692 return -EFAULT; 693 ucontrols++; 694 kcontrols++; 695 } 696 return 0; 697 } 698 699 struct v4l2_event32 { 700 __u32 type; 701 union { 702 __u8 data[64]; 703 } u; 704 __u32 pending; 705 __u32 sequence; 706 struct compat_timespec timestamp; 707 __u32 id; 708 __u32 reserved[8]; 709 }; 710 711 static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) 712 { 713 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || 714 put_user(kp->type, &up->type) || 715 copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || 716 put_user(kp->pending, &up->pending) || 717 put_user(kp->sequence, &up->sequence) || 718 put_compat_timespec(&kp->timestamp, &up->timestamp) || 719 put_user(kp->id, &up->id) || 720 copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) 721 return -EFAULT; 722 return 0; 723 } 724 725 struct v4l2_subdev_edid32 { 726 __u32 pad; 727 __u32 start_block; 728 __u32 blocks; 729 __u32 reserved[5]; 730 compat_caddr_t edid; 731 }; 732 733 static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) 734 { 735 u32 tmp; 736 737 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_subdev_edid32)) || 738 get_user(kp->pad, &up->pad) || 739 get_user(kp->start_block, &up->start_block) || 740 get_user(kp->blocks, &up->blocks) || 741 get_user(tmp, &up->edid) || 742 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 743 return -EFAULT; 744 kp->edid = compat_ptr(tmp); 745 return 0; 746 } 747 748 static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) 749 { 750 u32 tmp = (u32)((unsigned long)kp->edid); 751 752 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_subdev_edid32)) || 753 put_user(kp->pad, &up->pad) || 754 put_user(kp->start_block, &up->start_block) || 755 put_user(kp->blocks, &up->blocks) || 756 put_user(tmp, &up->edid) || 757 copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 758 return -EFAULT; 759 return 0; 760 } 761 762 763 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 764 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 765 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 766 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 767 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 768 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 769 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 770 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 771 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 772 #define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 63, struct v4l2_subdev_edid32) 773 #define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 64, struct v4l2_subdev_edid32) 774 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 775 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 776 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 777 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 778 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 779 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 780 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 781 782 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) 783 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) 784 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) 785 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) 786 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32) 787 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) 788 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) 789 790 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 791 { 792 union { 793 struct v4l2_format v2f; 794 struct v4l2_buffer v2b; 795 struct v4l2_framebuffer v2fb; 796 struct v4l2_input v2i; 797 struct v4l2_standard v2s; 798 struct v4l2_ext_controls v2ecs; 799 struct v4l2_event v2ev; 800 struct v4l2_create_buffers v2crt; 801 struct v4l2_subdev_edid v2edid; 802 unsigned long vx; 803 int vi; 804 } karg; 805 void __user *up = compat_ptr(arg); 806 int compatible_arg = 1; 807 long err = 0; 808 809 /* First, convert the command. */ 810 switch (cmd) { 811 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; 812 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; 813 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; 814 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 815 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 816 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; 817 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; 818 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; 819 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; 820 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; 821 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; 822 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; 823 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; 824 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; 825 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 826 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; 827 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; 828 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 829 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; 830 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break; 831 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; 832 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break; 833 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break; 834 case VIDIOC_SUBDEV_G_EDID32: cmd = VIDIOC_SUBDEV_G_EDID; break; 835 case VIDIOC_SUBDEV_S_EDID32: cmd = VIDIOC_SUBDEV_S_EDID; break; 836 } 837 838 switch (cmd) { 839 case VIDIOC_OVERLAY: 840 case VIDIOC_STREAMON: 841 case VIDIOC_STREAMOFF: 842 case VIDIOC_S_INPUT: 843 case VIDIOC_S_OUTPUT: 844 err = get_user(karg.vi, (s32 __user *)up); 845 compatible_arg = 0; 846 break; 847 848 case VIDIOC_G_INPUT: 849 case VIDIOC_G_OUTPUT: 850 compatible_arg = 0; 851 break; 852 853 case VIDIOC_SUBDEV_G_EDID: 854 case VIDIOC_SUBDEV_S_EDID: 855 err = get_v4l2_subdev_edid32(&karg.v2edid, up); 856 compatible_arg = 0; 857 break; 858 859 case VIDIOC_G_FMT: 860 case VIDIOC_S_FMT: 861 case VIDIOC_TRY_FMT: 862 err = get_v4l2_format32(&karg.v2f, up); 863 compatible_arg = 0; 864 break; 865 866 case VIDIOC_CREATE_BUFS: 867 err = get_v4l2_create32(&karg.v2crt, up); 868 compatible_arg = 0; 869 break; 870 871 case VIDIOC_PREPARE_BUF: 872 case VIDIOC_QUERYBUF: 873 case VIDIOC_QBUF: 874 case VIDIOC_DQBUF: 875 err = get_v4l2_buffer32(&karg.v2b, up); 876 compatible_arg = 0; 877 break; 878 879 case VIDIOC_S_FBUF: 880 err = get_v4l2_framebuffer32(&karg.v2fb, up); 881 compatible_arg = 0; 882 break; 883 884 case VIDIOC_G_FBUF: 885 compatible_arg = 0; 886 break; 887 888 case VIDIOC_ENUMSTD: 889 err = get_v4l2_standard32(&karg.v2s, up); 890 compatible_arg = 0; 891 break; 892 893 case VIDIOC_ENUMINPUT: 894 err = get_v4l2_input32(&karg.v2i, up); 895 compatible_arg = 0; 896 break; 897 898 case VIDIOC_G_EXT_CTRLS: 899 case VIDIOC_S_EXT_CTRLS: 900 case VIDIOC_TRY_EXT_CTRLS: 901 err = get_v4l2_ext_controls32(&karg.v2ecs, up); 902 compatible_arg = 0; 903 break; 904 case VIDIOC_DQEVENT: 905 compatible_arg = 0; 906 break; 907 } 908 if (err) 909 return err; 910 911 if (compatible_arg) 912 err = native_ioctl(file, cmd, (unsigned long)up); 913 else { 914 mm_segment_t old_fs = get_fs(); 915 916 set_fs(KERNEL_DS); 917 err = native_ioctl(file, cmd, (unsigned long)&karg); 918 set_fs(old_fs); 919 } 920 921 /* Special case: even after an error we need to put the 922 results back for these ioctls since the error_idx will 923 contain information on which control failed. */ 924 switch (cmd) { 925 case VIDIOC_G_EXT_CTRLS: 926 case VIDIOC_S_EXT_CTRLS: 927 case VIDIOC_TRY_EXT_CTRLS: 928 if (put_v4l2_ext_controls32(&karg.v2ecs, up)) 929 err = -EFAULT; 930 break; 931 } 932 if (err) 933 return err; 934 935 switch (cmd) { 936 case VIDIOC_S_INPUT: 937 case VIDIOC_S_OUTPUT: 938 case VIDIOC_G_INPUT: 939 case VIDIOC_G_OUTPUT: 940 err = put_user(((s32)karg.vi), (s32 __user *)up); 941 break; 942 943 case VIDIOC_G_FBUF: 944 err = put_v4l2_framebuffer32(&karg.v2fb, up); 945 break; 946 947 case VIDIOC_DQEVENT: 948 err = put_v4l2_event32(&karg.v2ev, up); 949 break; 950 951 case VIDIOC_SUBDEV_G_EDID: 952 case VIDIOC_SUBDEV_S_EDID: 953 err = put_v4l2_subdev_edid32(&karg.v2edid, up); 954 break; 955 956 case VIDIOC_G_FMT: 957 case VIDIOC_S_FMT: 958 case VIDIOC_TRY_FMT: 959 err = put_v4l2_format32(&karg.v2f, up); 960 break; 961 962 case VIDIOC_CREATE_BUFS: 963 err = put_v4l2_create32(&karg.v2crt, up); 964 break; 965 966 case VIDIOC_QUERYBUF: 967 case VIDIOC_QBUF: 968 case VIDIOC_DQBUF: 969 err = put_v4l2_buffer32(&karg.v2b, up); 970 break; 971 972 case VIDIOC_ENUMSTD: 973 err = put_v4l2_standard32(&karg.v2s, up); 974 break; 975 976 case VIDIOC_ENUMINPUT: 977 err = put_v4l2_input32(&karg.v2i, up); 978 break; 979 } 980 return err; 981 } 982 983 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 984 { 985 struct video_device *vdev = video_devdata(file); 986 long ret = -ENOIOCTLCMD; 987 988 if (!file->f_op->unlocked_ioctl) 989 return ret; 990 991 switch (cmd) { 992 case VIDIOC_QUERYCAP: 993 case VIDIOC_RESERVED: 994 case VIDIOC_ENUM_FMT: 995 case VIDIOC_G_FMT32: 996 case VIDIOC_S_FMT32: 997 case VIDIOC_REQBUFS: 998 case VIDIOC_QUERYBUF32: 999 case VIDIOC_G_FBUF32: 1000 case VIDIOC_S_FBUF32: 1001 case VIDIOC_OVERLAY32: 1002 case VIDIOC_QBUF32: 1003 case VIDIOC_DQBUF32: 1004 case VIDIOC_STREAMON32: 1005 case VIDIOC_STREAMOFF32: 1006 case VIDIOC_G_PARM: 1007 case VIDIOC_S_PARM: 1008 case VIDIOC_G_STD: 1009 case VIDIOC_S_STD: 1010 case VIDIOC_ENUMSTD32: 1011 case VIDIOC_ENUMINPUT32: 1012 case VIDIOC_G_CTRL: 1013 case VIDIOC_S_CTRL: 1014 case VIDIOC_G_TUNER: 1015 case VIDIOC_S_TUNER: 1016 case VIDIOC_G_AUDIO: 1017 case VIDIOC_S_AUDIO: 1018 case VIDIOC_QUERYCTRL: 1019 case VIDIOC_QUERYMENU: 1020 case VIDIOC_G_INPUT32: 1021 case VIDIOC_S_INPUT32: 1022 case VIDIOC_G_OUTPUT32: 1023 case VIDIOC_S_OUTPUT32: 1024 case VIDIOC_ENUMOUTPUT: 1025 case VIDIOC_G_AUDOUT: 1026 case VIDIOC_S_AUDOUT: 1027 case VIDIOC_G_MODULATOR: 1028 case VIDIOC_S_MODULATOR: 1029 case VIDIOC_S_FREQUENCY: 1030 case VIDIOC_G_FREQUENCY: 1031 case VIDIOC_CROPCAP: 1032 case VIDIOC_G_CROP: 1033 case VIDIOC_S_CROP: 1034 case VIDIOC_G_SELECTION: 1035 case VIDIOC_S_SELECTION: 1036 case VIDIOC_G_JPEGCOMP: 1037 case VIDIOC_S_JPEGCOMP: 1038 case VIDIOC_QUERYSTD: 1039 case VIDIOC_TRY_FMT32: 1040 case VIDIOC_ENUMAUDIO: 1041 case VIDIOC_ENUMAUDOUT: 1042 case VIDIOC_G_PRIORITY: 1043 case VIDIOC_S_PRIORITY: 1044 case VIDIOC_G_SLICED_VBI_CAP: 1045 case VIDIOC_LOG_STATUS: 1046 case VIDIOC_G_EXT_CTRLS32: 1047 case VIDIOC_S_EXT_CTRLS32: 1048 case VIDIOC_TRY_EXT_CTRLS32: 1049 case VIDIOC_ENUM_FRAMESIZES: 1050 case VIDIOC_ENUM_FRAMEINTERVALS: 1051 case VIDIOC_G_ENC_INDEX: 1052 case VIDIOC_ENCODER_CMD: 1053 case VIDIOC_TRY_ENCODER_CMD: 1054 case VIDIOC_DECODER_CMD: 1055 case VIDIOC_TRY_DECODER_CMD: 1056 case VIDIOC_DBG_S_REGISTER: 1057 case VIDIOC_DBG_G_REGISTER: 1058 case VIDIOC_DBG_G_CHIP_IDENT: 1059 case VIDIOC_S_HW_FREQ_SEEK: 1060 case VIDIOC_ENUM_DV_PRESETS: 1061 case VIDIOC_S_DV_PRESET: 1062 case VIDIOC_G_DV_PRESET: 1063 case VIDIOC_QUERY_DV_PRESET: 1064 case VIDIOC_S_DV_TIMINGS: 1065 case VIDIOC_G_DV_TIMINGS: 1066 case VIDIOC_DQEVENT: 1067 case VIDIOC_DQEVENT32: 1068 case VIDIOC_SUBSCRIBE_EVENT: 1069 case VIDIOC_UNSUBSCRIBE_EVENT: 1070 case VIDIOC_CREATE_BUFS32: 1071 case VIDIOC_PREPARE_BUF32: 1072 case VIDIOC_ENUM_DV_TIMINGS: 1073 case VIDIOC_QUERY_DV_TIMINGS: 1074 case VIDIOC_DV_TIMINGS_CAP: 1075 case VIDIOC_ENUM_FREQ_BANDS: 1076 case VIDIOC_SUBDEV_G_EDID32: 1077 case VIDIOC_SUBDEV_S_EDID32: 1078 ret = do_video_ioctl(file, cmd, arg); 1079 break; 1080 1081 default: 1082 if (vdev->fops->compat_ioctl32) 1083 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1084 1085 if (ret == -ENOIOCTLCMD) 1086 printk(KERN_WARNING "compat_ioctl32: " 1087 "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1088 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), 1089 cmd); 1090 break; 1091 } 1092 return ret; 1093 } 1094 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1095