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