1
2
3
4
5
6
7
8
9
10
11
12
13
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
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