linux/drivers/staging/android/ion/compat_ion.c
<<
>>
Prefs
   1/*
   2 * drivers/staging/android/ion/compat_ion.c
   3 *
   4 * Copyright (C) 2013 Google, Inc.
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 */
  16
  17#include <linux/compat.h>
  18#include <linux/fs.h>
  19#include <linux/uaccess.h>
  20
  21#include "ion.h"
  22#include "compat_ion.h"
  23
  24/* See drivers/staging/android/uapi/ion.h for the definition of these structs */
  25struct compat_ion_allocation_data {
  26        compat_size_t len;
  27        compat_size_t align;
  28        compat_uint_t heap_id_mask;
  29        compat_uint_t flags;
  30        compat_int_t handle;
  31};
  32
  33struct compat_ion_custom_data {
  34        compat_uint_t cmd;
  35        compat_ulong_t arg;
  36};
  37
  38struct compat_ion_handle_data {
  39        compat_int_t handle;
  40};
  41
  42#define COMPAT_ION_IOC_ALLOC    _IOWR(ION_IOC_MAGIC, 0, \
  43                                      struct compat_ion_allocation_data)
  44#define COMPAT_ION_IOC_FREE     _IOWR(ION_IOC_MAGIC, 1, \
  45                                      struct compat_ion_handle_data)
  46#define COMPAT_ION_IOC_CUSTOM   _IOWR(ION_IOC_MAGIC, 6, \
  47                                      struct compat_ion_custom_data)
  48
  49static int compat_get_ion_allocation_data(
  50                        struct compat_ion_allocation_data __user *data32,
  51                        struct ion_allocation_data __user *data)
  52{
  53        compat_size_t s;
  54        compat_uint_t u;
  55        compat_int_t i;
  56        int err;
  57
  58        err = get_user(s, &data32->len);
  59        err |= put_user(s, &data->len);
  60        err |= get_user(s, &data32->align);
  61        err |= put_user(s, &data->align);
  62        err |= get_user(u, &data32->heap_id_mask);
  63        err |= put_user(u, &data->heap_id_mask);
  64        err |= get_user(u, &data32->flags);
  65        err |= put_user(u, &data->flags);
  66        err |= get_user(i, &data32->handle);
  67        err |= put_user(i, &data->handle);
  68
  69        return err;
  70}
  71
  72static int compat_get_ion_handle_data(
  73                        struct compat_ion_handle_data __user *data32,
  74                        struct ion_handle_data __user *data)
  75{
  76        compat_int_t i;
  77        int err;
  78
  79        err = get_user(i, &data32->handle);
  80        err |= put_user(i, &data->handle);
  81
  82        return err;
  83}
  84
  85static int compat_put_ion_allocation_data(
  86                        struct compat_ion_allocation_data __user *data32,
  87                        struct ion_allocation_data __user *data)
  88{
  89        compat_size_t s;
  90        compat_uint_t u;
  91        compat_int_t i;
  92        int err;
  93
  94        err = get_user(s, &data->len);
  95        err |= put_user(s, &data32->len);
  96        err |= get_user(s, &data->align);
  97        err |= put_user(s, &data32->align);
  98        err |= get_user(u, &data->heap_id_mask);
  99        err |= put_user(u, &data32->heap_id_mask);
 100        err |= get_user(u, &data->flags);
 101        err |= put_user(u, &data32->flags);
 102        err |= get_user(i, &data->handle);
 103        err |= put_user(i, &data32->handle);
 104
 105        return err;
 106}
 107
 108static int compat_get_ion_custom_data(
 109                        struct compat_ion_custom_data __user *data32,
 110                        struct ion_custom_data __user *data)
 111{
 112        compat_uint_t cmd;
 113        compat_ulong_t arg;
 114        int err;
 115
 116        err = get_user(cmd, &data32->cmd);
 117        err |= put_user(cmd, &data->cmd);
 118        err |= get_user(arg, &data32->arg);
 119        err |= put_user(arg, &data->arg);
 120
 121        return err;
 122};
 123
 124long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 125{
 126        long ret;
 127
 128        if (!filp->f_op->unlocked_ioctl)
 129                return -ENOTTY;
 130
 131        switch (cmd) {
 132        case COMPAT_ION_IOC_ALLOC:
 133        {
 134                struct compat_ion_allocation_data __user *data32;
 135                struct ion_allocation_data __user *data;
 136                int err;
 137
 138                data32 = compat_ptr(arg);
 139                data = compat_alloc_user_space(sizeof(*data));
 140                if (!data)
 141                        return -EFAULT;
 142
 143                err = compat_get_ion_allocation_data(data32, data);
 144                if (err)
 145                        return err;
 146                ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
 147                                                        (unsigned long)data);
 148                err = compat_put_ion_allocation_data(data32, data);
 149                return ret ? ret : err;
 150        }
 151        case COMPAT_ION_IOC_FREE:
 152        {
 153                struct compat_ion_handle_data __user *data32;
 154                struct ion_handle_data __user *data;
 155                int err;
 156
 157                data32 = compat_ptr(arg);
 158                data = compat_alloc_user_space(sizeof(*data));
 159                if (!data)
 160                        return -EFAULT;
 161
 162                err = compat_get_ion_handle_data(data32, data);
 163                if (err)
 164                        return err;
 165
 166                return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
 167                                                        (unsigned long)data);
 168        }
 169        case COMPAT_ION_IOC_CUSTOM: {
 170                struct compat_ion_custom_data __user *data32;
 171                struct ion_custom_data __user *data;
 172                int err;
 173
 174                data32 = compat_ptr(arg);
 175                data = compat_alloc_user_space(sizeof(*data));
 176                if (!data)
 177                        return -EFAULT;
 178
 179                err = compat_get_ion_custom_data(data32, data);
 180                if (err)
 181                        return err;
 182
 183                return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM,
 184                                                        (unsigned long)data);
 185        }
 186        case ION_IOC_SHARE:
 187        case ION_IOC_MAP:
 188        case ION_IOC_IMPORT:
 189        case ION_IOC_SYNC:
 190                return filp->f_op->unlocked_ioctl(filp, cmd,
 191                                                (unsigned long)compat_ptr(arg));
 192        default:
 193                return -ENOIOCTLCMD;
 194        }
 195}
 196