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 __s32 fd; 301 } m; 302 __u32 data_offset; 303 __u32 reserved[11]; 304 }; 305 306 struct v4l2_buffer32 { 307 __u32 index; 308 __u32 type; /* enum v4l2_buf_type */ 309 __u32 bytesused; 310 __u32 flags; 311 __u32 field; /* enum v4l2_field */ 312 struct compat_timeval timestamp; 313 struct v4l2_timecode timecode; 314 __u32 sequence; 315 316 /* memory location */ 317 __u32 memory; /* enum v4l2_memory */ 318 union { 319 __u32 offset; 320 compat_long_t userptr; 321 compat_caddr_t planes; 322 __s32 fd; 323 } m; 324 __u32 length; 325 __u32 reserved2; 326 __u32 reserved; 327 }; 328 329 static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, 330 enum v4l2_memory memory) 331 { 332 void __user *up_pln; 333 compat_long_t p; 334 335 if (copy_in_user(up, up32, 2 * sizeof(__u32)) || 336 copy_in_user(&up->data_offset, &up32->data_offset, 337 sizeof(__u32))) 338 return -EFAULT; 339 340 if (memory == V4L2_MEMORY_USERPTR) { 341 if (get_user(p, &up32->m.userptr)) 342 return -EFAULT; 343 up_pln = compat_ptr(p); 344 if (put_user((unsigned long)up_pln, &up->m.userptr)) 345 return -EFAULT; 346 } else if (memory == V4L2_MEMORY_DMABUF) { 347 if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int))) 348 return -EFAULT; 349 } else { 350 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, 351 sizeof(__u32))) 352 return -EFAULT; 353 } 354 355 return 0; 356 } 357 358 static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, 359 enum v4l2_memory memory) 360 { 361 if (copy_in_user(up32, up, 2 * sizeof(__u32)) || 362 copy_in_user(&up32->data_offset, &up->data_offset, 363 sizeof(__u32))) 364 return -EFAULT; 365 366 /* For MMAP, driver might've set up the offset, so copy it back. 367 * USERPTR stays the same (was userspace-provided), so no copying. */ 368 if (memory == V4L2_MEMORY_MMAP) 369 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, 370 sizeof(__u32))) 371 return -EFAULT; 372 /* For DMABUF, driver might've set up the fd, so copy it back. */ 373 if (memory == V4L2_MEMORY_DMABUF) 374 if (copy_in_user(&up32->m.fd, &up->m.fd, 375 sizeof(int))) 376 return -EFAULT; 377 378 return 0; 379 } 380 381 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 382 { 383 struct v4l2_plane32 __user *uplane32; 384 struct v4l2_plane __user *uplane; 385 compat_caddr_t p; 386 int num_planes; 387 int ret; 388 389 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 390 get_user(kp->index, &up->index) || 391 get_user(kp->type, &up->type) || 392 get_user(kp->flags, &up->flags) || 393 get_user(kp->memory, &up->memory)) 394 return -EFAULT; 395 396 if (V4L2_TYPE_IS_OUTPUT(kp->type)) 397 if (get_user(kp->bytesused, &up->bytesused) || 398 get_user(kp->field, &up->field) || 399 get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 400 get_user(kp->timestamp.tv_usec, 401 &up->timestamp.tv_usec)) 402 return -EFAULT; 403 404 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 405 if (get_user(kp->length, &up->length)) 406 return -EFAULT; 407 408 num_planes = kp->length; 409 if (num_planes == 0) { 410 kp->m.planes = NULL; 411 /* num_planes == 0 is legal, e.g. when userspace doesn't 412 * need planes array on DQBUF*/ 413 return 0; 414 } 415 416 if (get_user(p, &up->m.planes)) 417 return -EFAULT; 418 419 uplane32 = compat_ptr(p); 420 if (!access_ok(VERIFY_READ, uplane32, 421 num_planes * sizeof(struct v4l2_plane32))) 422 return -EFAULT; 423 424 /* We don't really care if userspace decides to kill itself 425 * by passing a very big num_planes value */ 426 uplane = compat_alloc_user_space(num_planes * 427 sizeof(struct v4l2_plane)); 428 kp->m.planes = uplane; 429 430 while (--num_planes >= 0) { 431 ret = get_v4l2_plane32(uplane, uplane32, kp->memory); 432 if (ret) 433 return ret; 434 ++uplane; 435 ++uplane32; 436 } 437 } else { 438 switch (kp->memory) { 439 case V4L2_MEMORY_MMAP: 440 if (get_user(kp->length, &up->length) || 441 get_user(kp->m.offset, &up->m.offset)) 442 return -EFAULT; 443 break; 444 case V4L2_MEMORY_USERPTR: 445 { 446 compat_long_t tmp; 447 448 if (get_user(kp->length, &up->length) || 449 get_user(tmp, &up->m.userptr)) 450 return -EFAULT; 451 452 kp->m.userptr = (unsigned long)compat_ptr(tmp); 453 } 454 break; 455 case V4L2_MEMORY_OVERLAY: 456 if (get_user(kp->m.offset, &up->m.offset)) 457 return -EFAULT; 458 break; 459 case V4L2_MEMORY_DMABUF: 460 if (get_user(kp->m.fd, &up->m.fd)) 461 return -EFAULT; 462 break; 463 } 464 } 465 466 return 0; 467 } 468 469 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 470 { 471 struct v4l2_plane32 __user *uplane32; 472 struct v4l2_plane __user *uplane; 473 compat_caddr_t p; 474 int num_planes; 475 int ret; 476 477 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 478 put_user(kp->index, &up->index) || 479 put_user(kp->type, &up->type) || 480 put_user(kp->flags, &up->flags) || 481 put_user(kp->memory, &up->memory)) 482 return -EFAULT; 483 484 if (put_user(kp->bytesused, &up->bytesused) || 485 put_user(kp->field, &up->field) || 486 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 487 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || 488 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || 489 put_user(kp->sequence, &up->sequence) || 490 put_user(kp->reserved2, &up->reserved2) || 491 put_user(kp->reserved, &up->reserved)) 492 return -EFAULT; 493 494 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 495 num_planes = kp->length; 496 if (num_planes == 0) 497 return 0; 498 499 uplane = kp->m.planes; 500 if (get_user(p, &up->m.planes)) 501 return -EFAULT; 502 uplane32 = compat_ptr(p); 503 504 while (--num_planes >= 0) { 505 ret = put_v4l2_plane32(uplane, uplane32, kp->memory); 506 if (ret) 507 return ret; 508 ++uplane; 509 ++uplane32; 510 } 511 } else { 512 switch (kp->memory) { 513 case V4L2_MEMORY_MMAP: 514 if (put_user(kp->length, &up->length) || 515 put_user(kp->m.offset, &up->m.offset)) 516 return -EFAULT; 517 break; 518 case V4L2_MEMORY_USERPTR: 519 if (put_user(kp->length, &up->length) || 520 put_user(kp->m.userptr, &up->m.userptr)) 521 return -EFAULT; 522 break; 523 case V4L2_MEMORY_OVERLAY: 524 if (put_user(kp->m.offset, &up->m.offset)) 525 return -EFAULT; 526 break; 527 case V4L2_MEMORY_DMABUF: 528 if (put_user(kp->m.fd, &up->m.fd)) 529 return -EFAULT; 530 break; 531 } 532 } 533 534 return 0; 535 } 536 537 struct v4l2_framebuffer32 { 538 __u32 capability; 539 __u32 flags; 540 compat_caddr_t base; 541 struct v4l2_pix_format fmt; 542 }; 543 544 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 545 { 546 u32 tmp; 547 548 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || 549 get_user(tmp, &up->base) || 550 get_user(kp->capability, &up->capability) || 551 get_user(kp->flags, &up->flags)) 552 return -EFAULT; 553 kp->base = compat_ptr(tmp); 554 get_v4l2_pix_format(&kp->fmt, &up->fmt); 555 return 0; 556 } 557 558 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 559 { 560 u32 tmp = (u32)((unsigned long)kp->base); 561 562 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || 563 put_user(tmp, &up->base) || 564 put_user(kp->capability, &up->capability) || 565 put_user(kp->flags, &up->flags)) 566 return -EFAULT; 567 put_v4l2_pix_format(&kp->fmt, &up->fmt); 568 return 0; 569 } 570 571 struct v4l2_input32 { 572 __u32 index; /* Which input */ 573 __u8 name[32]; /* Label */ 574 __u32 type; /* Type of input */ 575 __u32 audioset; /* Associated audios (bitfield) */ 576 __u32 tuner; /* Associated tuner */ 577 v4l2_std_id std; 578 __u32 status; 579 __u32 reserved[4]; 580 } __attribute__ ((packed)); 581 582 /* The 64-bit v4l2_input struct has extra padding at the end of the struct. 583 Otherwise it is identical to the 32-bit version. */ 584 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 585 { 586 if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) 587 return -EFAULT; 588 return 0; 589 } 590 591 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 592 { 593 if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) 594 return -EFAULT; 595 return 0; 596 } 597 598 struct v4l2_ext_controls32 { 599 __u32 ctrl_class; 600 __u32 count; 601 __u32 error_idx; 602 __u32 reserved[2]; 603 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 604 }; 605 606 struct v4l2_ext_control32 { 607 __u32 id; 608 __u32 size; 609 __u32 reserved2[1]; 610 union { 611 __s32 value; 612 __s64 value64; 613 compat_caddr_t string; /* actually char * */ 614 }; 615 } __attribute__ ((packed)); 616 617 /* The following function really belong in v4l2-common, but that causes 618 a circular dependency between modules. We need to think about this, but 619 for now this will do. */ 620 621 /* Return non-zero if this control is a pointer type. Currently only 622 type STRING is a pointer type. */ 623 static inline int ctrl_is_pointer(u32 id) 624 { 625 switch (id) { 626 case V4L2_CID_RDS_TX_PS_NAME: 627 case V4L2_CID_RDS_TX_RADIO_TEXT: 628 return 1; 629 default: 630 return 0; 631 } 632 } 633 634 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 635 { 636 struct v4l2_ext_control32 __user *ucontrols; 637 struct v4l2_ext_control __user *kcontrols; 638 int n; 639 compat_caddr_t p; 640 641 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || 642 get_user(kp->ctrl_class, &up->ctrl_class) || 643 get_user(kp->count, &up->count) || 644 get_user(kp->error_idx, &up->error_idx) || 645 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 646 return -EFAULT; 647 n = kp->count; 648 if (n == 0) { 649 kp->controls = NULL; 650 return 0; 651 } 652 if (get_user(p, &up->controls)) 653 return -EFAULT; 654 ucontrols = compat_ptr(p); 655 if (!access_ok(VERIFY_READ, ucontrols, 656 n * sizeof(struct v4l2_ext_control32))) 657 return -EFAULT; 658 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); 659 kp->controls = kcontrols; 660 while (--n >= 0) { 661 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) 662 return -EFAULT; 663 if (ctrl_is_pointer(kcontrols->id)) { 664 void __user *s; 665 666 if (get_user(p, &ucontrols->string)) 667 return -EFAULT; 668 s = compat_ptr(p); 669 if (put_user(s, &kcontrols->string)) 670 return -EFAULT; 671 } 672 ucontrols++; 673 kcontrols++; 674 } 675 return 0; 676 } 677 678 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 679 { 680 struct v4l2_ext_control32 __user *ucontrols; 681 struct v4l2_ext_control __user *kcontrols = kp->controls; 682 int n = kp->count; 683 compat_caddr_t p; 684 685 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || 686 put_user(kp->ctrl_class, &up->ctrl_class) || 687 put_user(kp->count, &up->count) || 688 put_user(kp->error_idx, &up->error_idx) || 689 copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) 690 return -EFAULT; 691 if (!kp->count) 692 return 0; 693 694 if (get_user(p, &up->controls)) 695 return -EFAULT; 696 ucontrols = compat_ptr(p); 697 if (!access_ok(VERIFY_WRITE, ucontrols, 698 n * sizeof(struct v4l2_ext_control32))) 699 return -EFAULT; 700 701 while (--n >= 0) { 702 unsigned size = sizeof(*ucontrols); 703 704 /* Do not modify the pointer when copying a pointer control. 705 The contents of the pointer was changed, not the pointer 706 itself. */ 707 if (ctrl_is_pointer(kcontrols->id)) 708 size -= sizeof(ucontrols->value64); 709 if (copy_in_user(ucontrols, kcontrols, size)) 710 return -EFAULT; 711 ucontrols++; 712 kcontrols++; 713 } 714 return 0; 715 } 716 717 struct v4l2_event32 { 718 __u32 type; 719 union { 720 __u8 data[64]; 721 } u; 722 __u32 pending; 723 __u32 sequence; 724 struct compat_timespec timestamp; 725 __u32 id; 726 __u32 reserved[8]; 727 }; 728 729 static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) 730 { 731 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || 732 put_user(kp->type, &up->type) || 733 copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || 734 put_user(kp->pending, &up->pending) || 735 put_user(kp->sequence, &up->sequence) || 736 put_compat_timespec(&kp->timestamp, &up->timestamp) || 737 put_user(kp->id, &up->id) || 738 copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) 739 return -EFAULT; 740 return 0; 741 } 742 743 struct v4l2_subdev_edid32 { 744 __u32 pad; 745 __u32 start_block; 746 __u32 blocks; 747 __u32 reserved[5]; 748 compat_caddr_t edid; 749 }; 750 751 static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) 752 { 753 u32 tmp; 754 755 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_subdev_edid32)) || 756 get_user(kp->pad, &up->pad) || 757 get_user(kp->start_block, &up->start_block) || 758 get_user(kp->blocks, &up->blocks) || 759 get_user(tmp, &up->edid) || 760 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 761 return -EFAULT; 762 kp->edid = compat_ptr(tmp); 763 return 0; 764 } 765 766 static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) 767 { 768 u32 tmp = (u32)((unsigned long)kp->edid); 769 770 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_subdev_edid32)) || 771 put_user(kp->pad, &up->pad) || 772 put_user(kp->start_block, &up->start_block) || 773 put_user(kp->blocks, &up->blocks) || 774 put_user(tmp, &up->edid) || 775 copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 776 return -EFAULT; 777 return 0; 778 } 779 780 781 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 782 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 783 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 784 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 785 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 786 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 787 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 788 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 789 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 790 #define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 63, struct v4l2_subdev_edid32) 791 #define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 64, struct v4l2_subdev_edid32) 792 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 793 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 794 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 795 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 796 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 797 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 798 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 799 800 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) 801 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) 802 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) 803 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) 804 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32) 805 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) 806 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) 807 808 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 809 { 810 union { 811 struct v4l2_format v2f; 812 struct v4l2_buffer v2b; 813 struct v4l2_framebuffer v2fb; 814 struct v4l2_input v2i; 815 struct v4l2_standard v2s; 816 struct v4l2_ext_controls v2ecs; 817 struct v4l2_event v2ev; 818 struct v4l2_create_buffers v2crt; 819 struct v4l2_subdev_edid v2edid; 820 unsigned long vx; 821 int vi; 822 } karg; 823 void __user *up = compat_ptr(arg); 824 int compatible_arg = 1; 825 long err = 0; 826 827 /* First, convert the command. */ 828 switch (cmd) { 829 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; 830 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; 831 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; 832 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 833 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 834 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; 835 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; 836 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; 837 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; 838 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; 839 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; 840 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; 841 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; 842 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; 843 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 844 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; 845 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; 846 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 847 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; 848 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break; 849 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; 850 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break; 851 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break; 852 case VIDIOC_SUBDEV_G_EDID32: cmd = VIDIOC_SUBDEV_G_EDID; break; 853 case VIDIOC_SUBDEV_S_EDID32: cmd = VIDIOC_SUBDEV_S_EDID; break; 854 } 855 856 switch (cmd) { 857 case VIDIOC_OVERLAY: 858 case VIDIOC_STREAMON: 859 case VIDIOC_STREAMOFF: 860 case VIDIOC_S_INPUT: 861 case VIDIOC_S_OUTPUT: 862 err = get_user(karg.vi, (s32 __user *)up); 863 compatible_arg = 0; 864 break; 865 866 case VIDIOC_G_INPUT: 867 case VIDIOC_G_OUTPUT: 868 compatible_arg = 0; 869 break; 870 871 case VIDIOC_SUBDEV_G_EDID: 872 case VIDIOC_SUBDEV_S_EDID: 873 err = get_v4l2_subdev_edid32(&karg.v2edid, up); 874 compatible_arg = 0; 875 break; 876 877 case VIDIOC_G_FMT: 878 case VIDIOC_S_FMT: 879 case VIDIOC_TRY_FMT: 880 err = get_v4l2_format32(&karg.v2f, up); 881 compatible_arg = 0; 882 break; 883 884 case VIDIOC_CREATE_BUFS: 885 err = get_v4l2_create32(&karg.v2crt, up); 886 compatible_arg = 0; 887 break; 888 889 case VIDIOC_PREPARE_BUF: 890 case VIDIOC_QUERYBUF: 891 case VIDIOC_QBUF: 892 case VIDIOC_DQBUF: 893 err = get_v4l2_buffer32(&karg.v2b, up); 894 compatible_arg = 0; 895 break; 896 897 case VIDIOC_S_FBUF: 898 err = get_v4l2_framebuffer32(&karg.v2fb, up); 899 compatible_arg = 0; 900 break; 901 902 case VIDIOC_G_FBUF: 903 compatible_arg = 0; 904 break; 905 906 case VIDIOC_ENUMSTD: 907 err = get_v4l2_standard32(&karg.v2s, up); 908 compatible_arg = 0; 909 break; 910 911 case VIDIOC_ENUMINPUT: 912 err = get_v4l2_input32(&karg.v2i, up); 913 compatible_arg = 0; 914 break; 915 916 case VIDIOC_G_EXT_CTRLS: 917 case VIDIOC_S_EXT_CTRLS: 918 case VIDIOC_TRY_EXT_CTRLS: 919 err = get_v4l2_ext_controls32(&karg.v2ecs, up); 920 compatible_arg = 0; 921 break; 922 case VIDIOC_DQEVENT: 923 compatible_arg = 0; 924 break; 925 } 926 if (err) 927 return err; 928 929 if (compatible_arg) 930 err = native_ioctl(file, cmd, (unsigned long)up); 931 else { 932 mm_segment_t old_fs = get_fs(); 933 934 set_fs(KERNEL_DS); 935 err = native_ioctl(file, cmd, (unsigned long)&karg); 936 set_fs(old_fs); 937 } 938 939 /* Special case: even after an error we need to put the 940 results back for these ioctls since the error_idx will 941 contain information on which control failed. */ 942 switch (cmd) { 943 case VIDIOC_G_EXT_CTRLS: 944 case VIDIOC_S_EXT_CTRLS: 945 case VIDIOC_TRY_EXT_CTRLS: 946 if (put_v4l2_ext_controls32(&karg.v2ecs, up)) 947 err = -EFAULT; 948 break; 949 } 950 if (err) 951 return err; 952 953 switch (cmd) { 954 case VIDIOC_S_INPUT: 955 case VIDIOC_S_OUTPUT: 956 case VIDIOC_G_INPUT: 957 case VIDIOC_G_OUTPUT: 958 err = put_user(((s32)karg.vi), (s32 __user *)up); 959 break; 960 961 case VIDIOC_G_FBUF: 962 err = put_v4l2_framebuffer32(&karg.v2fb, up); 963 break; 964 965 case VIDIOC_DQEVENT: 966 err = put_v4l2_event32(&karg.v2ev, up); 967 break; 968 969 case VIDIOC_SUBDEV_G_EDID: 970 case VIDIOC_SUBDEV_S_EDID: 971 err = put_v4l2_subdev_edid32(&karg.v2edid, up); 972 break; 973 974 case VIDIOC_G_FMT: 975 case VIDIOC_S_FMT: 976 case VIDIOC_TRY_FMT: 977 err = put_v4l2_format32(&karg.v2f, up); 978 break; 979 980 case VIDIOC_CREATE_BUFS: 981 err = put_v4l2_create32(&karg.v2crt, up); 982 break; 983 984 case VIDIOC_QUERYBUF: 985 case VIDIOC_QBUF: 986 case VIDIOC_DQBUF: 987 err = put_v4l2_buffer32(&karg.v2b, up); 988 break; 989 990 case VIDIOC_ENUMSTD: 991 err = put_v4l2_standard32(&karg.v2s, up); 992 break; 993 994 case VIDIOC_ENUMINPUT: 995 err = put_v4l2_input32(&karg.v2i, up); 996 break; 997 } 998 return err; 999 } 1000 1001 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 1002 { 1003 struct video_device *vdev = video_devdata(file); 1004 long ret = -ENOIOCTLCMD; 1005 1006 if (!file->f_op->unlocked_ioctl) 1007 return ret; 1008 1009 switch (cmd) { 1010 case VIDIOC_QUERYCAP: 1011 case VIDIOC_RESERVED: 1012 case VIDIOC_ENUM_FMT: 1013 case VIDIOC_G_FMT32: 1014 case VIDIOC_S_FMT32: 1015 case VIDIOC_REQBUFS: 1016 case VIDIOC_QUERYBUF32: 1017 case VIDIOC_G_FBUF32: 1018 case VIDIOC_S_FBUF32: 1019 case VIDIOC_OVERLAY32: 1020 case VIDIOC_QBUF32: 1021 case VIDIOC_EXPBUF: 1022 case VIDIOC_DQBUF32: 1023 case VIDIOC_STREAMON32: 1024 case VIDIOC_STREAMOFF32: 1025 case VIDIOC_G_PARM: 1026 case VIDIOC_S_PARM: 1027 case VIDIOC_G_STD: 1028 case VIDIOC_S_STD: 1029 case VIDIOC_ENUMSTD32: 1030 case VIDIOC_ENUMINPUT32: 1031 case VIDIOC_G_CTRL: 1032 case VIDIOC_S_CTRL: 1033 case VIDIOC_G_TUNER: 1034 case VIDIOC_S_TUNER: 1035 case VIDIOC_G_AUDIO: 1036 case VIDIOC_S_AUDIO: 1037 case VIDIOC_QUERYCTRL: 1038 case VIDIOC_QUERYMENU: 1039 case VIDIOC_G_INPUT32: 1040 case VIDIOC_S_INPUT32: 1041 case VIDIOC_G_OUTPUT32: 1042 case VIDIOC_S_OUTPUT32: 1043 case VIDIOC_ENUMOUTPUT: 1044 case VIDIOC_G_AUDOUT: 1045 case VIDIOC_S_AUDOUT: 1046 case VIDIOC_G_MODULATOR: 1047 case VIDIOC_S_MODULATOR: 1048 case VIDIOC_S_FREQUENCY: 1049 case VIDIOC_G_FREQUENCY: 1050 case VIDIOC_CROPCAP: 1051 case VIDIOC_G_CROP: 1052 case VIDIOC_S_CROP: 1053 case VIDIOC_G_SELECTION: 1054 case VIDIOC_S_SELECTION: 1055 case VIDIOC_G_JPEGCOMP: 1056 case VIDIOC_S_JPEGCOMP: 1057 case VIDIOC_QUERYSTD: 1058 case VIDIOC_TRY_FMT32: 1059 case VIDIOC_ENUMAUDIO: 1060 case VIDIOC_ENUMAUDOUT: 1061 case VIDIOC_G_PRIORITY: 1062 case VIDIOC_S_PRIORITY: 1063 case VIDIOC_G_SLICED_VBI_CAP: 1064 case VIDIOC_LOG_STATUS: 1065 case VIDIOC_G_EXT_CTRLS32: 1066 case VIDIOC_S_EXT_CTRLS32: 1067 case VIDIOC_TRY_EXT_CTRLS32: 1068 case VIDIOC_ENUM_FRAMESIZES: 1069 case VIDIOC_ENUM_FRAMEINTERVALS: 1070 case VIDIOC_G_ENC_INDEX: 1071 case VIDIOC_ENCODER_CMD: 1072 case VIDIOC_TRY_ENCODER_CMD: 1073 case VIDIOC_DECODER_CMD: 1074 case VIDIOC_TRY_DECODER_CMD: 1075 case VIDIOC_DBG_S_REGISTER: 1076 case VIDIOC_DBG_G_REGISTER: 1077 case VIDIOC_S_HW_FREQ_SEEK: 1078 case VIDIOC_S_DV_TIMINGS: 1079 case VIDIOC_G_DV_TIMINGS: 1080 case VIDIOC_DQEVENT: 1081 case VIDIOC_DQEVENT32: 1082 case VIDIOC_SUBSCRIBE_EVENT: 1083 case VIDIOC_UNSUBSCRIBE_EVENT: 1084 case VIDIOC_CREATE_BUFS32: 1085 case VIDIOC_PREPARE_BUF32: 1086 case VIDIOC_ENUM_DV_TIMINGS: 1087 case VIDIOC_QUERY_DV_TIMINGS: 1088 case VIDIOC_DV_TIMINGS_CAP: 1089 case VIDIOC_ENUM_FREQ_BANDS: 1090 case VIDIOC_SUBDEV_G_EDID32: 1091 case VIDIOC_SUBDEV_S_EDID32: 1092 ret = do_video_ioctl(file, cmd, arg); 1093 break; 1094 1095 default: 1096 if (vdev->fops->compat_ioctl32) 1097 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1098 1099 if (ret == -ENOIOCTLCMD) 1100 printk(KERN_WARNING "compat_ioctl32: " 1101 "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1102 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), 1103 cmd); 1104 break; 1105 } 1106 return ret; 1107 } 1108 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1109