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