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 if (get_user(kp->type, &up->type)) 182 return -EFAULT; 183 184 switch (kp->type) { 185 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 186 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 187 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 188 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 189 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 190 return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, 191 &up->fmt.pix_mp); 192 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 193 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 194 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); 195 case V4L2_BUF_TYPE_VBI_CAPTURE: 196 case V4L2_BUF_TYPE_VBI_OUTPUT: 197 return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 198 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 199 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 200 return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); 201 default: 202 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", 203 kp->type); 204 return -EINVAL; 205 } 206 } 207 208 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 209 { 210 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) 211 return -EFAULT; 212 return __get_v4l2_format32(kp, up); 213 } 214 215 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) 216 { 217 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || 218 copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) 219 return -EFAULT; 220 return __get_v4l2_format32(&kp->format, &up->format); 221 } 222 223 static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 224 { 225 if (put_user(kp->type, &up->type)) 226 return -EFAULT; 227 228 switch (kp->type) { 229 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 230 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 231 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 232 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 233 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 234 return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp, 235 &up->fmt.pix_mp); 236 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 237 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 238 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); 239 case V4L2_BUF_TYPE_VBI_CAPTURE: 240 case V4L2_BUF_TYPE_VBI_OUTPUT: 241 return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 242 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 243 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 244 return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); 245 default: 246 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", 247 kp->type); 248 return -EINVAL; 249 } 250 } 251 252 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 253 { 254 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32))) 255 return -EFAULT; 256 return __put_v4l2_format32(kp, up); 257 } 258 259 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) 260 { 261 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || 262 copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format))) 263 return -EFAULT; 264 return __put_v4l2_format32(&kp->format, &up->format); 265 } 266 267 struct v4l2_standard32 { 268 __u32 index; 269 __u32 id[2]; /* __u64 would get the alignment wrong */ 270 __u8 name[24]; 271 struct v4l2_fract frameperiod; /* Frames, not fields */ 272 __u32 framelines; 273 __u32 reserved[4]; 274 }; 275 276 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 277 { 278 /* other fields are not set by the user, nor used by the driver */ 279 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || 280 get_user(kp->index, &up->index)) 281 return -EFAULT; 282 return 0; 283 } 284 285 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 286 { 287 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || 288 put_user(kp->index, &up->index) || 289 copy_to_user(up->id, &kp->id, sizeof(__u64)) || 290 copy_to_user(up->name, kp->name, 24) || 291 copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || 292 put_user(kp->framelines, &up->framelines) || 293 copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) 294 return -EFAULT; 295 return 0; 296 } 297 298 struct v4l2_plane32 { 299 __u32 bytesused; 300 __u32 length; 301 union { 302 __u32 mem_offset; 303 compat_long_t userptr; 304 __s32 fd; 305 } m; 306 __u32 data_offset; 307 __u32 reserved[11]; 308 }; 309 310 struct v4l2_buffer32 { 311 __u32 index; 312 __u32 type; /* enum v4l2_buf_type */ 313 __u32 bytesused; 314 __u32 flags; 315 __u32 field; /* enum v4l2_field */ 316 struct compat_timeval timestamp; 317 struct v4l2_timecode timecode; 318 __u32 sequence; 319 320 /* memory location */ 321 __u32 memory; /* enum v4l2_memory */ 322 union { 323 __u32 offset; 324 compat_long_t userptr; 325 compat_caddr_t planes; 326 __s32 fd; 327 } m; 328 __u32 length; 329 __u32 reserved2; 330 __u32 reserved; 331 }; 332 333 static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, 334 enum v4l2_memory memory) 335 { 336 void __user *up_pln; 337 compat_long_t p; 338 339 if (copy_in_user(up, up32, 2 * sizeof(__u32)) || 340 copy_in_user(&up->data_offset, &up32->data_offset, 341 sizeof(__u32))) 342 return -EFAULT; 343 344 if (memory == V4L2_MEMORY_USERPTR) { 345 if (get_user(p, &up32->m.userptr)) 346 return -EFAULT; 347 up_pln = compat_ptr(p); 348 if (put_user((unsigned long)up_pln, &up->m.userptr)) 349 return -EFAULT; 350 } else if (memory == V4L2_MEMORY_DMABUF) { 351 if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int))) 352 return -EFAULT; 353 } else { 354 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, 355 sizeof(__u32))) 356 return -EFAULT; 357 } 358 359 return 0; 360 } 361 362 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, 363 enum v4l2_memory memory) 364 { 365 if (copy_in_user(up32, up, 2 * sizeof(__u32)) || 366 copy_in_user(&up32->data_offset, &up->data_offset, 367 sizeof(__u32))) 368 return -EFAULT; 369 370 /* For MMAP, driver might've set up the offset, so copy it back. 371 * USERPTR stays the same (was userspace-provided), so no copying. */ 372 if (memory == V4L2_MEMORY_MMAP) 373 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, 374 sizeof(__u32))) 375 return -EFAULT; 376 /* For DMABUF, driver might've set up the fd, so copy it back. */ 377 if (memory == V4L2_MEMORY_DMABUF) 378 if (copy_in_user(&up32->m.fd, &up->m.fd, 379 sizeof(int))) 380 return -EFAULT; 381 382 return 0; 383 } 384 385 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 386 { 387 struct v4l2_plane32 __user *uplane32; 388 struct v4l2_plane __user *uplane; 389 compat_caddr_t p; 390 int num_planes; 391 int ret; 392 393 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 394 get_user(kp->index, &up->index) || 395 get_user(kp->type, &up->type) || 396 get_user(kp->flags, &up->flags) || 397 get_user(kp->memory, &up->memory)) 398 return -EFAULT; 399 400 if (V4L2_TYPE_IS_OUTPUT(kp->type)) 401 if (get_user(kp->bytesused, &up->bytesused) || 402 get_user(kp->field, &up->field) || 403 get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 404 get_user(kp->timestamp.tv_usec, 405 &up->timestamp.tv_usec)) 406 return -EFAULT; 407 408 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 409 if (get_user(kp->length, &up->length)) 410 return -EFAULT; 411 412 num_planes = kp->length; 413 if (num_planes == 0) { 414 kp->m.planes = NULL; 415 /* num_planes == 0 is legal, e.g. when userspace doesn't 416 * need planes array on DQBUF*/ 417 return 0; 418 } 419 420 if (get_user(p, &up->m.planes)) 421 return -EFAULT; 422 423 uplane32 = compat_ptr(p); 424 if (!access_ok(VERIFY_READ, uplane32, 425 num_planes * sizeof(struct v4l2_plane32))) 426 return -EFAULT; 427 428 /* We don't really care if userspace decides to kill itself 429 * by passing a very big num_planes value */ 430 uplane = compat_alloc_user_space(num_planes * 431 sizeof(struct v4l2_plane)); 432 kp->m.planes = (__force struct v4l2_plane *)uplane; 433 434 while (--num_planes >= 0) { 435 ret = get_v4l2_plane32(uplane, uplane32, kp->memory); 436 if (ret) 437 return ret; 438 ++uplane; 439 ++uplane32; 440 } 441 } else { 442 switch (kp->memory) { 443 case V4L2_MEMORY_MMAP: 444 if (get_user(kp->length, &up->length) || 445 get_user(kp->m.offset, &up->m.offset)) 446 return -EFAULT; 447 break; 448 case V4L2_MEMORY_USERPTR: 449 { 450 compat_long_t tmp; 451 452 if (get_user(kp->length, &up->length) || 453 get_user(tmp, &up->m.userptr)) 454 return -EFAULT; 455 456 kp->m.userptr = (unsigned long)compat_ptr(tmp); 457 } 458 break; 459 case V4L2_MEMORY_OVERLAY: 460 if (get_user(kp->m.offset, &up->m.offset)) 461 return -EFAULT; 462 break; 463 case V4L2_MEMORY_DMABUF: 464 if (get_user(kp->m.fd, &up->m.fd)) 465 return -EFAULT; 466 break; 467 } 468 } 469 470 return 0; 471 } 472 473 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 474 { 475 struct v4l2_plane32 __user *uplane32; 476 struct v4l2_plane __user *uplane; 477 compat_caddr_t p; 478 int num_planes; 479 int ret; 480 481 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 482 put_user(kp->index, &up->index) || 483 put_user(kp->type, &up->type) || 484 put_user(kp->flags, &up->flags) || 485 put_user(kp->memory, &up->memory)) 486 return -EFAULT; 487 488 if (put_user(kp->bytesused, &up->bytesused) || 489 put_user(kp->field, &up->field) || 490 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 491 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || 492 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || 493 put_user(kp->sequence, &up->sequence) || 494 put_user(kp->reserved2, &up->reserved2) || 495 put_user(kp->reserved, &up->reserved)) 496 return -EFAULT; 497 498 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { 499 num_planes = kp->length; 500 if (num_planes == 0) 501 return 0; 502 503 uplane = (__force struct v4l2_plane __user *)kp->m.planes; 504 if (get_user(p, &up->m.planes)) 505 return -EFAULT; 506 uplane32 = compat_ptr(p); 507 508 while (--num_planes >= 0) { 509 ret = put_v4l2_plane32(uplane, uplane32, kp->memory); 510 if (ret) 511 return ret; 512 ++uplane; 513 ++uplane32; 514 } 515 } else { 516 switch (kp->memory) { 517 case V4L2_MEMORY_MMAP: 518 if (put_user(kp->length, &up->length) || 519 put_user(kp->m.offset, &up->m.offset)) 520 return -EFAULT; 521 break; 522 case V4L2_MEMORY_USERPTR: 523 if (put_user(kp->length, &up->length) || 524 put_user(kp->m.userptr, &up->m.userptr)) 525 return -EFAULT; 526 break; 527 case V4L2_MEMORY_OVERLAY: 528 if (put_user(kp->m.offset, &up->m.offset)) 529 return -EFAULT; 530 break; 531 case V4L2_MEMORY_DMABUF: 532 if (put_user(kp->m.fd, &up->m.fd)) 533 return -EFAULT; 534 break; 535 } 536 } 537 538 return 0; 539 } 540 541 struct v4l2_framebuffer32 { 542 __u32 capability; 543 __u32 flags; 544 compat_caddr_t base; 545 struct { 546 __u32 width; 547 __u32 height; 548 __u32 pixelformat; 549 __u32 field; 550 __u32 bytesperline; 551 __u32 sizeimage; 552 __u32 colorspace; 553 __u32 priv; 554 } fmt; 555 }; 556 557 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 558 { 559 u32 tmp; 560 561 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || 562 get_user(tmp, &up->base) || 563 get_user(kp->capability, &up->capability) || 564 get_user(kp->flags, &up->flags) || 565 copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) 566 return -EFAULT; 567 kp->base = (__force void *)compat_ptr(tmp); 568 return 0; 569 } 570 571 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 572 { 573 u32 tmp = (u32)((unsigned long)kp->base); 574 575 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || 576 put_user(tmp, &up->base) || 577 put_user(kp->capability, &up->capability) || 578 put_user(kp->flags, &up->flags) || 579 copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) 580 return -EFAULT; 581 return 0; 582 } 583 584 struct v4l2_input32 { 585 __u32 index; /* Which input */ 586 __u8 name[32]; /* Label */ 587 __u32 type; /* Type of input */ 588 __u32 audioset; /* Associated audios (bitfield) */ 589 __u32 tuner; /* Associated tuner */ 590 v4l2_std_id std; 591 __u32 status; 592 __u32 reserved[4]; 593 } __attribute__ ((packed)); 594 595 /* The 64-bit v4l2_input struct has extra padding at the end of the struct. 596 Otherwise it is identical to the 32-bit version. */ 597 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 598 { 599 if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) 600 return -EFAULT; 601 return 0; 602 } 603 604 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) 605 { 606 if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) 607 return -EFAULT; 608 return 0; 609 } 610 611 struct v4l2_ext_controls32 { 612 __u32 ctrl_class; 613 __u32 count; 614 __u32 error_idx; 615 __u32 reserved[2]; 616 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 617 }; 618 619 struct v4l2_ext_control32 { 620 __u32 id; 621 __u32 size; 622 __u32 reserved2[1]; 623 union { 624 __s32 value; 625 __s64 value64; 626 compat_caddr_t string; /* actually char * */ 627 }; 628 } __attribute__ ((packed)); 629 630 /* The following function really belong in v4l2-common, but that causes 631 a circular dependency between modules. We need to think about this, but 632 for now this will do. */ 633 634 /* Return non-zero if this control is a pointer type. Currently only 635 type STRING is a pointer type. */ 636 static inline int ctrl_is_pointer(u32 id) 637 { 638 switch (id) { 639 case V4L2_CID_RDS_TX_PS_NAME: 640 case V4L2_CID_RDS_TX_RADIO_TEXT: 641 return 1; 642 default: 643 return 0; 644 } 645 } 646 647 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 648 { 649 struct v4l2_ext_control32 __user *ucontrols; 650 struct v4l2_ext_control __user *kcontrols; 651 int n; 652 compat_caddr_t p; 653 654 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || 655 get_user(kp->ctrl_class, &up->ctrl_class) || 656 get_user(kp->count, &up->count) || 657 get_user(kp->error_idx, &up->error_idx) || 658 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 659 return -EFAULT; 660 n = kp->count; 661 if (n == 0) { 662 kp->controls = NULL; 663 return 0; 664 } 665 if (get_user(p, &up->controls)) 666 return -EFAULT; 667 ucontrols = compat_ptr(p); 668 if (!access_ok(VERIFY_READ, ucontrols, 669 n * sizeof(struct v4l2_ext_control32))) 670 return -EFAULT; 671 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); 672 kp->controls = (__force struct v4l2_ext_control *)kcontrols; 673 while (--n >= 0) { 674 u32 id; 675 676 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) 677 return -EFAULT; 678 if (get_user(id, &kcontrols->id)) 679 return -EFAULT; 680 if (ctrl_is_pointer(id)) { 681 void __user *s; 682 683 if (get_user(p, &ucontrols->string)) 684 return -EFAULT; 685 s = compat_ptr(p); 686 if (put_user(s, &kcontrols->string)) 687 return -EFAULT; 688 } 689 ucontrols++; 690 kcontrols++; 691 } 692 return 0; 693 } 694 695 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) 696 { 697 struct v4l2_ext_control32 __user *ucontrols; 698 struct v4l2_ext_control __user *kcontrols = 699 (__force struct v4l2_ext_control __user *)kp->controls; 700 int n = kp->count; 701 compat_caddr_t p; 702 703 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || 704 put_user(kp->ctrl_class, &up->ctrl_class) || 705 put_user(kp->count, &up->count) || 706 put_user(kp->error_idx, &up->error_idx) || 707 copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) 708 return -EFAULT; 709 if (!kp->count) 710 return 0; 711 712 if (get_user(p, &up->controls)) 713 return -EFAULT; 714 ucontrols = compat_ptr(p); 715 if (!access_ok(VERIFY_WRITE, ucontrols, 716 n * sizeof(struct v4l2_ext_control32))) 717 return -EFAULT; 718 719 while (--n >= 0) { 720 unsigned size = sizeof(*ucontrols); 721 u32 id; 722 723 if (get_user(id, &kcontrols->id)) 724 return -EFAULT; 725 /* Do not modify the pointer when copying a pointer control. 726 The contents of the pointer was changed, not the pointer 727 itself. */ 728 if (ctrl_is_pointer(id)) 729 size -= sizeof(ucontrols->value64); 730 if (copy_in_user(ucontrols, kcontrols, size)) 731 return -EFAULT; 732 ucontrols++; 733 kcontrols++; 734 } 735 return 0; 736 } 737 738 struct v4l2_event32 { 739 __u32 type; 740 union { 741 __u8 data[64]; 742 } u; 743 __u32 pending; 744 __u32 sequence; 745 struct compat_timespec timestamp; 746 __u32 id; 747 __u32 reserved[8]; 748 }; 749 750 static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) 751 { 752 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || 753 put_user(kp->type, &up->type) || 754 copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || 755 put_user(kp->pending, &up->pending) || 756 put_user(kp->sequence, &up->sequence) || 757 compat_put_timespec(&kp->timestamp, &up->timestamp) || 758 put_user(kp->id, &up->id) || 759 copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) 760 return -EFAULT; 761 return 0; 762 } 763 764 struct v4l2_edid32 { 765 __u32 pad; 766 __u32 start_block; 767 __u32 blocks; 768 __u32 reserved[5]; 769 compat_caddr_t edid; 770 }; 771 772 static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) 773 { 774 u32 tmp; 775 776 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) || 777 get_user(kp->pad, &up->pad) || 778 get_user(kp->start_block, &up->start_block) || 779 get_user(kp->blocks, &up->blocks) || 780 get_user(tmp, &up->edid) || 781 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) 782 return -EFAULT; 783 kp->edid = (__force u8 *)compat_ptr(tmp); 784 return 0; 785 } 786 787 static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) 788 { 789 u32 tmp = (u32)((unsigned long)kp->edid); 790 791 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) || 792 put_user(kp->pad, &up->pad) || 793 put_user(kp->start_block, &up->start_block) || 794 put_user(kp->blocks, &up->blocks) || 795 put_user(tmp, &up->edid) || 796 copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) 797 return -EFAULT; 798 return 0; 799 } 800 801 802 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 803 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 804 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 805 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 806 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 807 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 808 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 809 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 810 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 811 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) 812 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) 813 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 814 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 815 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 816 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 817 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 818 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 819 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 820 821 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) 822 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) 823 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) 824 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) 825 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32) 826 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) 827 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) 828 829 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 830 { 831 union { 832 struct v4l2_format v2f; 833 struct v4l2_buffer v2b; 834 struct v4l2_framebuffer v2fb; 835 struct v4l2_input v2i; 836 struct v4l2_standard v2s; 837 struct v4l2_ext_controls v2ecs; 838 struct v4l2_event v2ev; 839 struct v4l2_create_buffers v2crt; 840 struct v4l2_edid v2edid; 841 unsigned long vx; 842 int vi; 843 } karg; 844 void __user *up = compat_ptr(arg); 845 int compatible_arg = 1; 846 long err = 0; 847 848 /* First, convert the command. */ 849 switch (cmd) { 850 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; 851 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; 852 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; 853 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 854 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 855 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; 856 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; 857 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break; 858 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break; 859 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; 860 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break; 861 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; 862 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; 863 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break; 864 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 865 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; 866 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; 867 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 868 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; 869 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break; 870 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; 871 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break; 872 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break; 873 case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break; 874 case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break; 875 } 876 877 switch (cmd) { 878 case VIDIOC_OVERLAY: 879 case VIDIOC_STREAMON: 880 case VIDIOC_STREAMOFF: 881 case VIDIOC_S_INPUT: 882 case VIDIOC_S_OUTPUT: 883 err = get_user(karg.vi, (s32 __user *)up); 884 compatible_arg = 0; 885 break; 886 887 case VIDIOC_G_INPUT: 888 case VIDIOC_G_OUTPUT: 889 compatible_arg = 0; 890 break; 891 892 case VIDIOC_G_EDID: 893 case VIDIOC_S_EDID: 894 err = get_v4l2_edid32(&karg.v2edid, up); 895 compatible_arg = 0; 896 break; 897 898 case VIDIOC_G_FMT: 899 case VIDIOC_S_FMT: 900 case VIDIOC_TRY_FMT: 901 err = get_v4l2_format32(&karg.v2f, up); 902 compatible_arg = 0; 903 break; 904 905 case VIDIOC_CREATE_BUFS: 906 err = get_v4l2_create32(&karg.v2crt, up); 907 compatible_arg = 0; 908 break; 909 910 case VIDIOC_PREPARE_BUF: 911 case VIDIOC_QUERYBUF: 912 case VIDIOC_QBUF: 913 case VIDIOC_DQBUF: 914 err = get_v4l2_buffer32(&karg.v2b, up); 915 compatible_arg = 0; 916 break; 917 918 case VIDIOC_S_FBUF: 919 err = get_v4l2_framebuffer32(&karg.v2fb, up); 920 compatible_arg = 0; 921 break; 922 923 case VIDIOC_G_FBUF: 924 compatible_arg = 0; 925 break; 926 927 case VIDIOC_ENUMSTD: 928 err = get_v4l2_standard32(&karg.v2s, up); 929 compatible_arg = 0; 930 break; 931 932 case VIDIOC_ENUMINPUT: 933 err = get_v4l2_input32(&karg.v2i, up); 934 compatible_arg = 0; 935 break; 936 937 case VIDIOC_G_EXT_CTRLS: 938 case VIDIOC_S_EXT_CTRLS: 939 case VIDIOC_TRY_EXT_CTRLS: 940 err = get_v4l2_ext_controls32(&karg.v2ecs, up); 941 compatible_arg = 0; 942 break; 943 case VIDIOC_DQEVENT: 944 compatible_arg = 0; 945 break; 946 } 947 if (err) 948 return err; 949 950 if (compatible_arg) 951 err = native_ioctl(file, cmd, (unsigned long)up); 952 else { 953 mm_segment_t old_fs = get_fs(); 954 955 set_fs(KERNEL_DS); 956 err = native_ioctl(file, cmd, (unsigned long)&karg); 957 set_fs(old_fs); 958 } 959 960 /* Special case: even after an error we need to put the 961 results back for these ioctls since the error_idx will 962 contain information on which control failed. */ 963 switch (cmd) { 964 case VIDIOC_G_EXT_CTRLS: 965 case VIDIOC_S_EXT_CTRLS: 966 case VIDIOC_TRY_EXT_CTRLS: 967 if (put_v4l2_ext_controls32(&karg.v2ecs, up)) 968 err = -EFAULT; 969 break; 970 } 971 if (err) 972 return err; 973 974 switch (cmd) { 975 case VIDIOC_S_INPUT: 976 case VIDIOC_S_OUTPUT: 977 case VIDIOC_G_INPUT: 978 case VIDIOC_G_OUTPUT: 979 err = put_user(((s32)karg.vi), (s32 __user *)up); 980 break; 981 982 case VIDIOC_G_FBUF: 983 err = put_v4l2_framebuffer32(&karg.v2fb, up); 984 break; 985 986 case VIDIOC_DQEVENT: 987 err = put_v4l2_event32(&karg.v2ev, up); 988 break; 989 990 case VIDIOC_G_EDID: 991 case VIDIOC_S_EDID: 992 err = put_v4l2_edid32(&karg.v2edid, up); 993 break; 994 995 case VIDIOC_G_FMT: 996 case VIDIOC_S_FMT: 997 case VIDIOC_TRY_FMT: 998 err = put_v4l2_format32(&karg.v2f, up); 999 break; 1000 1001 case VIDIOC_CREATE_BUFS: 1002 err = put_v4l2_create32(&karg.v2crt, up); 1003 break; 1004 1005 case VIDIOC_QUERYBUF: 1006 case VIDIOC_QBUF: 1007 case VIDIOC_DQBUF: 1008 err = put_v4l2_buffer32(&karg.v2b, up); 1009 break; 1010 1011 case VIDIOC_ENUMSTD: 1012 err = put_v4l2_standard32(&karg.v2s, up); 1013 break; 1014 1015 case VIDIOC_ENUMINPUT: 1016 err = put_v4l2_input32(&karg.v2i, up); 1017 break; 1018 } 1019 return err; 1020 } 1021 1022 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 1023 { 1024 struct video_device *vdev = video_devdata(file); 1025 long ret = -ENOIOCTLCMD; 1026 1027 if (!file->f_op->unlocked_ioctl) 1028 return ret; 1029 1030 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE) 1031 ret = do_video_ioctl(file, cmd, arg); 1032 else if (vdev->fops->compat_ioctl32) 1033 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1034 1035 if (ret == -ENOIOCTLCMD) 1036 pr_warn("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1037 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); 1038 return ret; 1039 } 1040 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1041