Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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