compat_ion.c revision e1d855b02f5ac4c3a6cbeaa253958b2708826b9f
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 38#define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ 39 struct compat_ion_allocation_data) 40#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) 41#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ 42 struct compat_ion_custom_data) 43 44static int compat_get_ion_allocation_data( 45 struct compat_ion_allocation_data __user *data32, 46 struct ion_allocation_data __user *data) 47{ 48 compat_size_t s; 49 compat_uint_t u; 50 compat_int_t i; 51 int err; 52 53 err = get_user(s, &data32->len); 54 err |= put_user(s, &data->len); 55 err |= get_user(s, &data32->align); 56 err |= put_user(s, &data->align); 57 err |= get_user(u, &data32->heap_id_mask); 58 err |= put_user(u, &data->heap_id_mask); 59 err |= get_user(u, &data32->flags); 60 err |= put_user(u, &data->flags); 61 err |= get_user(i, &data32->handle); 62 err |= put_user(i, &data->handle); 63 64 return err; 65} 66 67static int compat_put_ion_allocation_data( 68 struct compat_ion_allocation_data __user *data32, 69 struct ion_allocation_data __user *data) 70{ 71 compat_size_t s; 72 compat_uint_t u; 73 compat_int_t i; 74 int err; 75 76 err = get_user(s, &data->len); 77 err |= put_user(s, &data32->len); 78 err |= get_user(s, &data->align); 79 err |= put_user(s, &data32->align); 80 err |= get_user(u, &data->heap_id_mask); 81 err |= put_user(u, &data32->heap_id_mask); 82 err |= get_user(u, &data->flags); 83 err |= put_user(u, &data32->flags); 84 err |= get_user(i, &data->handle); 85 err |= put_user(i, &data32->handle); 86 87 return err; 88} 89 90static int compat_get_ion_custom_data( 91 struct compat_ion_custom_data __user *data32, 92 struct ion_custom_data __user *data) 93{ 94 compat_uint_t cmd; 95 compat_ulong_t arg; 96 int err; 97 98 err = get_user(cmd, &data32->cmd); 99 err |= put_user(cmd, &data->cmd); 100 err |= get_user(arg, &data32->arg); 101 err |= put_user(arg, &data->arg); 102 103 return err; 104}; 105 106long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 107{ 108 long ret; 109 110 if (!filp->f_op || !filp->f_op->unlocked_ioctl) 111 return -ENOTTY; 112 113 switch (cmd) { 114 case COMPAT_ION_IOC_ALLOC: 115 { 116 struct compat_ion_allocation_data __user *data32; 117 struct ion_allocation_data __user *data; 118 int err; 119 120 data32 = compat_ptr(arg); 121 data = compat_alloc_user_space(sizeof(*data)); 122 if (data == NULL) 123 return -EFAULT; 124 125 err = compat_get_ion_allocation_data(data32, data); 126 if (err) 127 return err; 128 ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC, 129 (unsigned long)data); 130 err = compat_put_ion_allocation_data(data32, data); 131 return ret ? ret : err; 132 } 133 case COMPAT_ION_IOC_FREE: 134 { 135 struct compat_ion_allocation_data __user *data32; 136 struct ion_allocation_data __user *data; 137 int err; 138 139 data32 = compat_ptr(arg); 140 data = compat_alloc_user_space(sizeof(*data)); 141 if (data == NULL) 142 return -EFAULT; 143 144 err = compat_get_ion_allocation_data(data32, data); 145 if (err) 146 return err; 147 148 return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE, 149 (unsigned long)data); 150 } 151 case COMPAT_ION_IOC_CUSTOM: { 152 struct compat_ion_custom_data __user *data32; 153 struct ion_custom_data __user *data; 154 int err; 155 156 data32 = compat_ptr(arg); 157 data = compat_alloc_user_space(sizeof(*data)); 158 if (data == NULL) 159 return -EFAULT; 160 161 err = compat_get_ion_custom_data(data32, data); 162 if (err) 163 return err; 164 165 return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM, 166 (unsigned long)data); 167 } 168 case ION_IOC_SHARE: 169 case ION_IOC_MAP: 170 case ION_IOC_IMPORT: 171 case ION_IOC_SYNC: 172 return filp->f_op->unlocked_ioctl(filp, cmd, 173 (unsigned long)compat_ptr(arg)); 174 default: 175 return -ENOIOCTLCMD; 176 } 177} 178