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