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