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 == NULL) 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 == NULL) 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 == NULL) 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