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