blob: d32b1a0431eacb847e570615108f39560fc35be4 [file] [log] [blame]
Sathish Ambley69e1ab02016-10-18 10:28:15 -07001/*
Sathish Ambleya21b5b52017-01-11 16:11:01 -08002 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Sathish Ambley69e1ab02016-10-18 10:28:15 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/compat.h>
16#include <linux/fs.h>
17#include <linux/uaccess.h>
18#include <linux/msm_ion.h>
19
20#include "adsprpc_compat.h"
21#include "adsprpc_shared.h"
22
23#define COMPAT_FASTRPC_IOCTL_INVOKE \
24 _IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
25#define COMPAT_FASTRPC_IOCTL_MMAP \
26 _IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
27#define COMPAT_FASTRPC_IOCTL_MUNMAP \
28 _IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
29#define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
30 _IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
31#define COMPAT_FASTRPC_IOCTL_INIT \
32 _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
33#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
34 _IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
Sathish Ambleya21b5b52017-01-11 16:11:01 -080035#define COMPAT_FASTRPC_IOCTL_GETPERF \
36 _IOWR('R', 9, struct compat_fastrpc_ioctl_perf)
Sathish Ambley69e1ab02016-10-18 10:28:15 -070037
38struct compat_remote_buf {
39 compat_uptr_t pv; /* buffer pointer */
40 compat_ssize_t len; /* length of buffer */
41};
42
43union compat_remote_arg {
44 struct compat_remote_buf buf;
45 compat_uint_t h;
46};
47
48struct compat_fastrpc_ioctl_invoke {
49 compat_uint_t handle; /* remote handle */
50 compat_uint_t sc; /* scalars describing the data */
51 compat_uptr_t pra; /* remote arguments list */
52};
53
54struct compat_fastrpc_ioctl_invoke_fd {
55 struct compat_fastrpc_ioctl_invoke inv;
56 compat_uptr_t fds; /* fd list */
57};
58
59struct compat_fastrpc_ioctl_invoke_attrs {
60 struct compat_fastrpc_ioctl_invoke inv;
61 compat_uptr_t fds; /* fd list */
62 compat_uptr_t attrs; /* attribute list */
63};
64
65struct compat_fastrpc_ioctl_mmap {
66 compat_int_t fd; /* ion fd */
67 compat_uint_t flags; /* flags for dsp to map with */
68 compat_uptr_t vaddrin; /* optional virtual address */
69 compat_ssize_t size; /* size */
70 compat_uptr_t vaddrout; /* dsps virtual address */
71};
72
73struct compat_fastrpc_ioctl_munmap {
74 compat_uptr_t vaddrout; /* address to unmap */
75 compat_ssize_t size; /* size */
76};
77
78struct compat_fastrpc_ioctl_init {
79 compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
80 compat_uptr_t file; /* pointer to elf file */
81 compat_int_t filelen; /* elf file length */
82 compat_int_t filefd; /* ION fd for the file */
83 compat_uptr_t mem; /* mem for the PD */
84 compat_int_t memlen; /* mem length */
85 compat_int_t memfd; /* ION fd for the mem */
86};
87
Sathish Ambleya21b5b52017-01-11 16:11:01 -080088struct compat_fastrpc_ioctl_perf { /* kernel performance data */
89 compat_uptr_t data;
90 compat_int_t numkeys;
91 compat_uptr_t keys;
92};
93
Sathish Ambley69e1ab02016-10-18 10:28:15 -070094static int compat_get_fastrpc_ioctl_invoke(
95 struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
96 struct fastrpc_ioctl_invoke_attrs __user **inva,
97 unsigned int cmd)
98{
99 compat_uint_t u, sc;
100 compat_ssize_t s;
101 compat_uptr_t p;
102 struct fastrpc_ioctl_invoke_attrs *inv;
103 union compat_remote_arg *pra32;
104 union remote_arg *pra;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800105 int err, len, j;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700106
107 err = get_user(sc, &inv32->inv.sc);
108 if (err)
109 return err;
110
111 len = REMOTE_SCALARS_LENGTH(sc);
112 VERIFY(err, NULL != (inv = compat_alloc_user_space(
113 sizeof(*inv) + len * sizeof(*pra))));
114 if (err)
115 return -EFAULT;
116
117 pra = (union remote_arg *)(inv + 1);
118 err = put_user(pra, &inv->inv.pra);
119 err |= put_user(sc, &inv->inv.sc);
120 err |= get_user(u, &inv32->inv.handle);
121 err |= put_user(u, &inv->inv.handle);
122 err |= get_user(p, &inv32->inv.pra);
123 if (err)
124 return err;
125
126 pra32 = compat_ptr(p);
127 pra = (union remote_arg *)(inv + 1);
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800128 for (j = 0; j < len; j++) {
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700129 err |= get_user(p, &pra32[j].buf.pv);
130 err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
131 err |= get_user(s, &pra32[j].buf.len);
132 err |= put_user(s, &pra[j].buf.len);
133 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700134
135 err |= put_user(NULL, &inv->fds);
136 if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
137 err |= get_user(p, &inv32->fds);
138 err |= put_user(p, (compat_uptr_t *)&inv->fds);
139 }
140 err |= put_user(NULL, &inv->attrs);
141 if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) {
142 err |= get_user(p, &inv32->attrs);
143 err |= put_user(p, (compat_uptr_t *)&inv->attrs);
144 }
145
146 *inva = inv;
147 return err;
148}
149
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700150static int compat_get_fastrpc_ioctl_mmap(
151 struct compat_fastrpc_ioctl_mmap __user *map32,
152 struct fastrpc_ioctl_mmap __user *map)
153{
154 compat_uint_t u;
155 compat_int_t i;
156 compat_ssize_t s;
157 compat_uptr_t p;
158 int err;
159
160 err = get_user(i, &map32->fd);
161 err |= put_user(i, &map->fd);
162 err |= get_user(u, &map32->flags);
163 err |= put_user(u, &map->flags);
164 err |= get_user(p, &map32->vaddrin);
165 err |= put_user(p, (uintptr_t *)&map->vaddrin);
166 err |= get_user(s, &map32->size);
167 err |= put_user(s, &map->size);
168
169 return err;
170}
171
172static int compat_put_fastrpc_ioctl_mmap(
173 struct compat_fastrpc_ioctl_mmap __user *map32,
174 struct fastrpc_ioctl_mmap __user *map)
175{
176 compat_uptr_t p;
177 int err;
178
179 err = get_user(p, &map->vaddrout);
180 err |= put_user(p, &map32->vaddrout);
181
182 return err;
183}
184
185static int compat_get_fastrpc_ioctl_munmap(
186 struct compat_fastrpc_ioctl_munmap __user *unmap32,
187 struct fastrpc_ioctl_munmap __user *unmap)
188{
189 compat_uptr_t p;
190 compat_ssize_t s;
191 int err;
192
193 err = get_user(p, &unmap32->vaddrout);
194 err |= put_user(p, &unmap->vaddrout);
195 err |= get_user(s, &unmap32->size);
196 err |= put_user(s, &unmap->size);
197
198 return err;
199}
200
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800201static int compat_get_fastrpc_ioctl_perf(
202 struct compat_fastrpc_ioctl_perf __user *perf32,
203 struct fastrpc_ioctl_perf __user *perf)
204{
205 compat_uptr_t p;
206 int err;
207
208 err = get_user(p, &perf32->data);
209 err |= put_user(p, &perf->data);
210 err |= get_user(p, &perf32->keys);
211 err |= put_user(p, &perf->keys);
212
213 return err;
214}
215
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700216static int compat_get_fastrpc_ioctl_init(
217 struct compat_fastrpc_ioctl_init __user *init32,
218 struct fastrpc_ioctl_init __user *init)
219{
220 compat_uint_t u;
221 compat_uptr_t p;
222 compat_int_t i;
223 int err;
224
225 err = get_user(u, &init32->flags);
226 err |= put_user(u, &init->flags);
227 err |= get_user(p, &init32->file);
228 err |= put_user(p, &init->file);
229 err |= get_user(i, &init32->filelen);
230 err |= put_user(i, &init->filelen);
231 err |= get_user(i, &init32->filefd);
232 err |= put_user(i, &init->filefd);
233 err |= get_user(p, &init32->mem);
234 err |= put_user(p, &init->mem);
235 err |= get_user(i, &init32->memlen);
236 err |= put_user(i, &init->memlen);
237 err |= get_user(i, &init32->memfd);
238 err |= put_user(i, &init->memfd);
239
240 return err;
241}
242
243long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
244 unsigned long arg)
245{
246 int err = 0;
247
248 if (!filp->f_op || !filp->f_op->unlocked_ioctl)
249 return -ENOTTY;
250
251 switch (cmd) {
252 case COMPAT_FASTRPC_IOCTL_INVOKE:
253 case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
254 case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
255 {
256 struct compat_fastrpc_ioctl_invoke_attrs __user *inv32;
257 struct fastrpc_ioctl_invoke_attrs __user *inv;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700258
259 inv32 = compat_ptr(arg);
260 VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
261 &inv, cmd));
262 if (err)
263 return err;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800264 return filp->f_op->unlocked_ioctl(filp,
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700265 FASTRPC_IOCTL_INVOKE_ATTRS, (unsigned long)inv);
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700266 }
267 case COMPAT_FASTRPC_IOCTL_MMAP:
268 {
269 struct compat_fastrpc_ioctl_mmap __user *map32;
270 struct fastrpc_ioctl_mmap __user *map;
271 long ret;
272
273 map32 = compat_ptr(arg);
274 VERIFY(err, NULL != (map = compat_alloc_user_space(
275 sizeof(*map))));
276 if (err)
277 return -EFAULT;
278 VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
279 if (err)
280 return err;
281 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP,
282 (unsigned long)map);
283 if (ret)
284 return ret;
285 VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
286 return err;
287 }
288 case COMPAT_FASTRPC_IOCTL_MUNMAP:
289 {
290 struct compat_fastrpc_ioctl_munmap __user *unmap32;
291 struct fastrpc_ioctl_munmap __user *unmap;
292
293 unmap32 = compat_ptr(arg);
294 VERIFY(err, NULL != (unmap = compat_alloc_user_space(
295 sizeof(*unmap))));
296 if (err)
297 return -EFAULT;
298 VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
299 unmap));
300 if (err)
301 return err;
302 return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP,
303 (unsigned long)unmap);
304 }
305 case COMPAT_FASTRPC_IOCTL_INIT:
306 {
307 struct compat_fastrpc_ioctl_init __user *init32;
308 struct fastrpc_ioctl_init __user *init;
309
310 init32 = compat_ptr(arg);
311 VERIFY(err, NULL != (init = compat_alloc_user_space(
312 sizeof(*init))));
313 if (err)
314 return -EFAULT;
315 VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
316 init));
317 if (err)
318 return err;
319 return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_INIT,
320 (unsigned long)init);
321 }
322 case FASTRPC_IOCTL_GETINFO:
323 {
324 compat_uptr_t __user *info32;
325 uint32_t __user *info;
326 compat_uint_t u;
327 long ret;
328
329 info32 = compat_ptr(arg);
330 VERIFY(err, NULL != (info = compat_alloc_user_space(
331 sizeof(*info))));
332 if (err)
333 return -EFAULT;
334 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO,
335 (unsigned long)info);
336 if (ret)
337 return ret;
338 err = get_user(u, info);
339 err |= put_user(u, info32);
340 return err;
341 }
342 case FASTRPC_IOCTL_SETMODE:
343 return filp->f_op->unlocked_ioctl(filp, cmd,
344 (unsigned long)compat_ptr(arg));
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800345 case COMPAT_FASTRPC_IOCTL_GETPERF:
346 {
347 struct compat_fastrpc_ioctl_perf __user *perf32;
348 struct fastrpc_ioctl_perf *perf;
349 compat_uint_t u;
350 long ret;
351
352 perf32 = compat_ptr(arg);
353 VERIFY(err, NULL != (perf = compat_alloc_user_space(
354 sizeof(*perf))));
355 if (err)
356 return -EFAULT;
357 VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
358 perf));
359 if (err)
360 return err;
361 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
362 (unsigned long)perf);
363 if (ret)
364 return ret;
365 err = get_user(u, &perf->numkeys);
366 err |= put_user(u, &perf32->numkeys);
367 return err;
368 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700369 default:
370 return -ENOIOCTLCMD;
371 }
372}