blob: 8e72b4ddfd931929974010dc7c0ed4209164a0c9 [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 Ambleyd6300c32017-01-18 09:50:43 -080037#define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
38 _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
Sathish Ambley69e1ab02016-10-18 10:28:15 -070039
40struct compat_remote_buf {
41 compat_uptr_t pv; /* buffer pointer */
42 compat_ssize_t len; /* length of buffer */
43};
44
45union compat_remote_arg {
46 struct compat_remote_buf buf;
47 compat_uint_t h;
48};
49
50struct compat_fastrpc_ioctl_invoke {
51 compat_uint_t handle; /* remote handle */
52 compat_uint_t sc; /* scalars describing the data */
53 compat_uptr_t pra; /* remote arguments list */
54};
55
56struct compat_fastrpc_ioctl_invoke_fd {
57 struct compat_fastrpc_ioctl_invoke inv;
58 compat_uptr_t fds; /* fd list */
59};
60
61struct compat_fastrpc_ioctl_invoke_attrs {
62 struct compat_fastrpc_ioctl_invoke inv;
63 compat_uptr_t fds; /* fd list */
64 compat_uptr_t attrs; /* attribute list */
65};
66
67struct compat_fastrpc_ioctl_mmap {
68 compat_int_t fd; /* ion fd */
69 compat_uint_t flags; /* flags for dsp to map with */
70 compat_uptr_t vaddrin; /* optional virtual address */
71 compat_ssize_t size; /* size */
72 compat_uptr_t vaddrout; /* dsps virtual address */
73};
74
75struct compat_fastrpc_ioctl_munmap {
76 compat_uptr_t vaddrout; /* address to unmap */
77 compat_ssize_t size; /* size */
78};
79
80struct compat_fastrpc_ioctl_init {
81 compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
82 compat_uptr_t file; /* pointer to elf file */
83 compat_int_t filelen; /* elf file length */
84 compat_int_t filefd; /* ION fd for the file */
85 compat_uptr_t mem; /* mem for the PD */
86 compat_int_t memlen; /* mem length */
87 compat_int_t memfd; /* ION fd for the mem */
88};
89
Sathish Ambleyd6300c32017-01-18 09:50:43 -080090struct compat_fastrpc_ioctl_init_attrs {
91 struct compat_fastrpc_ioctl_init init;
92 compat_int_t attrs; /* attributes to init process */
93 compat_int_t siglen; /* test signature file length */
94};
95
Sathish Ambleya21b5b52017-01-11 16:11:01 -080096struct compat_fastrpc_ioctl_perf { /* kernel performance data */
97 compat_uptr_t data;
98 compat_int_t numkeys;
99 compat_uptr_t keys;
100};
101
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700102static int compat_get_fastrpc_ioctl_invoke(
103 struct compat_fastrpc_ioctl_invoke_attrs __user *inv32,
104 struct fastrpc_ioctl_invoke_attrs __user **inva,
105 unsigned int cmd)
106{
107 compat_uint_t u, sc;
108 compat_ssize_t s;
109 compat_uptr_t p;
110 struct fastrpc_ioctl_invoke_attrs *inv;
111 union compat_remote_arg *pra32;
112 union remote_arg *pra;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800113 int err, len, j;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700114
115 err = get_user(sc, &inv32->inv.sc);
116 if (err)
117 return err;
118
119 len = REMOTE_SCALARS_LENGTH(sc);
120 VERIFY(err, NULL != (inv = compat_alloc_user_space(
121 sizeof(*inv) + len * sizeof(*pra))));
122 if (err)
123 return -EFAULT;
124
125 pra = (union remote_arg *)(inv + 1);
126 err = put_user(pra, &inv->inv.pra);
127 err |= put_user(sc, &inv->inv.sc);
128 err |= get_user(u, &inv32->inv.handle);
129 err |= put_user(u, &inv->inv.handle);
130 err |= get_user(p, &inv32->inv.pra);
131 if (err)
132 return err;
133
134 pra32 = compat_ptr(p);
135 pra = (union remote_arg *)(inv + 1);
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800136 for (j = 0; j < len; j++) {
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700137 err |= get_user(p, &pra32[j].buf.pv);
138 err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
139 err |= get_user(s, &pra32[j].buf.len);
140 err |= put_user(s, &pra[j].buf.len);
141 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700142
143 err |= put_user(NULL, &inv->fds);
144 if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
145 err |= get_user(p, &inv32->fds);
146 err |= put_user(p, (compat_uptr_t *)&inv->fds);
147 }
148 err |= put_user(NULL, &inv->attrs);
149 if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) {
150 err |= get_user(p, &inv32->attrs);
151 err |= put_user(p, (compat_uptr_t *)&inv->attrs);
152 }
153
154 *inva = inv;
155 return err;
156}
157
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700158static int compat_get_fastrpc_ioctl_mmap(
159 struct compat_fastrpc_ioctl_mmap __user *map32,
160 struct fastrpc_ioctl_mmap __user *map)
161{
162 compat_uint_t u;
163 compat_int_t i;
164 compat_ssize_t s;
165 compat_uptr_t p;
166 int err;
167
168 err = get_user(i, &map32->fd);
169 err |= put_user(i, &map->fd);
170 err |= get_user(u, &map32->flags);
171 err |= put_user(u, &map->flags);
172 err |= get_user(p, &map32->vaddrin);
173 err |= put_user(p, (uintptr_t *)&map->vaddrin);
174 err |= get_user(s, &map32->size);
175 err |= put_user(s, &map->size);
176
177 return err;
178}
179
180static int compat_put_fastrpc_ioctl_mmap(
181 struct compat_fastrpc_ioctl_mmap __user *map32,
182 struct fastrpc_ioctl_mmap __user *map)
183{
184 compat_uptr_t p;
185 int err;
186
187 err = get_user(p, &map->vaddrout);
188 err |= put_user(p, &map32->vaddrout);
189
190 return err;
191}
192
193static int compat_get_fastrpc_ioctl_munmap(
194 struct compat_fastrpc_ioctl_munmap __user *unmap32,
195 struct fastrpc_ioctl_munmap __user *unmap)
196{
197 compat_uptr_t p;
198 compat_ssize_t s;
199 int err;
200
201 err = get_user(p, &unmap32->vaddrout);
202 err |= put_user(p, &unmap->vaddrout);
203 err |= get_user(s, &unmap32->size);
204 err |= put_user(s, &unmap->size);
205
206 return err;
207}
208
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800209static int compat_get_fastrpc_ioctl_perf(
210 struct compat_fastrpc_ioctl_perf __user *perf32,
211 struct fastrpc_ioctl_perf __user *perf)
212{
213 compat_uptr_t p;
214 int err;
215
216 err = get_user(p, &perf32->data);
217 err |= put_user(p, &perf->data);
218 err |= get_user(p, &perf32->keys);
219 err |= put_user(p, &perf->keys);
220
221 return err;
222}
223
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700224static int compat_get_fastrpc_ioctl_init(
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800225 struct compat_fastrpc_ioctl_init_attrs __user *init32,
226 struct fastrpc_ioctl_init_attrs __user *init,
227 unsigned int cmd)
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700228{
229 compat_uint_t u;
230 compat_uptr_t p;
231 compat_int_t i;
232 int err;
233
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800234 err = get_user(u, &init32->init.flags);
235 err |= put_user(u, &init->init.flags);
236 err |= get_user(p, &init32->init.file);
237 err |= put_user(p, &init->init.file);
238 err |= get_user(i, &init32->init.filelen);
239 err |= put_user(i, &init->init.filelen);
240 err |= get_user(i, &init32->init.filefd);
241 err |= put_user(i, &init->init.filefd);
242 err |= get_user(p, &init32->init.mem);
243 err |= put_user(p, &init->init.mem);
244 err |= get_user(i, &init32->init.memlen);
245 err |= put_user(i, &init->init.memlen);
246 err |= get_user(i, &init32->init.memfd);
247 err |= put_user(i, &init->init.memfd);
248
249 err |= put_user(0, &init->attrs);
250 if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
251 err |= get_user(i, &init32->attrs);
252 err |= put_user(i, (compat_uptr_t *)&init->attrs);
253 }
254
255 err |= put_user(0, &init->siglen);
256 if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
257 err |= get_user(i, &init32->siglen);
258 err |= put_user(i, (compat_uptr_t *)&init->siglen);
259 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700260
261 return err;
262}
263
264long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
265 unsigned long arg)
266{
267 int err = 0;
268
269 if (!filp->f_op || !filp->f_op->unlocked_ioctl)
270 return -ENOTTY;
271
272 switch (cmd) {
273 case COMPAT_FASTRPC_IOCTL_INVOKE:
274 case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
275 case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
276 {
277 struct compat_fastrpc_ioctl_invoke_attrs __user *inv32;
278 struct fastrpc_ioctl_invoke_attrs __user *inv;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700279
280 inv32 = compat_ptr(arg);
281 VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
282 &inv, cmd));
283 if (err)
284 return err;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800285 return filp->f_op->unlocked_ioctl(filp,
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700286 FASTRPC_IOCTL_INVOKE_ATTRS, (unsigned long)inv);
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700287 }
288 case COMPAT_FASTRPC_IOCTL_MMAP:
289 {
290 struct compat_fastrpc_ioctl_mmap __user *map32;
291 struct fastrpc_ioctl_mmap __user *map;
292 long ret;
293
294 map32 = compat_ptr(arg);
295 VERIFY(err, NULL != (map = compat_alloc_user_space(
296 sizeof(*map))));
297 if (err)
298 return -EFAULT;
299 VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
300 if (err)
301 return err;
302 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP,
303 (unsigned long)map);
304 if (ret)
305 return ret;
306 VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
307 return err;
308 }
309 case COMPAT_FASTRPC_IOCTL_MUNMAP:
310 {
311 struct compat_fastrpc_ioctl_munmap __user *unmap32;
312 struct fastrpc_ioctl_munmap __user *unmap;
313
314 unmap32 = compat_ptr(arg);
315 VERIFY(err, NULL != (unmap = compat_alloc_user_space(
316 sizeof(*unmap))));
317 if (err)
318 return -EFAULT;
319 VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
320 unmap));
321 if (err)
322 return err;
323 return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP,
324 (unsigned long)unmap);
325 }
326 case COMPAT_FASTRPC_IOCTL_INIT:
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800327 /* fall through */
328 case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700329 {
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800330 struct compat_fastrpc_ioctl_init_attrs __user *init32;
331 struct fastrpc_ioctl_init_attrs __user *init;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700332
333 init32 = compat_ptr(arg);
334 VERIFY(err, NULL != (init = compat_alloc_user_space(
335 sizeof(*init))));
336 if (err)
337 return -EFAULT;
338 VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800339 init, cmd));
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700340 if (err)
341 return err;
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800342 return filp->f_op->unlocked_ioctl(filp,
343 FASTRPC_IOCTL_INIT_ATTRS, (unsigned long)init);
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700344 }
345 case FASTRPC_IOCTL_GETINFO:
346 {
347 compat_uptr_t __user *info32;
348 uint32_t __user *info;
349 compat_uint_t u;
350 long ret;
351
352 info32 = compat_ptr(arg);
353 VERIFY(err, NULL != (info = compat_alloc_user_space(
354 sizeof(*info))));
355 if (err)
356 return -EFAULT;
Sathish Ambley36849af2017-02-02 09:35:55 -0800357 err = get_user(u, info32);
358 err |= put_user(u, info);
359 if (err)
360 return err;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700361 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO,
362 (unsigned long)info);
363 if (ret)
364 return ret;
365 err = get_user(u, info);
366 err |= put_user(u, info32);
367 return err;
368 }
369 case FASTRPC_IOCTL_SETMODE:
370 return filp->f_op->unlocked_ioctl(filp, cmd,
371 (unsigned long)compat_ptr(arg));
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800372 case COMPAT_FASTRPC_IOCTL_GETPERF:
373 {
374 struct compat_fastrpc_ioctl_perf __user *perf32;
375 struct fastrpc_ioctl_perf *perf;
376 compat_uint_t u;
377 long ret;
378
379 perf32 = compat_ptr(arg);
380 VERIFY(err, NULL != (perf = compat_alloc_user_space(
381 sizeof(*perf))));
382 if (err)
383 return -EFAULT;
384 VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
385 perf));
386 if (err)
387 return err;
388 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
389 (unsigned long)perf);
390 if (ret)
391 return ret;
392 err = get_user(u, &perf->numkeys);
393 err |= put_user(u, &perf32->numkeys);
394 return err;
395 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700396 default:
397 return -ENOIOCTLCMD;
398 }
399}