linux/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
<<
>>
Prefs
   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-fh.h>
  22#include <media/v4l2-ctrls.h>
  23#include <media/v4l2-ioctl.h>
  24
  25/**
  26 * assign_in_user() - Copy from one __user var to another one
  27 *
  28 * @to: __user var where data will be stored
  29 * @from: __user var where data will be retrieved.
  30 *
  31 * As this code very often needs to allocate userspace memory, it is easier
  32 * to have a macro that will do both get_user() and put_user() at once.
  33 *
  34 * This function complements the macros defined at asm-generic/uaccess.h.
  35 * It uses the same argument order as copy_in_user()
  36 */
  37#define assign_in_user(to, from)                                        \
  38({                                                                      \
  39        typeof(*from) __assign_tmp;                                     \
  40                                                                        \
  41        get_user(__assign_tmp, from) || put_user(__assign_tmp, to);     \
  42})
  43
  44/**
  45 * get_user_cast() - Stores at a kernelspace local var the contents from a
  46 *              pointer with userspace data that is not tagged with __user.
  47 *
  48 * @__x: var where data will be stored
  49 * @__ptr: var where data will be retrieved.
  50 *
  51 * Sometimes we need to declare a pointer without __user because it
  52 * comes from a pointer struct field that will be retrieved from userspace
  53 * by the 64-bit native ioctl handler. This function ensures that the
  54 * @__ptr will be cast to __user before calling get_user() in order to
  55 * avoid warnings with static code analyzers like smatch.
  56 */
  57#define get_user_cast(__x, __ptr)                                       \
  58({                                                                      \
  59        get_user(__x, (typeof(*__ptr) __user *)(__ptr));                \
  60})
  61
  62/**
  63 * put_user_force() - Stores the contents of a kernelspace local var
  64 *                    into a userspace pointer, removing any __user cast.
  65 *
  66 * @__x: var where data will be stored
  67 * @__ptr: var where data will be retrieved.
  68 *
  69 * Sometimes we need to remove the __user attribute from some data,
  70 * by passing the __force macro. This function ensures that the
  71 * @__ptr will be cast with __force before calling put_user(), in order to
  72 * avoid warnings with static code analyzers like smatch.
  73 */
  74#define put_user_force(__x, __ptr)                                      \
  75({                                                                      \
  76        put_user((typeof(*__x) __force *)(__x), __ptr);                 \
  77})
  78
  79/**
  80 * assign_in_user_cast() - Copy from one __user var to another one
  81 *
  82 * @to: __user var where data will be stored
  83 * @from: var where data will be retrieved that needs to be cast to __user.
  84 *
  85 * As this code very often needs to allocate userspace memory, it is easier
  86 * to have a macro that will do both get_user_cast() and put_user() at once.
  87 *
  88 * This function should be used instead of assign_in_user() when the @from
  89 * variable was not declared as __user. See get_user_cast() for more details.
  90 *
  91 * This function complements the macros defined at asm-generic/uaccess.h.
  92 * It uses the same argument order as copy_in_user()
  93 */
  94#define assign_in_user_cast(to, from)                                   \
  95({                                                                      \
  96        typeof(*from) __assign_tmp;                                     \
  97                                                                        \
  98        get_user_cast(__assign_tmp, from) || put_user(__assign_tmp, to);\
  99})
 100
 101/**
 102 * native_ioctl - Ancillary function that calls the native 64 bits ioctl
 103 * handler.
 104 *
 105 * @file: pointer to &struct file with the file handler
 106 * @cmd: ioctl to be called
 107 * @arg: arguments passed from/to the ioctl handler
 108 *
 109 * This function calls the native ioctl handler at v4l2-dev, e. g. v4l2_ioctl()
 110 */
 111static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 112{
 113        long ret = -ENOIOCTLCMD;
 114
 115        if (file->f_op->unlocked_ioctl)
 116                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
 117
 118        return ret;
 119}
 120
 121
 122/*
 123 * Per-ioctl data copy handlers.
 124 *
 125 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
 126 * where "v4l2_foo" is the name of the V4L2 struct.
 127 *
 128 * They basically get two __user pointers, one with a 32-bits struct that
 129 * came from the userspace call and a 64-bits struct, also allocated as
 130 * userspace, but filled internally by do_video_ioctl().
 131 *
 132 * For ioctls that have pointers inside it, the functions will also
 133 * receive an ancillary buffer with extra space, used to pass extra
 134 * data to the routine.
 135 */
 136
 137struct v4l2_clip32 {
 138        struct v4l2_rect        c;
 139        compat_caddr_t          next;
 140};
 141
 142struct v4l2_window32 {
 143        struct v4l2_rect        w;
 144        __u32                   field;  /* enum v4l2_field */
 145        __u32                   chromakey;
 146        compat_caddr_t          clips; /* actually struct v4l2_clip32 * */
 147        __u32                   clipcount;
 148        compat_caddr_t          bitmap;
 149        __u8                    global_alpha;
 150};
 151
 152static int get_v4l2_window32(struct v4l2_window __user *p64,
 153                             struct v4l2_window32 __user *p32,
 154                             void __user *aux_buf, u32 aux_space)
 155{
 156        struct v4l2_clip32 __user *uclips;
 157        struct v4l2_clip __user *kclips;
 158        compat_caddr_t p;
 159        u32 clipcount;
 160
 161        if (!access_ok(p32, sizeof(*p32)) ||
 162            copy_in_user(&p64->w, &p32->w, sizeof(p32->w)) ||
 163            assign_in_user(&p64->field, &p32->field) ||
 164            assign_in_user(&p64->chromakey, &p32->chromakey) ||
 165            assign_in_user(&p64->global_alpha, &p32->global_alpha) ||
 166            get_user(clipcount, &p32->clipcount) ||
 167            put_user(clipcount, &p64->clipcount))
 168                return -EFAULT;
 169        if (clipcount > 2048)
 170                return -EINVAL;
 171        if (!clipcount)
 172                return put_user(NULL, &p64->clips);
 173
 174        if (get_user(p, &p32->clips))
 175                return -EFAULT;
 176        uclips = compat_ptr(p);
 177        if (aux_space < clipcount * sizeof(*kclips))
 178                return -EFAULT;
 179        kclips = aux_buf;
 180        if (put_user(kclips, &p64->clips))
 181                return -EFAULT;
 182
 183        while (clipcount--) {
 184                if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
 185                        return -EFAULT;
 186                if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
 187                        return -EFAULT;
 188                uclips++;
 189                kclips++;
 190        }
 191        return 0;
 192}
 193
 194static int put_v4l2_window32(struct v4l2_window __user *p64,
 195                             struct v4l2_window32 __user *p32)
 196{
 197        struct v4l2_clip __user *kclips;
 198        struct v4l2_clip32 __user *uclips;
 199        compat_caddr_t p;
 200        u32 clipcount;
 201
 202        if (copy_in_user(&p32->w, &p64->w, sizeof(p64->w)) ||
 203            assign_in_user(&p32->field, &p64->field) ||
 204            assign_in_user(&p32->chromakey, &p64->chromakey) ||
 205            assign_in_user(&p32->global_alpha, &p64->global_alpha) ||
 206            get_user(clipcount, &p64->clipcount) ||
 207            put_user(clipcount, &p32->clipcount))
 208                return -EFAULT;
 209        if (!clipcount)
 210                return 0;
 211
 212        if (get_user(kclips, &p64->clips))
 213                return -EFAULT;
 214        if (get_user(p, &p32->clips))
 215                return -EFAULT;
 216        uclips = compat_ptr(p);
 217        while (clipcount--) {
 218                if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
 219                        return -EFAULT;
 220                uclips++;
 221                kclips++;
 222        }
 223        return 0;
 224}
 225
 226struct v4l2_format32 {
 227        __u32   type;   /* enum v4l2_buf_type */
 228        union {
 229                struct v4l2_pix_format  pix;
 230                struct v4l2_pix_format_mplane   pix_mp;
 231                struct v4l2_window32    win;
 232                struct v4l2_vbi_format  vbi;
 233                struct v4l2_sliced_vbi_format   sliced;
 234                struct v4l2_sdr_format  sdr;
 235                struct v4l2_meta_format meta;
 236                __u8    raw_data[200];        /* user-defined */
 237        } fmt;
 238};
 239
 240/**
 241 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
 242 * @index:      on return, index of the first created buffer
 243 * @count:      entry: number of requested buffers,
 244 *              return: number of created buffers
 245 * @memory:     buffer memory type
 246 * @format:     frame format, for which buffers are requested
 247 * @reserved:   future extensions
 248 */
 249struct v4l2_create_buffers32 {
 250        __u32                   index;
 251        __u32                   count;
 252        __u32                   memory; /* enum v4l2_memory */
 253        struct v4l2_format32    format;
 254        __u32                   reserved[8];
 255};
 256
 257static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
 258{
 259        u32 type;
 260
 261        if (get_user(type, &p32->type))
 262                return -EFAULT;
 263
 264        switch (type) {
 265        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 266        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
 267                u32 clipcount;
 268
 269                if (get_user(clipcount, &p32->fmt.win.clipcount))
 270                        return -EFAULT;
 271                if (clipcount > 2048)
 272                        return -EINVAL;
 273                *size = clipcount * sizeof(struct v4l2_clip);
 274                return 0;
 275        }
 276        default:
 277                *size = 0;
 278                return 0;
 279        }
 280}
 281
 282static int bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
 283{
 284        if (!access_ok(p32, sizeof(*p32)))
 285                return -EFAULT;
 286        return __bufsize_v4l2_format(p32, size);
 287}
 288
 289static int __get_v4l2_format32(struct v4l2_format __user *p64,
 290                               struct v4l2_format32 __user *p32,
 291                               void __user *aux_buf, u32 aux_space)
 292{
 293        u32 type;
 294
 295        if (get_user(type, &p32->type) || put_user(type, &p64->type))
 296                return -EFAULT;
 297
 298        switch (type) {
 299        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 300        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 301                return copy_in_user(&p64->fmt.pix, &p32->fmt.pix,
 302                                    sizeof(p64->fmt.pix)) ? -EFAULT : 0;
 303        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 304        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 305                return copy_in_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
 306                                    sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
 307        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 308        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 309                return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win,
 310                                         aux_buf, aux_space);
 311        case V4L2_BUF_TYPE_VBI_CAPTURE:
 312        case V4L2_BUF_TYPE_VBI_OUTPUT:
 313                return copy_in_user(&p64->fmt.vbi, &p32->fmt.vbi,
 314                                    sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
 315        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 316        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 317                return copy_in_user(&p64->fmt.sliced, &p32->fmt.sliced,
 318                                    sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
 319        case V4L2_BUF_TYPE_SDR_CAPTURE:
 320        case V4L2_BUF_TYPE_SDR_OUTPUT:
 321                return copy_in_user(&p64->fmt.sdr, &p32->fmt.sdr,
 322                                    sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
 323        case V4L2_BUF_TYPE_META_CAPTURE:
 324        case V4L2_BUF_TYPE_META_OUTPUT:
 325                return copy_in_user(&p64->fmt.meta, &p32->fmt.meta,
 326                                    sizeof(p64->fmt.meta)) ? -EFAULT : 0;
 327        default:
 328                return -EINVAL;
 329        }
 330}
 331
 332static int get_v4l2_format32(struct v4l2_format __user *p64,
 333                             struct v4l2_format32 __user *p32,
 334                             void __user *aux_buf, u32 aux_space)
 335{
 336        if (!access_ok(p32, sizeof(*p32)))
 337                return -EFAULT;
 338        return __get_v4l2_format32(p64, p32, aux_buf, aux_space);
 339}
 340
 341static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *p32,
 342                               u32 *size)
 343{
 344        if (!access_ok(p32, sizeof(*p32)))
 345                return -EFAULT;
 346        return __bufsize_v4l2_format(&p32->format, size);
 347}
 348
 349static int get_v4l2_create32(struct v4l2_create_buffers __user *p64,
 350                             struct v4l2_create_buffers32 __user *p32,
 351                             void __user *aux_buf, u32 aux_space)
 352{
 353        if (!access_ok(p32, sizeof(*p32)) ||
 354            copy_in_user(p64, p32,
 355                         offsetof(struct v4l2_create_buffers32, format)))
 356                return -EFAULT;
 357        return __get_v4l2_format32(&p64->format, &p32->format,
 358                                   aux_buf, aux_space);
 359}
 360
 361static int __put_v4l2_format32(struct v4l2_format __user *p64,
 362                               struct v4l2_format32 __user *p32)
 363{
 364        u32 type;
 365
 366        if (get_user(type, &p64->type))
 367                return -EFAULT;
 368
 369        switch (type) {
 370        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 371        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 372                return copy_in_user(&p32->fmt.pix, &p64->fmt.pix,
 373                                    sizeof(p64->fmt.pix)) ? -EFAULT : 0;
 374        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 375        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 376                return copy_in_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
 377                                    sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
 378        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 379        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 380                return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
 381        case V4L2_BUF_TYPE_VBI_CAPTURE:
 382        case V4L2_BUF_TYPE_VBI_OUTPUT:
 383                return copy_in_user(&p32->fmt.vbi, &p64->fmt.vbi,
 384                                    sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
 385        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 386        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 387                return copy_in_user(&p32->fmt.sliced, &p64->fmt.sliced,
 388                                    sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
 389        case V4L2_BUF_TYPE_SDR_CAPTURE:
 390        case V4L2_BUF_TYPE_SDR_OUTPUT:
 391                return copy_in_user(&p32->fmt.sdr, &p64->fmt.sdr,
 392                                    sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
 393        case V4L2_BUF_TYPE_META_CAPTURE:
 394        case V4L2_BUF_TYPE_META_OUTPUT:
 395                return copy_in_user(&p32->fmt.meta, &p64->fmt.meta,
 396                                    sizeof(p64->fmt.meta)) ? -EFAULT : 0;
 397        default:
 398                return -EINVAL;
 399        }
 400}
 401
 402static int put_v4l2_format32(struct v4l2_format __user *p64,
 403                             struct v4l2_format32 __user *p32)
 404{
 405        if (!access_ok(p32, sizeof(*p32)))
 406                return -EFAULT;
 407        return __put_v4l2_format32(p64, p32);
 408}
 409
 410static int put_v4l2_create32(struct v4l2_create_buffers __user *p64,
 411                             struct v4l2_create_buffers32 __user *p32)
 412{
 413        if (!access_ok(p32, sizeof(*p32)) ||
 414            copy_in_user(p32, p64,
 415                         offsetof(struct v4l2_create_buffers32, format)) ||
 416            copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
 417                return -EFAULT;
 418        return __put_v4l2_format32(&p64->format, &p32->format);
 419}
 420
 421struct v4l2_standard32 {
 422        __u32                index;
 423        compat_u64           id;
 424        __u8                 name[24];
 425        struct v4l2_fract    frameperiod; /* Frames, not fields */
 426        __u32                framelines;
 427        __u32                reserved[4];
 428};
 429
 430static int get_v4l2_standard32(struct v4l2_standard __user *p64,
 431                               struct v4l2_standard32 __user *p32)
 432{
 433        /* other fields are not set by the user, nor used by the driver */
 434        if (!access_ok(p32, sizeof(*p32)) ||
 435            assign_in_user(&p64->index, &p32->index))
 436                return -EFAULT;
 437        return 0;
 438}
 439
 440static int put_v4l2_standard32(struct v4l2_standard __user *p64,
 441                               struct v4l2_standard32 __user *p32)
 442{
 443        if (!access_ok(p32, sizeof(*p32)) ||
 444            assign_in_user(&p32->index, &p64->index) ||
 445            assign_in_user(&p32->id, &p64->id) ||
 446            copy_in_user(p32->name, p64->name, sizeof(p32->name)) ||
 447            copy_in_user(&p32->frameperiod, &p64->frameperiod,
 448                         sizeof(p32->frameperiod)) ||
 449            assign_in_user(&p32->framelines, &p64->framelines) ||
 450            copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
 451                return -EFAULT;
 452        return 0;
 453}
 454
 455struct v4l2_plane32 {
 456        __u32                   bytesused;
 457        __u32                   length;
 458        union {
 459                __u32           mem_offset;
 460                compat_long_t   userptr;
 461                __s32           fd;
 462        } m;
 463        __u32                   data_offset;
 464        __u32                   reserved[11];
 465};
 466
 467struct v4l2_buffer32 {
 468        __u32                   index;
 469        __u32                   type;   /* enum v4l2_buf_type */
 470        __u32                   bytesused;
 471        __u32                   flags;
 472        __u32                   field;  /* enum v4l2_field */
 473        struct compat_timeval   timestamp;
 474        struct v4l2_timecode    timecode;
 475        __u32                   sequence;
 476
 477        /* memory location */
 478        __u32                   memory; /* enum v4l2_memory */
 479        union {
 480                __u32           offset;
 481                compat_long_t   userptr;
 482                compat_caddr_t  planes;
 483                __s32           fd;
 484        } m;
 485        __u32                   length;
 486        __u32                   reserved2;
 487        __u32                   reserved;
 488};
 489
 490static int get_v4l2_plane32(struct v4l2_plane __user *p64,
 491                            struct v4l2_plane32 __user *p32,
 492                            enum v4l2_memory memory)
 493{
 494        compat_ulong_t p;
 495
 496        if (copy_in_user(p64, p32, 2 * sizeof(__u32)) ||
 497            copy_in_user(&p64->data_offset, &p32->data_offset,
 498                         sizeof(p64->data_offset)))
 499                return -EFAULT;
 500
 501        switch (memory) {
 502        case V4L2_MEMORY_MMAP:
 503        case V4L2_MEMORY_OVERLAY:
 504                if (copy_in_user(&p64->m.mem_offset, &p32->m.mem_offset,
 505                                 sizeof(p32->m.mem_offset)))
 506                        return -EFAULT;
 507                break;
 508        case V4L2_MEMORY_USERPTR:
 509                if (get_user(p, &p32->m.userptr) ||
 510                    put_user((unsigned long)compat_ptr(p), &p64->m.userptr))
 511                        return -EFAULT;
 512                break;
 513        case V4L2_MEMORY_DMABUF:
 514                if (copy_in_user(&p64->m.fd, &p32->m.fd, sizeof(p32->m.fd)))
 515                        return -EFAULT;
 516                break;
 517        }
 518
 519        return 0;
 520}
 521
 522static int put_v4l2_plane32(struct v4l2_plane __user *p64,
 523                            struct v4l2_plane32 __user *p32,
 524                            enum v4l2_memory memory)
 525{
 526        unsigned long p;
 527
 528        if (copy_in_user(p32, p64, 2 * sizeof(__u32)) ||
 529            copy_in_user(&p32->data_offset, &p64->data_offset,
 530                         sizeof(p64->data_offset)))
 531                return -EFAULT;
 532
 533        switch (memory) {
 534        case V4L2_MEMORY_MMAP:
 535        case V4L2_MEMORY_OVERLAY:
 536                if (copy_in_user(&p32->m.mem_offset, &p64->m.mem_offset,
 537                                 sizeof(p64->m.mem_offset)))
 538                        return -EFAULT;
 539                break;
 540        case V4L2_MEMORY_USERPTR:
 541                if (get_user(p, &p64->m.userptr) ||
 542                    put_user((compat_ulong_t)ptr_to_compat((void __user *)p),
 543                             &p32->m.userptr))
 544                        return -EFAULT;
 545                break;
 546        case V4L2_MEMORY_DMABUF:
 547                if (copy_in_user(&p32->m.fd, &p64->m.fd, sizeof(p64->m.fd)))
 548                        return -EFAULT;
 549                break;
 550        }
 551
 552        return 0;
 553}
 554
 555static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *p32, u32 *size)
 556{
 557        u32 type;
 558        u32 length;
 559
 560        if (!access_ok(p32, sizeof(*p32)) ||
 561            get_user(type, &p32->type) ||
 562            get_user(length, &p32->length))
 563                return -EFAULT;
 564
 565        if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
 566                if (length > VIDEO_MAX_PLANES)
 567                        return -EINVAL;
 568
 569                /*
 570                 * We don't really care if userspace decides to kill itself
 571                 * by passing a very big length value
 572                 */
 573                *size = length * sizeof(struct v4l2_plane);
 574        } else {
 575                *size = 0;
 576        }
 577        return 0;
 578}
 579
 580static int get_v4l2_buffer32(struct v4l2_buffer __user *p64,
 581                             struct v4l2_buffer32 __user *p32,
 582                             void __user *aux_buf, u32 aux_space)
 583{
 584        u32 type;
 585        u32 length;
 586        enum v4l2_memory memory;
 587        struct v4l2_plane32 __user *uplane32;
 588        struct v4l2_plane __user *uplane;
 589        compat_caddr_t p;
 590        int ret;
 591
 592        if (!access_ok(p32, sizeof(*p32)) ||
 593            assign_in_user(&p64->index, &p32->index) ||
 594            get_user(type, &p32->type) ||
 595            put_user(type, &p64->type) ||
 596            assign_in_user(&p64->flags, &p32->flags) ||
 597            get_user(memory, &p32->memory) ||
 598            put_user(memory, &p64->memory) ||
 599            get_user(length, &p32->length) ||
 600            put_user(length, &p64->length))
 601                return -EFAULT;
 602
 603        if (V4L2_TYPE_IS_OUTPUT(type))
 604                if (assign_in_user(&p64->bytesused, &p32->bytesused) ||
 605                    assign_in_user(&p64->field, &p32->field) ||
 606                    assign_in_user(&p64->timestamp.tv_sec,
 607                                   &p32->timestamp.tv_sec) ||
 608                    assign_in_user(&p64->timestamp.tv_usec,
 609                                   &p32->timestamp.tv_usec))
 610                        return -EFAULT;
 611
 612        if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
 613                u32 num_planes = length;
 614
 615                if (num_planes == 0) {
 616                        /*
 617                         * num_planes == 0 is legal, e.g. when userspace doesn't
 618                         * need planes array on DQBUF
 619                         */
 620                        return put_user(NULL, &p64->m.planes);
 621                }
 622                if (num_planes > VIDEO_MAX_PLANES)
 623                        return -EINVAL;
 624
 625                if (get_user(p, &p32->m.planes))
 626                        return -EFAULT;
 627
 628                uplane32 = compat_ptr(p);
 629                if (!access_ok(uplane32,
 630                               num_planes * sizeof(*uplane32)))
 631                        return -EFAULT;
 632
 633                /*
 634                 * We don't really care if userspace decides to kill itself
 635                 * by passing a very big num_planes value
 636                 */
 637                if (aux_space < num_planes * sizeof(*uplane))
 638                        return -EFAULT;
 639
 640                uplane = aux_buf;
 641                if (put_user_force(uplane, &p64->m.planes))
 642                        return -EFAULT;
 643
 644                while (num_planes--) {
 645                        ret = get_v4l2_plane32(uplane, uplane32, memory);
 646                        if (ret)
 647                                return ret;
 648                        uplane++;
 649                        uplane32++;
 650                }
 651        } else {
 652                switch (memory) {
 653                case V4L2_MEMORY_MMAP:
 654                case V4L2_MEMORY_OVERLAY:
 655                        if (assign_in_user(&p64->m.offset, &p32->m.offset))
 656                                return -EFAULT;
 657                        break;
 658                case V4L2_MEMORY_USERPTR: {
 659                        compat_ulong_t userptr;
 660
 661                        if (get_user(userptr, &p32->m.userptr) ||
 662                            put_user((unsigned long)compat_ptr(userptr),
 663                                     &p64->m.userptr))
 664                                return -EFAULT;
 665                        break;
 666                }
 667                case V4L2_MEMORY_DMABUF:
 668                        if (assign_in_user(&p64->m.fd, &p32->m.fd))
 669                                return -EFAULT;
 670                        break;
 671                }
 672        }
 673
 674        return 0;
 675}
 676
 677static int put_v4l2_buffer32(struct v4l2_buffer __user *p64,
 678                             struct v4l2_buffer32 __user *p32)
 679{
 680        u32 type;
 681        u32 length;
 682        enum v4l2_memory memory;
 683        struct v4l2_plane32 __user *uplane32;
 684        struct v4l2_plane *uplane;
 685        compat_caddr_t p;
 686        int ret;
 687
 688        if (!access_ok(p32, sizeof(*p32)) ||
 689            assign_in_user(&p32->index, &p64->index) ||
 690            get_user(type, &p64->type) ||
 691            put_user(type, &p32->type) ||
 692            assign_in_user(&p32->flags, &p64->flags) ||
 693            get_user(memory, &p64->memory) ||
 694            put_user(memory, &p32->memory))
 695                return -EFAULT;
 696
 697        if (assign_in_user(&p32->bytesused, &p64->bytesused) ||
 698            assign_in_user(&p32->field, &p64->field) ||
 699            assign_in_user(&p32->timestamp.tv_sec, &p64->timestamp.tv_sec) ||
 700            assign_in_user(&p32->timestamp.tv_usec, &p64->timestamp.tv_usec) ||
 701            copy_in_user(&p32->timecode, &p64->timecode, sizeof(p64->timecode)) ||
 702            assign_in_user(&p32->sequence, &p64->sequence) ||
 703            assign_in_user(&p32->reserved2, &p64->reserved2) ||
 704            assign_in_user(&p32->reserved, &p64->reserved) ||
 705            get_user(length, &p64->length) ||
 706            put_user(length, &p32->length))
 707                return -EFAULT;
 708
 709        if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
 710                u32 num_planes = length;
 711
 712                if (num_planes == 0)
 713                        return 0;
 714                /* We need to define uplane without __user, even though
 715                 * it does point to data in userspace here. The reason is
 716                 * that v4l2-ioctl.c copies it from userspace to kernelspace,
 717                 * so its definition in videodev2.h doesn't have a
 718                 * __user markup. Defining uplane with __user causes
 719                 * smatch warnings, so instead declare it without __user
 720                 * and cast it as a userspace pointer to put_v4l2_plane32().
 721                 */
 722                if (get_user(uplane, &p64->m.planes))
 723                        return -EFAULT;
 724                if (get_user(p, &p32->m.planes))
 725                        return -EFAULT;
 726                uplane32 = compat_ptr(p);
 727
 728                while (num_planes--) {
 729                        ret = put_v4l2_plane32((void __user *)uplane,
 730                                               uplane32, memory);
 731                        if (ret)
 732                                return ret;
 733                        ++uplane;
 734                        ++uplane32;
 735                }
 736        } else {
 737                switch (memory) {
 738                case V4L2_MEMORY_MMAP:
 739                case V4L2_MEMORY_OVERLAY:
 740                        if (assign_in_user(&p32->m.offset, &p64->m.offset))
 741                                return -EFAULT;
 742                        break;
 743                case V4L2_MEMORY_USERPTR:
 744                        if (assign_in_user(&p32->m.userptr, &p64->m.userptr))
 745                                return -EFAULT;
 746                        break;
 747                case V4L2_MEMORY_DMABUF:
 748                        if (assign_in_user(&p32->m.fd, &p64->m.fd))
 749                                return -EFAULT;
 750                        break;
 751                }
 752        }
 753
 754        return 0;
 755}
 756
 757struct v4l2_framebuffer32 {
 758        __u32                   capability;
 759        __u32                   flags;
 760        compat_caddr_t          base;
 761        struct {
 762                __u32           width;
 763                __u32           height;
 764                __u32           pixelformat;
 765                __u32           field;
 766                __u32           bytesperline;
 767                __u32           sizeimage;
 768                __u32           colorspace;
 769                __u32           priv;
 770        } fmt;
 771};
 772
 773static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *p64,
 774                                  struct v4l2_framebuffer32 __user *p32)
 775{
 776        compat_caddr_t tmp;
 777
 778        if (!access_ok(p32, sizeof(*p32)) ||
 779            get_user(tmp, &p32->base) ||
 780            put_user_force(compat_ptr(tmp), &p64->base) ||
 781            assign_in_user(&p64->capability, &p32->capability) ||
 782            assign_in_user(&p64->flags, &p32->flags) ||
 783            copy_in_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
 784                return -EFAULT;
 785        return 0;
 786}
 787
 788static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *p64,
 789                                  struct v4l2_framebuffer32 __user *p32)
 790{
 791        void *base;
 792
 793        if (!access_ok(p32, sizeof(*p32)) ||
 794            get_user(base, &p64->base) ||
 795            put_user(ptr_to_compat((void __user *)base), &p32->base) ||
 796            assign_in_user(&p32->capability, &p64->capability) ||
 797            assign_in_user(&p32->flags, &p64->flags) ||
 798            copy_in_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
 799                return -EFAULT;
 800        return 0;
 801}
 802
 803struct v4l2_input32 {
 804        __u32        index;             /*  Which input */
 805        __u8         name[32];          /*  Label */
 806        __u32        type;              /*  Type of input */
 807        __u32        audioset;          /*  Associated audios (bitfield) */
 808        __u32        tuner;             /*  Associated tuner */
 809        compat_u64   std;
 810        __u32        status;
 811        __u32        capabilities;
 812        __u32        reserved[3];
 813};
 814
 815/*
 816 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
 817 * Otherwise it is identical to the 32-bit version.
 818 */
 819static inline int get_v4l2_input32(struct v4l2_input __user *p64,
 820                                   struct v4l2_input32 __user *p32)
 821{
 822        if (copy_in_user(p64, p32, sizeof(*p32)))
 823                return -EFAULT;
 824        return 0;
 825}
 826
 827static inline int put_v4l2_input32(struct v4l2_input __user *p64,
 828                                   struct v4l2_input32 __user *p32)
 829{
 830        if (copy_in_user(p32, p64, sizeof(*p32)))
 831                return -EFAULT;
 832        return 0;
 833}
 834
 835struct v4l2_ext_controls32 {
 836        __u32 which;
 837        __u32 count;
 838        __u32 error_idx;
 839        __s32 request_fd;
 840        __u32 reserved[1];
 841        compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 842};
 843
 844struct v4l2_ext_control32 {
 845        __u32 id;
 846        __u32 size;
 847        __u32 reserved2[1];
 848        union {
 849                __s32 value;
 850                __s64 value64;
 851                compat_caddr_t string; /* actually char * */
 852        };
 853} __attribute__ ((packed));
 854
 855/* Return true if this control is a pointer type. */
 856static inline bool ctrl_is_pointer(struct file *file, u32 id)
 857{
 858        struct video_device *vdev = video_devdata(file);
 859        struct v4l2_fh *fh = NULL;
 860        struct v4l2_ctrl_handler *hdl = NULL;
 861        struct v4l2_query_ext_ctrl qec = { id };
 862        const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
 863
 864        if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
 865                fh = file->private_data;
 866
 867        if (fh && fh->ctrl_handler)
 868                hdl = fh->ctrl_handler;
 869        else if (vdev->ctrl_handler)
 870                hdl = vdev->ctrl_handler;
 871
 872        if (hdl) {
 873                struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
 874
 875                return ctrl && ctrl->is_ptr;
 876        }
 877
 878        if (!ops || !ops->vidioc_query_ext_ctrl)
 879                return false;
 880
 881        return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
 882                (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 883}
 884
 885static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *p32,
 886                                     u32 *size)
 887{
 888        u32 count;
 889
 890        if (!access_ok(p32, sizeof(*p32)) ||
 891            get_user(count, &p32->count))
 892                return -EFAULT;
 893        if (count > V4L2_CID_MAX_CTRLS)
 894                return -EINVAL;
 895        *size = count * sizeof(struct v4l2_ext_control);
 896        return 0;
 897}
 898
 899static int get_v4l2_ext_controls32(struct file *file,
 900                                   struct v4l2_ext_controls __user *p64,
 901                                   struct v4l2_ext_controls32 __user *p32,
 902                                   void __user *aux_buf, u32 aux_space)
 903{
 904        struct v4l2_ext_control32 __user *ucontrols;
 905        struct v4l2_ext_control __user *kcontrols;
 906        u32 count;
 907        u32 n;
 908        compat_caddr_t p;
 909
 910        if (!access_ok(p32, sizeof(*p32)) ||
 911            assign_in_user(&p64->which, &p32->which) ||
 912            get_user(count, &p32->count) ||
 913            put_user(count, &p64->count) ||
 914            assign_in_user(&p64->error_idx, &p32->error_idx) ||
 915            assign_in_user(&p64->request_fd, &p32->request_fd) ||
 916            copy_in_user(p64->reserved, p32->reserved, sizeof(p64->reserved)))
 917                return -EFAULT;
 918
 919        if (count == 0)
 920                return put_user(NULL, &p64->controls);
 921        if (count > V4L2_CID_MAX_CTRLS)
 922                return -EINVAL;
 923        if (get_user(p, &p32->controls))
 924                return -EFAULT;
 925        ucontrols = compat_ptr(p);
 926        if (!access_ok(ucontrols, count * sizeof(*ucontrols)))
 927                return -EFAULT;
 928        if (aux_space < count * sizeof(*kcontrols))
 929                return -EFAULT;
 930        kcontrols = aux_buf;
 931        if (put_user_force(kcontrols, &p64->controls))
 932                return -EFAULT;
 933
 934        for (n = 0; n < count; n++) {
 935                u32 id;
 936
 937                if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
 938                        return -EFAULT;
 939
 940                if (get_user(id, &kcontrols->id))
 941                        return -EFAULT;
 942
 943                if (ctrl_is_pointer(file, id)) {
 944                        void __user *s;
 945
 946                        if (get_user(p, &ucontrols->string))
 947                                return -EFAULT;
 948                        s = compat_ptr(p);
 949                        if (put_user(s, &kcontrols->string))
 950                                return -EFAULT;
 951                }
 952                ucontrols++;
 953                kcontrols++;
 954        }
 955        return 0;
 956}
 957
 958static int put_v4l2_ext_controls32(struct file *file,
 959                                   struct v4l2_ext_controls __user *p64,
 960                                   struct v4l2_ext_controls32 __user *p32)
 961{
 962        struct v4l2_ext_control32 __user *ucontrols;
 963        struct v4l2_ext_control *kcontrols;
 964        u32 count;
 965        u32 n;
 966        compat_caddr_t p;
 967
 968        /*
 969         * We need to define kcontrols without __user, even though it does
 970         * point to data in userspace here. The reason is that v4l2-ioctl.c
 971         * copies it from userspace to kernelspace, so its definition in
 972         * videodev2.h doesn't have a __user markup. Defining kcontrols
 973         * with __user causes smatch warnings, so instead declare it
 974         * without __user and cast it as a userspace pointer where needed.
 975         */
 976        if (!access_ok(p32, sizeof(*p32)) ||
 977            assign_in_user(&p32->which, &p64->which) ||
 978            get_user(count, &p64->count) ||
 979            put_user(count, &p32->count) ||
 980            assign_in_user(&p32->error_idx, &p64->error_idx) ||
 981            assign_in_user(&p32->request_fd, &p64->request_fd) ||
 982            copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)) ||
 983            get_user(kcontrols, &p64->controls))
 984                return -EFAULT;
 985
 986        if (!count || count > (U32_MAX/sizeof(*ucontrols)))
 987                return 0;
 988        if (get_user(p, &p32->controls))
 989                return -EFAULT;
 990        ucontrols = compat_ptr(p);
 991        if (!access_ok(ucontrols, count * sizeof(*ucontrols)))
 992                return -EFAULT;
 993
 994        for (n = 0; n < count; n++) {
 995                unsigned int size = sizeof(*ucontrols);
 996                u32 id;
 997
 998                if (get_user_cast(id, &kcontrols->id) ||
 999                    put_user(id, &ucontrols->id) ||
1000                    assign_in_user_cast(&ucontrols->size, &kcontrols->size) ||
1001                    copy_in_user(&ucontrols->reserved2,
1002                                 (void __user *)&kcontrols->reserved2,
1003                                 sizeof(ucontrols->reserved2)))
1004                        return -EFAULT;
1005
1006                /*
1007                 * Do not modify the pointer when copying a pointer control.
1008                 * The contents of the pointer was changed, not the pointer
1009                 * itself.
1010                 */
1011                if (ctrl_is_pointer(file, id))
1012                        size -= sizeof(ucontrols->value64);
1013
1014                if (copy_in_user(ucontrols,
1015                                 (void __user *)kcontrols, size))
1016                        return -EFAULT;
1017
1018                ucontrols++;
1019                kcontrols++;
1020        }
1021        return 0;
1022}
1023
1024struct v4l2_event32 {
1025        __u32                           type;
1026        union {
1027                compat_s64              value64;
1028                __u8                    data[64];
1029        } u;
1030        __u32                           pending;
1031        __u32                           sequence;
1032        struct compat_timespec          timestamp;
1033        __u32                           id;
1034        __u32                           reserved[8];
1035};
1036
1037static int put_v4l2_event32(struct v4l2_event __user *p64,
1038                            struct v4l2_event32 __user *p32)
1039{
1040        if (!access_ok(p32, sizeof(*p32)) ||
1041            assign_in_user(&p32->type, &p64->type) ||
1042            copy_in_user(&p32->u, &p64->u, sizeof(p64->u)) ||
1043            assign_in_user(&p32->pending, &p64->pending) ||
1044            assign_in_user(&p32->sequence, &p64->sequence) ||
1045            assign_in_user(&p32->timestamp.tv_sec, &p64->timestamp.tv_sec) ||
1046            assign_in_user(&p32->timestamp.tv_nsec, &p64->timestamp.tv_nsec) ||
1047            assign_in_user(&p32->id, &p64->id) ||
1048            copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
1049                return -EFAULT;
1050        return 0;
1051}
1052
1053struct v4l2_edid32 {
1054        __u32 pad;
1055        __u32 start_block;
1056        __u32 blocks;
1057        __u32 reserved[5];
1058        compat_caddr_t edid;
1059};
1060
1061static int get_v4l2_edid32(struct v4l2_edid __user *p64,
1062                           struct v4l2_edid32 __user *p32)
1063{
1064        compat_uptr_t tmp;
1065
1066        if (!access_ok(p32, sizeof(*p32)) ||
1067            assign_in_user(&p64->pad, &p32->pad) ||
1068            assign_in_user(&p64->start_block, &p32->start_block) ||
1069            assign_in_user_cast(&p64->blocks, &p32->blocks) ||
1070            get_user(tmp, &p32->edid) ||
1071            put_user_force(compat_ptr(tmp), &p64->edid) ||
1072            copy_in_user(p64->reserved, p32->reserved, sizeof(p64->reserved)))
1073                return -EFAULT;
1074        return 0;
1075}
1076
1077static int put_v4l2_edid32(struct v4l2_edid __user *p64,
1078                           struct v4l2_edid32 __user *p32)
1079{
1080        void *edid;
1081
1082        if (!access_ok(p32, sizeof(*p32)) ||
1083            assign_in_user(&p32->pad, &p64->pad) ||
1084            assign_in_user(&p32->start_block, &p64->start_block) ||
1085            assign_in_user(&p32->blocks, &p64->blocks) ||
1086            get_user(edid, &p64->edid) ||
1087            put_user(ptr_to_compat((void __user *)edid), &p32->edid) ||
1088            copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
1089                return -EFAULT;
1090        return 0;
1091}
1092
1093/*
1094 * List of ioctls that require 32-bits/64-bits conversion
1095 *
1096 * The V4L2 ioctls that aren't listed there don't have pointer arguments
1097 * and the struct size is identical for both 32 and 64 bits versions, so
1098 * they don't need translations.
1099 */
1100
1101#define VIDIOC_G_FMT32          _IOWR('V',  4, struct v4l2_format32)
1102#define VIDIOC_S_FMT32          _IOWR('V',  5, struct v4l2_format32)
1103#define VIDIOC_QUERYBUF32       _IOWR('V',  9, struct v4l2_buffer32)
1104#define VIDIOC_G_FBUF32         _IOR ('V', 10, struct v4l2_framebuffer32)
1105#define VIDIOC_S_FBUF32         _IOW ('V', 11, struct v4l2_framebuffer32)
1106#define VIDIOC_QBUF32           _IOWR('V', 15, struct v4l2_buffer32)
1107#define VIDIOC_DQBUF32          _IOWR('V', 17, struct v4l2_buffer32)
1108#define VIDIOC_ENUMSTD32        _IOWR('V', 25, struct v4l2_standard32)
1109#define VIDIOC_ENUMINPUT32      _IOWR('V', 26, struct v4l2_input32)
1110#define VIDIOC_G_EDID32         _IOWR('V', 40, struct v4l2_edid32)
1111#define VIDIOC_S_EDID32         _IOWR('V', 41, struct v4l2_edid32)
1112#define VIDIOC_TRY_FMT32        _IOWR('V', 64, struct v4l2_format32)
1113#define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
1114#define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
1115#define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
1116#define VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
1117#define VIDIOC_CREATE_BUFS32    _IOWR('V', 92, struct v4l2_create_buffers32)
1118#define VIDIOC_PREPARE_BUF32    _IOWR('V', 93, struct v4l2_buffer32)
1119
1120#define VIDIOC_OVERLAY32        _IOW ('V', 14, s32)
1121#define VIDIOC_STREAMON32       _IOW ('V', 18, s32)
1122#define VIDIOC_STREAMOFF32      _IOW ('V', 19, s32)
1123#define VIDIOC_G_INPUT32        _IOR ('V', 38, s32)
1124#define VIDIOC_S_INPUT32        _IOWR('V', 39, s32)
1125#define VIDIOC_G_OUTPUT32       _IOR ('V', 46, s32)
1126#define VIDIOC_S_OUTPUT32       _IOWR('V', 47, s32)
1127
1128/**
1129 * alloc_userspace() - Allocates a 64-bits userspace pointer compatible
1130 *      for calling the native 64-bits version of an ioctl.
1131 *
1132 * @size:       size of the structure itself to be allocated.
1133 * @aux_space:  extra size needed to store "extra" data, e.g. space for
1134 *              other __user data that is pointed to fields inside the
1135 *              structure.
1136 * @new_p64:    pointer to a pointer to be filled with the allocated struct.
1137 *
1138 * Return:
1139 *
1140 * if it can't allocate memory, either -ENOMEM or -EFAULT will be returned.
1141 * Zero otherwise.
1142 */
1143static int alloc_userspace(unsigned int size, u32 aux_space,
1144                           void __user **new_p64)
1145{
1146        *new_p64 = compat_alloc_user_space(size + aux_space);
1147        if (!*new_p64)
1148                return -ENOMEM;
1149        if (clear_user(*new_p64, size))
1150                return -EFAULT;
1151        return 0;
1152}
1153
1154/**
1155 * do_video_ioctl() - Ancillary function with handles a compat32 ioctl call
1156 *
1157 * @file: pointer to &struct file with the file handler
1158 * @cmd: ioctl to be called
1159 * @arg: arguments passed from/to the ioctl handler
1160 *
1161 * This function is called when a 32 bits application calls a V4L2 ioctl
1162 * and the Kernel is compiled with 64 bits.
1163 *
1164 * This function is called by v4l2_compat_ioctl32() when the function is
1165 * not private to some specific driver.
1166 *
1167 * It converts a 32-bits struct into a 64 bits one, calls the native 64-bits
1168 * ioctl handler and fills back the 32-bits struct with the results of the
1169 * native call.
1170 */
1171static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1172{
1173        void __user *p32 = compat_ptr(arg);
1174        void __user *new_p64 = NULL;
1175        void __user *aux_buf;
1176        u32 aux_space;
1177        int compatible_arg = 1;
1178        long err = 0;
1179
1180        /*
1181         * 1. When struct size is different, converts the command.
1182         */
1183        switch (cmd) {
1184        case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
1185        case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
1186        case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
1187        case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
1188        case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
1189        case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
1190        case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
1191        case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
1192        case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
1193        case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
1194        case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
1195        case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
1196        case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
1197        case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
1198        case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
1199        case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
1200        case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
1201        case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
1202        case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
1203        case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
1204        case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
1205        case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
1206        case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
1207        case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
1208        case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
1209        }
1210
1211        /*
1212         * 2. Allocates a 64-bits userspace pointer to store the
1213         * values of the ioctl and copy data from the 32-bits __user
1214         * argument into it.
1215         */
1216        switch (cmd) {
1217        case VIDIOC_OVERLAY:
1218        case VIDIOC_STREAMON:
1219        case VIDIOC_STREAMOFF:
1220        case VIDIOC_S_INPUT:
1221        case VIDIOC_S_OUTPUT:
1222                err = alloc_userspace(sizeof(unsigned int), 0, &new_p64);
1223                if (!err && assign_in_user((unsigned int __user *)new_p64,
1224                                           (compat_uint_t __user *)p32))
1225                        err = -EFAULT;
1226                compatible_arg = 0;
1227                break;
1228
1229        case VIDIOC_G_INPUT:
1230        case VIDIOC_G_OUTPUT:
1231                err = alloc_userspace(sizeof(unsigned int), 0, &new_p64);
1232                compatible_arg = 0;
1233                break;
1234
1235        case VIDIOC_G_EDID:
1236        case VIDIOC_S_EDID:
1237                err = alloc_userspace(sizeof(struct v4l2_edid), 0, &new_p64);
1238                if (!err)
1239                        err = get_v4l2_edid32(new_p64, p32);
1240                compatible_arg = 0;
1241                break;
1242
1243        case VIDIOC_G_FMT:
1244        case VIDIOC_S_FMT:
1245        case VIDIOC_TRY_FMT:
1246                err = bufsize_v4l2_format(p32, &aux_space);
1247                if (!err)
1248                        err = alloc_userspace(sizeof(struct v4l2_format),
1249                                              aux_space, &new_p64);
1250                if (!err) {
1251                        aux_buf = new_p64 + sizeof(struct v4l2_format);
1252                        err = get_v4l2_format32(new_p64, p32,
1253                                                aux_buf, aux_space);
1254                }
1255                compatible_arg = 0;
1256                break;
1257
1258        case VIDIOC_CREATE_BUFS:
1259                err = bufsize_v4l2_create(p32, &aux_space);
1260                if (!err)
1261                        err = alloc_userspace(sizeof(struct v4l2_create_buffers),
1262                                              aux_space, &new_p64);
1263                if (!err) {
1264                        aux_buf = new_p64 + sizeof(struct v4l2_create_buffers);
1265                        err = get_v4l2_create32(new_p64, p32,
1266                                                aux_buf, aux_space);
1267                }
1268                compatible_arg = 0;
1269                break;
1270
1271        case VIDIOC_PREPARE_BUF:
1272        case VIDIOC_QUERYBUF:
1273        case VIDIOC_QBUF:
1274        case VIDIOC_DQBUF:
1275                err = bufsize_v4l2_buffer(p32, &aux_space);
1276                if (!err)
1277                        err = alloc_userspace(sizeof(struct v4l2_buffer),
1278                                              aux_space, &new_p64);
1279                if (!err) {
1280                        aux_buf = new_p64 + sizeof(struct v4l2_buffer);
1281                        err = get_v4l2_buffer32(new_p64, p32,
1282                                                aux_buf, aux_space);
1283                }
1284                compatible_arg = 0;
1285                break;
1286
1287        case VIDIOC_S_FBUF:
1288                err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1289                                      &new_p64);
1290                if (!err)
1291                        err = get_v4l2_framebuffer32(new_p64, p32);
1292                compatible_arg = 0;
1293                break;
1294
1295        case VIDIOC_G_FBUF:
1296                err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1297                                      &new_p64);
1298                compatible_arg = 0;
1299                break;
1300
1301        case VIDIOC_ENUMSTD:
1302                err = alloc_userspace(sizeof(struct v4l2_standard), 0,
1303                                      &new_p64);
1304                if (!err)
1305                        err = get_v4l2_standard32(new_p64, p32);
1306                compatible_arg = 0;
1307                break;
1308
1309        case VIDIOC_ENUMINPUT:
1310                err = alloc_userspace(sizeof(struct v4l2_input), 0, &new_p64);
1311                if (!err)
1312                        err = get_v4l2_input32(new_p64, p32);
1313                compatible_arg = 0;
1314                break;
1315
1316        case VIDIOC_G_EXT_CTRLS:
1317        case VIDIOC_S_EXT_CTRLS:
1318        case VIDIOC_TRY_EXT_CTRLS:
1319                err = bufsize_v4l2_ext_controls(p32, &aux_space);
1320                if (!err)
1321                        err = alloc_userspace(sizeof(struct v4l2_ext_controls),
1322                                              aux_space, &new_p64);
1323                if (!err) {
1324                        aux_buf = new_p64 + sizeof(struct v4l2_ext_controls);
1325                        err = get_v4l2_ext_controls32(file, new_p64, p32,
1326                                                      aux_buf, aux_space);
1327                }
1328                compatible_arg = 0;
1329                break;
1330        case VIDIOC_DQEVENT:
1331                err = alloc_userspace(sizeof(struct v4l2_event), 0, &new_p64);
1332                compatible_arg = 0;
1333                break;
1334        }
1335        if (err)
1336                return err;
1337
1338        /*
1339         * 3. Calls the native 64-bits ioctl handler.
1340         *
1341         * For the functions where a conversion was not needed,
1342         * compatible_arg is true, and it will call it with the arguments
1343         * provided by userspace and stored at @p32 var.
1344         *
1345         * Otherwise, it will pass the newly allocated @new_p64 argument.
1346         */
1347        if (compatible_arg)
1348                err = native_ioctl(file, cmd, (unsigned long)p32);
1349        else
1350                err = native_ioctl(file, cmd, (unsigned long)new_p64);
1351
1352        if (err == -ENOTTY)
1353                return err;
1354
1355        /*
1356         * 4. Special case: even after an error we need to put the
1357         * results back for some ioctls.
1358         *
1359         * In the case of EXT_CTRLS, the error_idx will contain information
1360         * on which control failed.
1361         *
1362         * In the case of S_EDID, the driver can return E2BIG and set
1363         * the blocks to maximum allowed value.
1364         */
1365        switch (cmd) {
1366        case VIDIOC_G_EXT_CTRLS:
1367        case VIDIOC_S_EXT_CTRLS:
1368        case VIDIOC_TRY_EXT_CTRLS:
1369                if (put_v4l2_ext_controls32(file, new_p64, p32))
1370                        err = -EFAULT;
1371                break;
1372        case VIDIOC_S_EDID:
1373                if (put_v4l2_edid32(new_p64, p32))
1374                        err = -EFAULT;
1375                break;
1376        }
1377        if (err)
1378                return err;
1379
1380        /*
1381         * 5. Copy the data returned at the 64 bits userspace pointer to
1382         * the original 32 bits structure.
1383         */
1384        switch (cmd) {
1385        case VIDIOC_S_INPUT:
1386        case VIDIOC_S_OUTPUT:
1387        case VIDIOC_G_INPUT:
1388        case VIDIOC_G_OUTPUT:
1389                if (assign_in_user((compat_uint_t __user *)p32,
1390                                   ((unsigned int __user *)new_p64)))
1391                        err = -EFAULT;
1392                break;
1393
1394        case VIDIOC_G_FBUF:
1395                err = put_v4l2_framebuffer32(new_p64, p32);
1396                break;
1397
1398        case VIDIOC_DQEVENT:
1399                err = put_v4l2_event32(new_p64, p32);
1400                break;
1401
1402        case VIDIOC_G_EDID:
1403                err = put_v4l2_edid32(new_p64, p32);
1404                break;
1405
1406        case VIDIOC_G_FMT:
1407        case VIDIOC_S_FMT:
1408        case VIDIOC_TRY_FMT:
1409                err = put_v4l2_format32(new_p64, p32);
1410                break;
1411
1412        case VIDIOC_CREATE_BUFS:
1413                err = put_v4l2_create32(new_p64, p32);
1414                break;
1415
1416        case VIDIOC_PREPARE_BUF:
1417        case VIDIOC_QUERYBUF:
1418        case VIDIOC_QBUF:
1419        case VIDIOC_DQBUF:
1420                err = put_v4l2_buffer32(new_p64, p32);
1421                break;
1422
1423        case VIDIOC_ENUMSTD:
1424                err = put_v4l2_standard32(new_p64, p32);
1425                break;
1426
1427        case VIDIOC_ENUMINPUT:
1428                err = put_v4l2_input32(new_p64, p32);
1429                break;
1430        }
1431        return err;
1432}
1433
1434/**
1435 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1436 *
1437 * @file: pointer to &struct file with the file handler
1438 * @cmd: ioctl to be called
1439 * @arg: arguments passed from/to the ioctl handler
1440 *
1441 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1442 * in order to deal with 32-bit calls on a 64-bits Kernel.
1443 *
1444 * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1445 * If the function is a private one it calls vdev->fops->compat_ioctl32
1446 * instead.
1447 */
1448long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1449{
1450        struct video_device *vdev = video_devdata(file);
1451        long ret = -ENOIOCTLCMD;
1452
1453        if (!file->f_op->unlocked_ioctl)
1454                return ret;
1455
1456        if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1457                ret = do_video_ioctl(file, cmd, arg);
1458        else if (vdev->fops->compat_ioctl32)
1459                ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1460
1461        if (ret == -ENOIOCTLCMD)
1462                pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1463                         _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1464        return ret;
1465}
1466EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
1467