1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls. 4 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de> 5 * 6 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) 7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 8 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs 9 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) 10 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) 11 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> 12 * 13 * These routines maintain argument size conversion between 32bit and 64bit 14 * ioctls. 15 */ 16 17 #include <linux/compat.h> 18 #include <linux/module.h> 19 #include <linux/videodev2.h> 20 #include <linux/v4l2-subdev.h> 21 #include <media/v4l2-dev.h> 22 #include <media/v4l2-fh.h> 23 #include <media/v4l2-ctrls.h> 24 #include <media/v4l2-ioctl.h> 25 26 /* 27 * Per-ioctl data copy handlers. 28 * 29 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine, 30 * where "v4l2_foo" is the name of the V4L2 struct. 31 * 32 * They basically get two __user pointers, one with a 32-bits struct that 33 * came from the userspace call and a 64-bits struct, also allocated as 34 * userspace, but filled internally by do_video_ioctl(). 35 * 36 * For ioctls that have pointers inside it, the functions will also 37 * receive an ancillary buffer with extra space, used to pass extra 38 * data to the routine. 39 */ 40 41 struct v4l2_clip32 { 42 struct v4l2_rect c; 43 compat_caddr_t next; 44 }; 45 46 struct v4l2_window32 { 47 struct v4l2_rect w; 48 __u32 field; /* enum v4l2_field */ 49 __u32 chromakey; 50 compat_caddr_t clips; /* actually struct v4l2_clip32 * */ 51 __u32 clipcount; 52 compat_caddr_t bitmap; 53 __u8 global_alpha; 54 }; 55 56 static int get_v4l2_window32(struct v4l2_window *p64, 57 struct v4l2_window32 __user *p32) 58 { 59 struct v4l2_window32 w32; 60 61 if (copy_from_user(&w32, p32, sizeof(w32))) 62 return -EFAULT; 63 64 *p64 = (struct v4l2_window) { 65 .w = w32.w, 66 .field = w32.field, 67 .chromakey = w32.chromakey, 68 .clips = (void __force *)compat_ptr(w32.clips), 69 .clipcount = w32.clipcount, 70 .bitmap = compat_ptr(w32.bitmap), 71 .global_alpha = w32.global_alpha, 72 }; 73 74 if (p64->clipcount > 2048) 75 return -EINVAL; 76 if (!p64->clipcount) 77 p64->clips = NULL; 78 79 return 0; 80 } 81 82 static int put_v4l2_window32(struct v4l2_window *p64, 83 struct v4l2_window32 __user *p32) 84 { 85 struct v4l2_window32 w32; 86 87 memset(&w32, 0, sizeof(w32)); 88 w32 = (struct v4l2_window32) { 89 .w = p64->w, 90 .field = p64->field, 91 .chromakey = p64->chromakey, 92 .clips = (uintptr_t)p64->clips, 93 .clipcount = p64->clipcount, 94 .bitmap = ptr_to_compat(p64->bitmap), 95 .global_alpha = p64->global_alpha, 96 }; 97 98 /* copy everything except the clips pointer */ 99 if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) || 100 copy_to_user(&p32->clipcount, &w32.clipcount, 101 sizeof(w32) - offsetof(struct v4l2_window32, clipcount))) 102 return -EFAULT; 103 104 return 0; 105 } 106 107 struct v4l2_format32 { 108 __u32 type; /* enum v4l2_buf_type */ 109 union { 110 struct v4l2_pix_format pix; 111 struct v4l2_pix_format_mplane pix_mp; 112 struct v4l2_window32 win; 113 struct v4l2_vbi_format vbi; 114 struct v4l2_sliced_vbi_format sliced; 115 struct v4l2_sdr_format sdr; 116 struct v4l2_meta_format meta; 117 __u8 raw_data[200]; /* user-defined */ 118 } fmt; 119 }; 120 121 /** 122 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument 123 * @index: on return, index of the first created buffer 124 * @count: entry: number of requested buffers, 125 * return: number of created buffers 126 * @memory: buffer memory type 127 * @format: frame format, for which buffers are requested 128 * @capabilities: capabilities of this buffer type. 129 * @reserved: future extensions 130 */ 131 struct v4l2_create_buffers32 { 132 __u32 index; 133 __u32 count; 134 __u32 memory; /* enum v4l2_memory */ 135 struct v4l2_format32 format; 136 __u32 capabilities; 137 __u32 reserved[7]; 138 }; 139 140 static int get_v4l2_format32(struct v4l2_format *p64, 141 struct v4l2_format32 __user *p32) 142 { 143 if (get_user(p64->type, &p32->type)) 144 return -EFAULT; 145 146 switch (p64->type) { 147 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 148 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 149 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix, 150 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 151 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 152 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 153 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp, 154 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 155 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 156 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 157 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 158 case V4L2_BUF_TYPE_VBI_CAPTURE: 159 case V4L2_BUF_TYPE_VBI_OUTPUT: 160 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi, 161 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 162 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 163 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 164 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced, 165 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 166 case V4L2_BUF_TYPE_SDR_CAPTURE: 167 case V4L2_BUF_TYPE_SDR_OUTPUT: 168 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr, 169 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 170 case V4L2_BUF_TYPE_META_CAPTURE: 171 case V4L2_BUF_TYPE_META_OUTPUT: 172 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta, 173 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 174 default: 175 return -EINVAL; 176 } 177 } 178 179 static int get_v4l2_create32(struct v4l2_create_buffers *p64, 180 struct v4l2_create_buffers32 __user *p32) 181 { 182 if (copy_from_user(p64, p32, 183 offsetof(struct v4l2_create_buffers32, format))) 184 return -EFAULT; 185 return get_v4l2_format32(&p64->format, &p32->format); 186 } 187 188 static int put_v4l2_format32(struct v4l2_format *p64, 189 struct v4l2_format32 __user *p32) 190 { 191 switch (p64->type) { 192 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 193 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 194 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix, 195 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 196 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 197 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 198 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp, 199 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 200 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 201 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 202 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 203 case V4L2_BUF_TYPE_VBI_CAPTURE: 204 case V4L2_BUF_TYPE_VBI_OUTPUT: 205 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi, 206 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 207 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 208 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 209 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced, 210 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 211 case V4L2_BUF_TYPE_SDR_CAPTURE: 212 case V4L2_BUF_TYPE_SDR_OUTPUT: 213 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr, 214 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 215 case V4L2_BUF_TYPE_META_CAPTURE: 216 case V4L2_BUF_TYPE_META_OUTPUT: 217 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta, 218 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 219 default: 220 return -EINVAL; 221 } 222 } 223 224 static int put_v4l2_create32(struct v4l2_create_buffers *p64, 225 struct v4l2_create_buffers32 __user *p32) 226 { 227 if (copy_to_user(p32, p64, 228 offsetof(struct v4l2_create_buffers32, format)) || 229 put_user(p64->capabilities, &p32->capabilities) || 230 copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved))) 231 return -EFAULT; 232 return put_v4l2_format32(&p64->format, &p32->format); 233 } 234 235 struct v4l2_standard32 { 236 __u32 index; 237 compat_u64 id; 238 __u8 name[24]; 239 struct v4l2_fract frameperiod; /* Frames, not fields */ 240 __u32 framelines; 241 __u32 reserved[4]; 242 }; 243 244 static int get_v4l2_standard32(struct v4l2_standard *p64, 245 struct v4l2_standard32 __user *p32) 246 { 247 /* other fields are not set by the user, nor used by the driver */ 248 return get_user(p64->index, &p32->index); 249 } 250 251 static int put_v4l2_standard32(struct v4l2_standard *p64, 252 struct v4l2_standard32 __user *p32) 253 { 254 if (put_user(p64->index, &p32->index) || 255 put_user(p64->id, &p32->id) || 256 copy_to_user(p32->name, p64->name, sizeof(p32->name)) || 257 copy_to_user(&p32->frameperiod, &p64->frameperiod, 258 sizeof(p32->frameperiod)) || 259 put_user(p64->framelines, &p32->framelines) || 260 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 261 return -EFAULT; 262 return 0; 263 } 264 265 struct v4l2_plane32 { 266 __u32 bytesused; 267 __u32 length; 268 union { 269 __u32 mem_offset; 270 compat_long_t userptr; 271 __s32 fd; 272 } m; 273 __u32 data_offset; 274 __u32 reserved[11]; 275 }; 276 277 /* 278 * This is correct for all architectures including i386, but not x32, 279 * which has different alignment requirements for timestamp 280 */ 281 struct v4l2_buffer32 { 282 __u32 index; 283 __u32 type; /* enum v4l2_buf_type */ 284 __u32 bytesused; 285 __u32 flags; 286 __u32 field; /* enum v4l2_field */ 287 struct { 288 compat_s64 tv_sec; 289 compat_s64 tv_usec; 290 } timestamp; 291 struct v4l2_timecode timecode; 292 __u32 sequence; 293 294 /* memory location */ 295 __u32 memory; /* enum v4l2_memory */ 296 union { 297 __u32 offset; 298 compat_long_t userptr; 299 compat_caddr_t planes; 300 __s32 fd; 301 } m; 302 __u32 length; 303 __u32 reserved2; 304 __s32 request_fd; 305 }; 306 307 struct v4l2_buffer32_time32 { 308 __u32 index; 309 __u32 type; /* enum v4l2_buf_type */ 310 __u32 bytesused; 311 __u32 flags; 312 __u32 field; /* enum v4l2_field */ 313 struct old_timeval32 timestamp; 314 struct v4l2_timecode timecode; 315 __u32 sequence; 316 317 /* memory location */ 318 __u32 memory; /* enum v4l2_memory */ 319 union { 320 __u32 offset; 321 compat_long_t userptr; 322 compat_caddr_t planes; 323 __s32 fd; 324 } m; 325 __u32 length; 326 __u32 reserved2; 327 __s32 request_fd; 328 }; 329 330 static int get_v4l2_plane32(struct v4l2_plane *p64, 331 struct v4l2_plane32 __user *p32, 332 enum v4l2_memory memory) 333 { 334 struct v4l2_plane32 plane32; 335 typeof(p64->m) m = {}; 336 337 if (copy_from_user(&plane32, p32, sizeof(plane32))) 338 return -EFAULT; 339 340 switch (memory) { 341 case V4L2_MEMORY_MMAP: 342 case V4L2_MEMORY_OVERLAY: 343 m.mem_offset = plane32.m.mem_offset; 344 break; 345 case V4L2_MEMORY_USERPTR: 346 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr); 347 break; 348 case V4L2_MEMORY_DMABUF: 349 m.fd = plane32.m.fd; 350 break; 351 } 352 353 memset(p64, 0, sizeof(*p64)); 354 *p64 = (struct v4l2_plane) { 355 .bytesused = plane32.bytesused, 356 .length = plane32.length, 357 .m = m, 358 .data_offset = plane32.data_offset, 359 }; 360 361 return 0; 362 } 363 364 static int put_v4l2_plane32(struct v4l2_plane *p64, 365 struct v4l2_plane32 __user *p32, 366 enum v4l2_memory memory) 367 { 368 struct v4l2_plane32 plane32; 369 370 memset(&plane32, 0, sizeof(plane32)); 371 plane32 = (struct v4l2_plane32) { 372 .bytesused = p64->bytesused, 373 .length = p64->length, 374 .data_offset = p64->data_offset, 375 }; 376 377 switch (memory) { 378 case V4L2_MEMORY_MMAP: 379 case V4L2_MEMORY_OVERLAY: 380 plane32.m.mem_offset = p64->m.mem_offset; 381 break; 382 case V4L2_MEMORY_USERPTR: 383 plane32.m.userptr = (uintptr_t)(p64->m.userptr); 384 break; 385 case V4L2_MEMORY_DMABUF: 386 plane32.m.fd = p64->m.fd; 387 break; 388 } 389 390 if (copy_to_user(p32, &plane32, sizeof(plane32))) 391 return -EFAULT; 392 393 return 0; 394 } 395 396 static int get_v4l2_buffer32(struct v4l2_buffer *vb, 397 struct v4l2_buffer32 __user *arg) 398 { 399 struct v4l2_buffer32 vb32; 400 401 if (copy_from_user(&vb32, arg, sizeof(vb32))) 402 return -EFAULT; 403 404 memset(vb, 0, sizeof(*vb)); 405 *vb = (struct v4l2_buffer) { 406 .index = vb32.index, 407 .type = vb32.type, 408 .bytesused = vb32.bytesused, 409 .flags = vb32.flags, 410 .field = vb32.field, 411 .timestamp.tv_sec = vb32.timestamp.tv_sec, 412 .timestamp.tv_usec = vb32.timestamp.tv_usec, 413 .timecode = vb32.timecode, 414 .sequence = vb32.sequence, 415 .memory = vb32.memory, 416 .m.offset = vb32.m.offset, 417 .length = vb32.length, 418 .request_fd = vb32.request_fd, 419 }; 420 421 switch (vb->memory) { 422 case V4L2_MEMORY_MMAP: 423 case V4L2_MEMORY_OVERLAY: 424 vb->m.offset = vb32.m.offset; 425 break; 426 case V4L2_MEMORY_USERPTR: 427 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 428 break; 429 case V4L2_MEMORY_DMABUF: 430 vb->m.fd = vb32.m.fd; 431 break; 432 } 433 434 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 435 vb->m.planes = (void __force *) 436 compat_ptr(vb32.m.planes); 437 438 return 0; 439 } 440 441 #ifdef CONFIG_COMPAT_32BIT_TIME 442 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb, 443 struct v4l2_buffer32_time32 __user *arg) 444 { 445 struct v4l2_buffer32_time32 vb32; 446 447 if (copy_from_user(&vb32, arg, sizeof(vb32))) 448 return -EFAULT; 449 450 *vb = (struct v4l2_buffer) { 451 .index = vb32.index, 452 .type = vb32.type, 453 .bytesused = vb32.bytesused, 454 .flags = vb32.flags, 455 .field = vb32.field, 456 .timestamp.tv_sec = vb32.timestamp.tv_sec, 457 .timestamp.tv_usec = vb32.timestamp.tv_usec, 458 .timecode = vb32.timecode, 459 .sequence = vb32.sequence, 460 .memory = vb32.memory, 461 .m.offset = vb32.m.offset, 462 .length = vb32.length, 463 .request_fd = vb32.request_fd, 464 }; 465 switch (vb->memory) { 466 case V4L2_MEMORY_MMAP: 467 case V4L2_MEMORY_OVERLAY: 468 vb->m.offset = vb32.m.offset; 469 break; 470 case V4L2_MEMORY_USERPTR: 471 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 472 break; 473 case V4L2_MEMORY_DMABUF: 474 vb->m.fd = vb32.m.fd; 475 break; 476 } 477 478 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 479 vb->m.planes = (void __force *) 480 compat_ptr(vb32.m.planes); 481 482 return 0; 483 } 484 #endif 485 486 static int put_v4l2_buffer32(struct v4l2_buffer *vb, 487 struct v4l2_buffer32 __user *arg) 488 { 489 struct v4l2_buffer32 vb32; 490 491 memset(&vb32, 0, sizeof(vb32)); 492 vb32 = (struct v4l2_buffer32) { 493 .index = vb->index, 494 .type = vb->type, 495 .bytesused = vb->bytesused, 496 .flags = vb->flags, 497 .field = vb->field, 498 .timestamp.tv_sec = vb->timestamp.tv_sec, 499 .timestamp.tv_usec = vb->timestamp.tv_usec, 500 .timecode = vb->timecode, 501 .sequence = vb->sequence, 502 .memory = vb->memory, 503 .m.offset = vb->m.offset, 504 .length = vb->length, 505 .request_fd = vb->request_fd, 506 }; 507 508 switch (vb->memory) { 509 case V4L2_MEMORY_MMAP: 510 case V4L2_MEMORY_OVERLAY: 511 vb32.m.offset = vb->m.offset; 512 break; 513 case V4L2_MEMORY_USERPTR: 514 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 515 break; 516 case V4L2_MEMORY_DMABUF: 517 vb32.m.fd = vb->m.fd; 518 break; 519 } 520 521 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 522 vb32.m.planes = (uintptr_t)vb->m.planes; 523 524 if (copy_to_user(arg, &vb32, sizeof(vb32))) 525 return -EFAULT; 526 527 return 0; 528 } 529 530 #ifdef CONFIG_COMPAT_32BIT_TIME 531 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb, 532 struct v4l2_buffer32_time32 __user *arg) 533 { 534 struct v4l2_buffer32_time32 vb32; 535 536 memset(&vb32, 0, sizeof(vb32)); 537 vb32 = (struct v4l2_buffer32_time32) { 538 .index = vb->index, 539 .type = vb->type, 540 .bytesused = vb->bytesused, 541 .flags = vb->flags, 542 .field = vb->field, 543 .timestamp.tv_sec = vb->timestamp.tv_sec, 544 .timestamp.tv_usec = vb->timestamp.tv_usec, 545 .timecode = vb->timecode, 546 .sequence = vb->sequence, 547 .memory = vb->memory, 548 .m.offset = vb->m.offset, 549 .length = vb->length, 550 .request_fd = vb->request_fd, 551 }; 552 switch (vb->memory) { 553 case V4L2_MEMORY_MMAP: 554 case V4L2_MEMORY_OVERLAY: 555 vb32.m.offset = vb->m.offset; 556 break; 557 case V4L2_MEMORY_USERPTR: 558 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 559 break; 560 case V4L2_MEMORY_DMABUF: 561 vb32.m.fd = vb->m.fd; 562 break; 563 } 564 565 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 566 vb32.m.planes = (uintptr_t)vb->m.planes; 567 568 if (copy_to_user(arg, &vb32, sizeof(vb32))) 569 return -EFAULT; 570 571 return 0; 572 } 573 #endif 574 575 struct v4l2_framebuffer32 { 576 __u32 capability; 577 __u32 flags; 578 compat_caddr_t base; 579 struct { 580 __u32 width; 581 __u32 height; 582 __u32 pixelformat; 583 __u32 field; 584 __u32 bytesperline; 585 __u32 sizeimage; 586 __u32 colorspace; 587 __u32 priv; 588 } fmt; 589 }; 590 591 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 592 struct v4l2_framebuffer32 __user *p32) 593 { 594 compat_caddr_t tmp; 595 596 if (get_user(tmp, &p32->base) || 597 get_user(p64->capability, &p32->capability) || 598 get_user(p64->flags, &p32->flags) || 599 copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt))) 600 return -EFAULT; 601 p64->base = (void __force *)compat_ptr(tmp); 602 603 return 0; 604 } 605 606 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 607 struct v4l2_framebuffer32 __user *p32) 608 { 609 if (put_user((uintptr_t)p64->base, &p32->base) || 610 put_user(p64->capability, &p32->capability) || 611 put_user(p64->flags, &p32->flags) || 612 copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt))) 613 return -EFAULT; 614 615 return 0; 616 } 617 618 struct v4l2_input32 { 619 __u32 index; /* Which input */ 620 __u8 name[32]; /* Label */ 621 __u32 type; /* Type of input */ 622 __u32 audioset; /* Associated audios (bitfield) */ 623 __u32 tuner; /* Associated tuner */ 624 compat_u64 std; 625 __u32 status; 626 __u32 capabilities; 627 __u32 reserved[3]; 628 }; 629 630 /* 631 * The 64-bit v4l2_input struct has extra padding at the end of the struct. 632 * Otherwise it is identical to the 32-bit version. 633 */ 634 static inline int get_v4l2_input32(struct v4l2_input *p64, 635 struct v4l2_input32 __user *p32) 636 { 637 if (copy_from_user(p64, p32, sizeof(*p32))) 638 return -EFAULT; 639 return 0; 640 } 641 642 static inline int put_v4l2_input32(struct v4l2_input *p64, 643 struct v4l2_input32 __user *p32) 644 { 645 if (copy_to_user(p32, p64, sizeof(*p32))) 646 return -EFAULT; 647 return 0; 648 } 649 650 struct v4l2_ext_controls32 { 651 __u32 which; 652 __u32 count; 653 __u32 error_idx; 654 __s32 request_fd; 655 __u32 reserved[1]; 656 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 657 }; 658 659 struct v4l2_ext_control32 { 660 __u32 id; 661 __u32 size; 662 __u32 reserved2[1]; 663 union { 664 __s32 value; 665 __s64 value64; 666 compat_caddr_t string; /* actually char * */ 667 }; 668 } __attribute__ ((packed)); 669 670 /* Return true if this control is a pointer type. */ 671 static inline bool ctrl_is_pointer(struct file *file, u32 id) 672 { 673 struct video_device *vdev = video_devdata(file); 674 struct v4l2_fh *fh = NULL; 675 struct v4l2_ctrl_handler *hdl = NULL; 676 struct v4l2_query_ext_ctrl qec = { id }; 677 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; 678 679 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) 680 fh = file->private_data; 681 682 if (fh && fh->ctrl_handler) 683 hdl = fh->ctrl_handler; 684 else if (vdev->ctrl_handler) 685 hdl = vdev->ctrl_handler; 686 687 if (hdl) { 688 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); 689 690 return ctrl && ctrl->is_ptr; 691 } 692 693 if (!ops || !ops->vidioc_query_ext_ctrl) 694 return false; 695 696 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && 697 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); 698 } 699 700 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 701 struct v4l2_ext_controls32 __user *p32) 702 { 703 struct v4l2_ext_controls32 ec32; 704 705 if (copy_from_user(&ec32, p32, sizeof(ec32))) 706 return -EFAULT; 707 708 *p64 = (struct v4l2_ext_controls) { 709 .which = ec32.which, 710 .count = ec32.count, 711 .error_idx = ec32.error_idx, 712 .request_fd = ec32.request_fd, 713 .reserved[0] = ec32.reserved[0], 714 .controls = (void __force *)compat_ptr(ec32.controls), 715 }; 716 717 return 0; 718 } 719 720 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 721 struct v4l2_ext_controls32 __user *p32) 722 { 723 struct v4l2_ext_controls32 ec32; 724 725 memset(&ec32, 0, sizeof(ec32)); 726 ec32 = (struct v4l2_ext_controls32) { 727 .which = p64->which, 728 .count = p64->count, 729 .error_idx = p64->error_idx, 730 .request_fd = p64->request_fd, 731 .reserved[0] = p64->reserved[0], 732 .controls = (uintptr_t)p64->controls, 733 }; 734 735 if (copy_to_user(p32, &ec32, sizeof(ec32))) 736 return -EFAULT; 737 738 return 0; 739 } 740 741 #ifdef CONFIG_X86_64 742 /* 743 * x86 is the only compat architecture with different struct alignment 744 * between 32-bit and 64-bit tasks. 745 * 746 * On all other architectures, v4l2_event32 and v4l2_event32_time32 are 747 * the same as v4l2_event and v4l2_event_time32, so we can use the native 748 * handlers, converting v4l2_event to v4l2_event_time32 if necessary. 749 */ 750 struct v4l2_event32 { 751 __u32 type; 752 union { 753 compat_s64 value64; 754 __u8 data[64]; 755 } u; 756 __u32 pending; 757 __u32 sequence; 758 struct { 759 compat_s64 tv_sec; 760 compat_s64 tv_nsec; 761 } timestamp; 762 __u32 id; 763 __u32 reserved[8]; 764 }; 765 766 struct v4l2_event32_time32 { 767 __u32 type; 768 union { 769 compat_s64 value64; 770 __u8 data[64]; 771 } u; 772 __u32 pending; 773 __u32 sequence; 774 struct old_timespec32 timestamp; 775 __u32 id; 776 __u32 reserved[8]; 777 }; 778 779 static int put_v4l2_event32(struct v4l2_event *p64, 780 struct v4l2_event32 __user *p32) 781 { 782 if (put_user(p64->type, &p32->type) || 783 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 784 put_user(p64->pending, &p32->pending) || 785 put_user(p64->sequence, &p32->sequence) || 786 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 787 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 788 put_user(p64->id, &p32->id) || 789 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 790 return -EFAULT; 791 return 0; 792 } 793 794 #ifdef CONFIG_COMPAT_32BIT_TIME 795 static int put_v4l2_event32_time32(struct v4l2_event *p64, 796 struct v4l2_event32_time32 __user *p32) 797 { 798 if (put_user(p64->type, &p32->type) || 799 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 800 put_user(p64->pending, &p32->pending) || 801 put_user(p64->sequence, &p32->sequence) || 802 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 803 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 804 put_user(p64->id, &p32->id) || 805 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 806 return -EFAULT; 807 return 0; 808 } 809 #endif 810 #endif 811 812 struct v4l2_edid32 { 813 __u32 pad; 814 __u32 start_block; 815 __u32 blocks; 816 __u32 reserved[5]; 817 compat_caddr_t edid; 818 }; 819 820 static int get_v4l2_edid32(struct v4l2_edid *p64, 821 struct v4l2_edid32 __user *p32) 822 { 823 compat_uptr_t edid; 824 825 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) || 826 get_user(edid, &p32->edid)) 827 return -EFAULT; 828 829 p64->edid = (void __force *)compat_ptr(edid); 830 return 0; 831 } 832 833 static int put_v4l2_edid32(struct v4l2_edid *p64, 834 struct v4l2_edid32 __user *p32) 835 { 836 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid))) 837 return -EFAULT; 838 return 0; 839 } 840 841 /* 842 * List of ioctls that require 32-bits/64-bits conversion 843 * 844 * The V4L2 ioctls that aren't listed there don't have pointer arguments 845 * and the struct size is identical for both 32 and 64 bits versions, so 846 * they don't need translations. 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_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) 853 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 854 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 855 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 856 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) 857 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 858 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) 859 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 860 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 861 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) 862 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) 863 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 864 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 865 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 866 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 867 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 868 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) 869 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 870 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 871 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) 872 873 unsigned int v4l2_compat_translate_cmd(unsigned int cmd) 874 { 875 switch (cmd) { 876 case VIDIOC_G_FMT32: 877 return VIDIOC_G_FMT; 878 case VIDIOC_S_FMT32: 879 return VIDIOC_S_FMT; 880 case VIDIOC_TRY_FMT32: 881 return VIDIOC_TRY_FMT; 882 case VIDIOC_G_FBUF32: 883 return VIDIOC_G_FBUF; 884 case VIDIOC_S_FBUF32: 885 return VIDIOC_S_FBUF; 886 #ifdef CONFIG_COMPAT_32BIT_TIME 887 case VIDIOC_QUERYBUF32_TIME32: 888 return VIDIOC_QUERYBUF; 889 case VIDIOC_QBUF32_TIME32: 890 return VIDIOC_QBUF; 891 case VIDIOC_DQBUF32_TIME32: 892 return VIDIOC_DQBUF; 893 case VIDIOC_PREPARE_BUF32_TIME32: 894 return VIDIOC_PREPARE_BUF; 895 #endif 896 case VIDIOC_QUERYBUF32: 897 return VIDIOC_QUERYBUF; 898 case VIDIOC_QBUF32: 899 return VIDIOC_QBUF; 900 case VIDIOC_DQBUF32: 901 return VIDIOC_DQBUF; 902 case VIDIOC_CREATE_BUFS32: 903 return VIDIOC_CREATE_BUFS; 904 case VIDIOC_G_EXT_CTRLS32: 905 return VIDIOC_G_EXT_CTRLS; 906 case VIDIOC_S_EXT_CTRLS32: 907 return VIDIOC_S_EXT_CTRLS; 908 case VIDIOC_TRY_EXT_CTRLS32: 909 return VIDIOC_TRY_EXT_CTRLS; 910 case VIDIOC_PREPARE_BUF32: 911 return VIDIOC_PREPARE_BUF; 912 case VIDIOC_ENUMSTD32: 913 return VIDIOC_ENUMSTD; 914 case VIDIOC_ENUMINPUT32: 915 return VIDIOC_ENUMINPUT; 916 case VIDIOC_G_EDID32: 917 return VIDIOC_G_EDID; 918 case VIDIOC_S_EDID32: 919 return VIDIOC_S_EDID; 920 #ifdef CONFIG_X86_64 921 case VIDIOC_DQEVENT32: 922 return VIDIOC_DQEVENT; 923 #ifdef CONFIG_COMPAT_32BIT_TIME 924 case VIDIOC_DQEVENT32_TIME32: 925 return VIDIOC_DQEVENT; 926 #endif 927 #endif 928 } 929 return cmd; 930 } 931 932 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd) 933 { 934 switch (cmd) { 935 case VIDIOC_G_FMT32: 936 case VIDIOC_S_FMT32: 937 case VIDIOC_TRY_FMT32: 938 return get_v4l2_format32(parg, arg); 939 940 case VIDIOC_S_FBUF32: 941 return get_v4l2_framebuffer32(parg, arg); 942 #ifdef CONFIG_COMPAT_32BIT_TIME 943 case VIDIOC_QUERYBUF32_TIME32: 944 case VIDIOC_QBUF32_TIME32: 945 case VIDIOC_DQBUF32_TIME32: 946 case VIDIOC_PREPARE_BUF32_TIME32: 947 return get_v4l2_buffer32_time32(parg, arg); 948 #endif 949 case VIDIOC_QUERYBUF32: 950 case VIDIOC_QBUF32: 951 case VIDIOC_DQBUF32: 952 case VIDIOC_PREPARE_BUF32: 953 return get_v4l2_buffer32(parg, arg); 954 955 case VIDIOC_G_EXT_CTRLS32: 956 case VIDIOC_S_EXT_CTRLS32: 957 case VIDIOC_TRY_EXT_CTRLS32: 958 return get_v4l2_ext_controls32(parg, arg); 959 960 case VIDIOC_CREATE_BUFS32: 961 return get_v4l2_create32(parg, arg); 962 963 case VIDIOC_ENUMSTD32: 964 return get_v4l2_standard32(parg, arg); 965 966 case VIDIOC_ENUMINPUT32: 967 return get_v4l2_input32(parg, arg); 968 969 case VIDIOC_G_EDID32: 970 case VIDIOC_S_EDID32: 971 return get_v4l2_edid32(parg, arg); 972 } 973 return 0; 974 } 975 976 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) 977 { 978 switch (cmd) { 979 case VIDIOC_G_FMT32: 980 case VIDIOC_S_FMT32: 981 case VIDIOC_TRY_FMT32: 982 return put_v4l2_format32(parg, arg); 983 984 case VIDIOC_G_FBUF32: 985 return put_v4l2_framebuffer32(parg, arg); 986 #ifdef CONFIG_COMPAT_32BIT_TIME 987 case VIDIOC_QUERYBUF32_TIME32: 988 case VIDIOC_QBUF32_TIME32: 989 case VIDIOC_DQBUF32_TIME32: 990 case VIDIOC_PREPARE_BUF32_TIME32: 991 return put_v4l2_buffer32_time32(parg, arg); 992 #endif 993 case VIDIOC_QUERYBUF32: 994 case VIDIOC_QBUF32: 995 case VIDIOC_DQBUF32: 996 case VIDIOC_PREPARE_BUF32: 997 return put_v4l2_buffer32(parg, arg); 998 999 case VIDIOC_G_EXT_CTRLS32: 1000 case VIDIOC_S_EXT_CTRLS32: 1001 case VIDIOC_TRY_EXT_CTRLS32: 1002 return put_v4l2_ext_controls32(parg, arg); 1003 1004 case VIDIOC_CREATE_BUFS32: 1005 return put_v4l2_create32(parg, arg); 1006 1007 case VIDIOC_ENUMSTD32: 1008 return put_v4l2_standard32(parg, arg); 1009 1010 case VIDIOC_ENUMINPUT32: 1011 return put_v4l2_input32(parg, arg); 1012 1013 case VIDIOC_G_EDID32: 1014 case VIDIOC_S_EDID32: 1015 return put_v4l2_edid32(parg, arg); 1016 #ifdef CONFIG_X86_64 1017 case VIDIOC_DQEVENT32: 1018 return put_v4l2_event32(parg, arg); 1019 #ifdef CONFIG_COMPAT_32BIT_TIME 1020 case VIDIOC_DQEVENT32_TIME32: 1021 return put_v4l2_event32_time32(parg, arg); 1022 #endif 1023 #endif 1024 } 1025 return 0; 1026 } 1027 1028 int v4l2_compat_get_array_args(struct file *file, void *mbuf, 1029 void __user *user_ptr, size_t array_size, 1030 unsigned int cmd, void *arg) 1031 { 1032 int err = 0; 1033 1034 switch (cmd) { 1035 case VIDIOC_G_FMT32: 1036 case VIDIOC_S_FMT32: 1037 case VIDIOC_TRY_FMT32: { 1038 struct v4l2_format *f64 = arg; 1039 struct v4l2_clip *c64 = mbuf; 1040 struct v4l2_clip32 __user *c32 = user_ptr; 1041 u32 clipcount = f64->fmt.win.clipcount; 1042 1043 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1044 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1045 clipcount == 0) 1046 return 0; 1047 if (clipcount > 2048) 1048 return -EINVAL; 1049 while (clipcount--) { 1050 if (copy_from_user(c64, c32, sizeof(c64->c))) 1051 return -EFAULT; 1052 c64->next = NULL; 1053 c64++; 1054 c32++; 1055 } 1056 break; 1057 } 1058 case VIDIOC_QUERYBUF32_TIME32: 1059 case VIDIOC_QBUF32_TIME32: 1060 case VIDIOC_DQBUF32_TIME32: 1061 case VIDIOC_PREPARE_BUF32_TIME32: 1062 case VIDIOC_QUERYBUF32: 1063 case VIDIOC_QBUF32: 1064 case VIDIOC_DQBUF32: 1065 case VIDIOC_PREPARE_BUF32: { 1066 struct v4l2_buffer *b64 = arg; 1067 struct v4l2_plane *p64 = mbuf; 1068 struct v4l2_plane32 __user *p32 = user_ptr; 1069 1070 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1071 u32 num_planes = b64->length; 1072 1073 if (num_planes == 0) 1074 return 0; 1075 1076 while (num_planes--) { 1077 err = get_v4l2_plane32(p64, p32, b64->memory); 1078 if (err) 1079 return err; 1080 ++p64; 1081 ++p32; 1082 } 1083 } 1084 break; 1085 } 1086 case VIDIOC_G_EXT_CTRLS32: 1087 case VIDIOC_S_EXT_CTRLS32: 1088 case VIDIOC_TRY_EXT_CTRLS32: { 1089 struct v4l2_ext_controls *ecs64 = arg; 1090 struct v4l2_ext_control *ec64 = mbuf; 1091 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1092 int n; 1093 1094 for (n = 0; n < ecs64->count; n++) { 1095 if (copy_from_user(ec64, ec32, sizeof(*ec32))) 1096 return -EFAULT; 1097 1098 if (ctrl_is_pointer(file, ec64->id)) { 1099 compat_uptr_t p; 1100 1101 if (get_user(p, &ec32->string)) 1102 return -EFAULT; 1103 ec64->string = compat_ptr(p); 1104 } 1105 ec32++; 1106 ec64++; 1107 } 1108 break; 1109 } 1110 default: 1111 if (copy_from_user(mbuf, user_ptr, array_size)) 1112 err = -EFAULT; 1113 break; 1114 } 1115 1116 return err; 1117 } 1118 1119 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr, 1120 void *mbuf, size_t array_size, 1121 unsigned int cmd, void *arg) 1122 { 1123 int err = 0; 1124 1125 switch (cmd) { 1126 case VIDIOC_G_FMT32: 1127 case VIDIOC_S_FMT32: 1128 case VIDIOC_TRY_FMT32: { 1129 struct v4l2_format *f64 = arg; 1130 struct v4l2_clip *c64 = mbuf; 1131 struct v4l2_clip32 __user *c32 = user_ptr; 1132 u32 clipcount = f64->fmt.win.clipcount; 1133 1134 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1135 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1136 clipcount == 0) 1137 return 0; 1138 if (clipcount > 2048) 1139 return -EINVAL; 1140 while (clipcount--) { 1141 if (copy_to_user(c32, c64, sizeof(c64->c))) 1142 return -EFAULT; 1143 c64++; 1144 c32++; 1145 } 1146 break; 1147 } 1148 case VIDIOC_QUERYBUF32_TIME32: 1149 case VIDIOC_QBUF32_TIME32: 1150 case VIDIOC_DQBUF32_TIME32: 1151 case VIDIOC_PREPARE_BUF32_TIME32: 1152 case VIDIOC_QUERYBUF32: 1153 case VIDIOC_QBUF32: 1154 case VIDIOC_DQBUF32: 1155 case VIDIOC_PREPARE_BUF32: { 1156 struct v4l2_buffer *b64 = arg; 1157 struct v4l2_plane *p64 = mbuf; 1158 struct v4l2_plane32 __user *p32 = user_ptr; 1159 1160 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1161 u32 num_planes = b64->length; 1162 1163 if (num_planes == 0) 1164 return 0; 1165 1166 while (num_planes--) { 1167 err = put_v4l2_plane32(p64, p32, b64->memory); 1168 if (err) 1169 return err; 1170 ++p64; 1171 ++p32; 1172 } 1173 } 1174 break; 1175 } 1176 case VIDIOC_G_EXT_CTRLS32: 1177 case VIDIOC_S_EXT_CTRLS32: 1178 case VIDIOC_TRY_EXT_CTRLS32: { 1179 struct v4l2_ext_controls *ecs64 = arg; 1180 struct v4l2_ext_control *ec64 = mbuf; 1181 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1182 int n; 1183 1184 for (n = 0; n < ecs64->count; n++) { 1185 unsigned int size = sizeof(*ec32); 1186 /* 1187 * Do not modify the pointer when copying a pointer 1188 * control. The contents of the pointer was changed, 1189 * not the pointer itself. 1190 * The structures are otherwise compatible. 1191 */ 1192 if (ctrl_is_pointer(file, ec64->id)) 1193 size -= sizeof(ec32->value64); 1194 1195 if (copy_to_user(ec32, ec64, size)) 1196 return -EFAULT; 1197 1198 ec32++; 1199 ec64++; 1200 } 1201 break; 1202 } 1203 default: 1204 if (copy_to_user(user_ptr, mbuf, array_size)) 1205 err = -EFAULT; 1206 break; 1207 } 1208 1209 return err; 1210 } 1211 1212 /** 1213 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call 1214 * 1215 * @file: pointer to &struct file with the file handler 1216 * @cmd: ioctl to be called 1217 * @arg: arguments passed from/to the ioctl handler 1218 * 1219 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c 1220 * in order to deal with 32-bit calls on a 64-bits Kernel. 1221 * 1222 * This function calls do_video_ioctl() for non-private V4L2 ioctls. 1223 * If the function is a private one it calls vdev->fops->compat_ioctl32 1224 * instead. 1225 */ 1226 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 1227 { 1228 struct video_device *vdev = video_devdata(file); 1229 long ret = -ENOIOCTLCMD; 1230 1231 if (!file->f_op->unlocked_ioctl) 1232 return ret; 1233 1234 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE) 1235 ret = file->f_op->unlocked_ioctl(file, cmd, 1236 (unsigned long)compat_ptr(arg)); 1237 else if (vdev->fops->compat_ioctl32) 1238 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1239 1240 if (ret == -ENOIOCTLCMD) 1241 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1242 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); 1243 return ret; 1244 } 1245 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1246