adsprpc_compat.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/compat.h>
  6. #include <linux/fs.h>
  7. #include <linux/uaccess.h>
  8. #include <linux/msm_ion.h>
  9. #include <linux/slab.h>
  10. #include "adsprpc_compat.h"
  11. #include "adsprpc_shared.h"
  12. #define COMPAT_FASTRPC_IOCTL_INVOKE \
  13. _IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
  14. #define COMPAT_FASTRPC_IOCTL_MMAP \
  15. _IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
  16. #define COMPAT_FASTRPC_IOCTL_MUNMAP \
  17. _IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
  18. #define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
  19. _IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
  20. #define COMPAT_FASTRPC_IOCTL_INIT \
  21. _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
  22. #define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
  23. _IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
  24. #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
  25. _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
  26. #define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
  27. _IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
  28. #define COMPAT_FASTRPC_IOCTL_CONTROL \
  29. _IOWR('R', 12, struct compat_fastrpc_ioctl_control)
  30. #define COMPAT_FASTRPC_IOCTL_MMAP_64 \
  31. _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
  32. #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
  33. _IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
  34. #define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
  35. _IOWR('R', 17, \
  36. struct compat_fastrpc_ioctl_capability)
  37. #define COMPAT_FASTRPC_IOCTL_INVOKE2 \
  38. _IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2)
  39. #define COMPAT_FASTRPC_IOCTL_MEM_MAP \
  40. _IOWR('R', 19, struct compat_fastrpc_ioctl_mem_map)
  41. #define COMPAT_FASTRPC_IOCTL_MEM_UNMAP \
  42. _IOWR('R', 20, struct compat_fastrpc_ioctl_mem_unmap)
  43. #define COMPAT_FASTRPC_IOCTL_INVOKE_PERF \
  44. _IOWR('R', 21, struct compat_fastrpc_ioctl_invoke_perf)
  45. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE \
  46. _IOWR('R', 23, struct fastrpc_ioctl_dspsignal_create)
  47. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY \
  48. _IOWR('R', 24, struct fastrpc_ioctl_dspsignal_destroy)
  49. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL \
  50. _IOWR('R', 25, struct fastrpc_ioctl_dspsignal_signal)
  51. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT \
  52. _IOWR('R', 26, struct fastrpc_ioctl_dspsignal_wait)
  53. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT \
  54. _IOWR('R', 27, struct fastrpc_ioctl_dspsignal_cancel_wait)
  55. struct compat_remote_buf {
  56. compat_uptr_t pv; /* buffer pointer */
  57. compat_size_t len; /* length of buffer */
  58. };
  59. union compat_remote_arg {
  60. struct compat_remote_buf buf;
  61. compat_uint_t h;
  62. };
  63. struct compat_fastrpc_ioctl_invoke {
  64. compat_uint_t handle; /* remote handle */
  65. compat_uint_t sc; /* scalars describing the data */
  66. compat_uptr_t pra; /* remote arguments list */
  67. };
  68. struct compat_fastrpc_ioctl_invoke_fd {
  69. struct compat_fastrpc_ioctl_invoke inv;
  70. compat_uptr_t fds; /* fd list */
  71. };
  72. struct compat_fastrpc_ioctl_invoke_attrs {
  73. struct compat_fastrpc_ioctl_invoke inv;
  74. compat_uptr_t fds; /* fd list */
  75. compat_uptr_t attrs; /* attribute list */
  76. };
  77. struct compat_fastrpc_ioctl_invoke_crc {
  78. struct compat_fastrpc_ioctl_invoke inv;
  79. compat_uptr_t fds; /* fd list */
  80. compat_uptr_t attrs; /* attribute list */
  81. compat_uptr_t crc; /* crc list */
  82. };
  83. struct compat_fastrpc_ioctl_invoke_perf {
  84. struct compat_fastrpc_ioctl_invoke inv;
  85. compat_uptr_t fds;
  86. compat_uptr_t attrs;
  87. compat_uptr_t crc;
  88. compat_uptr_t perf_kernel;
  89. compat_uptr_t perf_dsp;
  90. };
  91. struct compat_fastrpc_ioctl_invoke_async {
  92. struct compat_fastrpc_ioctl_invoke inv;
  93. compat_uptr_t fds; /* fd list */
  94. compat_uptr_t attrs; /* attribute list */
  95. compat_uptr_t crc; /* crc list */
  96. compat_uptr_t perf_kernel; /* Kernel perf data pointer */
  97. compat_uptr_t perf_dsp; /* DSP perf data pointer */
  98. compat_uptr_t job; /* Async job */
  99. };
  100. struct compat_fastrpc_ioctl_invoke_async_no_perf {
  101. struct compat_fastrpc_ioctl_invoke inv;
  102. compat_uptr_t fds; /* fd list */
  103. compat_uptr_t attrs; /* attribute list */
  104. compat_uptr_t crc; /* crc list */
  105. compat_uptr_t job; /* Async job */
  106. };
  107. struct compat_fastrpc_ioctl_invoke2 {
  108. compat_uint_t req; /* type of invocation request */
  109. compat_uptr_t invparam; /* invocation request param */
  110. compat_uint_t size; /* size of invocation param */
  111. compat_int_t err; /* reserved */
  112. };
  113. struct compat_fastrpc_ioctl_async_response {
  114. compat_u64 jobid; /* job id generated by user */
  115. compat_int_t result; /* result from DSP */
  116. compat_uptr_t perf_kernel; /* Kernel perf data pointer */
  117. compat_uptr_t perf_dsp; /* DSP perf data pointer */
  118. compat_uint_t handle;
  119. compat_uint_t sc;
  120. };
  121. struct compat_fastrpc_ioctl_notif_rsp {
  122. compat_int_t domain; /* Domain of User PD */
  123. compat_int_t session; /* Session ID of User PD */
  124. compat_uint_t status; /* Status of the process */
  125. };
  126. struct compat_fastrpc_mem_map {
  127. compat_int_t fd; /* ion fd */
  128. compat_int_t offset; /* buffer offset */
  129. compat_uint_t flags; /* flags to control memory map */
  130. compat_uint_t attrs; /* buffer attributes used for SMMU mapping */
  131. compat_uptr_t vaddrin; /* virtual address */
  132. compat_size_t length; /* buffer length */
  133. compat_u64 vaddrout; /* dsp virtual address */
  134. };
  135. struct compat_fastrpc_ioctl_mem_map {
  136. compat_int_t version;
  137. union {
  138. struct compat_fastrpc_mem_map m;
  139. compat_int_t reserved[MAP_RESERVED_NUM];
  140. };
  141. };
  142. struct compat_fastrpc_mem_unmap {
  143. compat_int_t fd; /* ion fd */
  144. compat_u64 vaddr; /* dsp virtual address */
  145. compat_size_t length; /* buffer length */
  146. };
  147. struct compat_fastrpc_ioctl_mem_unmap {
  148. compat_int_t version;
  149. union {
  150. struct compat_fastrpc_mem_unmap um;
  151. compat_int_t reserved[UNMAP_RESERVED_NUM];
  152. };
  153. };
  154. struct compat_fastrpc_ioctl_mmap {
  155. compat_int_t fd; /* ion fd */
  156. compat_uint_t flags; /* flags for dsp to map with */
  157. compat_uptr_t vaddrin; /* optional virtual address */
  158. compat_size_t size; /* size */
  159. compat_uptr_t vaddrout; /* dsps virtual address */
  160. };
  161. struct compat_fastrpc_ioctl_mmap_64 {
  162. compat_int_t fd; /* ion fd */
  163. compat_uint_t flags; /* flags for dsp to map with */
  164. compat_u64 vaddrin; /* optional virtual address */
  165. compat_size_t size; /* size */
  166. compat_u64 vaddrout; /* dsps virtual address */
  167. };
  168. struct compat_fastrpc_ioctl_munmap {
  169. compat_uptr_t vaddrout; /* address to unmap */
  170. compat_size_t size; /* size */
  171. };
  172. struct compat_fastrpc_ioctl_munmap_64 {
  173. compat_u64 vaddrout; /* address to unmap */
  174. compat_size_t size; /* size */
  175. };
  176. struct compat_fastrpc_ioctl_init {
  177. compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
  178. compat_uptr_t file; /* pointer to elf file */
  179. compat_int_t filelen; /* elf file length */
  180. compat_int_t filefd; /* ION fd for the file */
  181. compat_uptr_t mem; /* mem for the PD */
  182. compat_int_t memlen; /* mem length */
  183. compat_int_t memfd; /* ION fd for the mem */
  184. };
  185. struct compat_fastrpc_ioctl_init_attrs {
  186. struct compat_fastrpc_ioctl_init init;
  187. compat_int_t attrs; /* attributes to init process */
  188. compat_int_t siglen; /* test signature file length */
  189. };
  190. #define FASTRPC_CONTROL_LATENCY (1)
  191. struct compat_fastrpc_ctrl_latency {
  192. compat_uint_t enable; /* latency control enable */
  193. compat_uint_t latency; /* target latency in us */
  194. };
  195. #define FASTRPC_CONTROL_KALLOC (3)
  196. struct compat_fastrpc_ctrl_kalloc {
  197. compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
  198. };
  199. struct compat_fastrpc_ctrl_wakelock {
  200. compat_uint_t enable; /* wakelock control enable */
  201. };
  202. struct compat_fastrpc_ctrl_pm {
  203. compat_uint_t timeout; /* timeout(in ms) for PM to keep system awake */
  204. };
  205. struct compat_fastrpc_ioctl_control {
  206. compat_uint_t req;
  207. union {
  208. struct compat_fastrpc_ctrl_latency lp;
  209. struct compat_fastrpc_ctrl_kalloc kalloc;
  210. struct compat_fastrpc_ctrl_wakelock wp;
  211. struct compat_fastrpc_ctrl_pm pm;
  212. };
  213. };
  214. struct compat_fastrpc_ioctl_capability {
  215. /*
  216. * @param[in]: DSP domain ADSP_DOMAIN_ID,
  217. * SDSP_DOMAIN_ID, or CDSP_DOMAIN_ID
  218. */
  219. compat_uint_t domain;
  220. /*
  221. * @param[in]: One of the DSP attributes
  222. * from enum remote_dsp_attributes
  223. */
  224. compat_uint_t attribute_ID;
  225. /*
  226. * @param[out]: Result of the DSP
  227. * capability query based on attribute_ID
  228. */
  229. compat_uint_t capability;
  230. };
  231. static int compat_get_fastrpc_ioctl_invoke(
  232. struct compat_fastrpc_ioctl_invoke_async __user *inv32,
  233. struct fastrpc_ioctl_invoke_async *inv,
  234. unsigned int cmd, unsigned int sc)
  235. {
  236. compat_uint_t u = 0;
  237. compat_size_t s;
  238. compat_uptr_t p, k;
  239. union compat_remote_arg *pra32;
  240. union remote_arg *pra;
  241. int err = 0, len = 0, j = 0;
  242. len = REMOTE_SCALARS_LENGTH(sc);
  243. pra = (union remote_arg *)(inv + 1);
  244. memcpy(&inv->inv.pra, &pra, sizeof(pra));
  245. memcpy(&inv->inv.sc, &sc, sizeof(sc));
  246. err |= get_user(u, &inv32->inv.handle);
  247. memcpy(&inv->inv.handle, &u, sizeof(u));
  248. err |= get_user(p, &inv32->inv.pra);
  249. if (err)
  250. return err;
  251. pra32 = compat_ptr(p);
  252. for (j = 0; j < len; j++) {
  253. err |= get_user(p, &pra32[j].buf.pv);
  254. memcpy((uintptr_t *)&pra[j].buf.pv, &p, sizeof(p));
  255. err |= get_user(s, &pra32[j].buf.len);
  256. memcpy(&pra[j].buf.len, &s, sizeof(s));
  257. }
  258. if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
  259. err |= get_user(p, &inv32->fds);
  260. memcpy(&inv->fds, &p, sizeof(p));
  261. }
  262. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
  263. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
  264. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) ||
  265. (cmd == FASTRPC_INVOKE2_ASYNC)) {
  266. err |= get_user(p, &inv32->attrs);
  267. memcpy(&inv->attrs, &p, sizeof(p));
  268. }
  269. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
  270. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF)) {
  271. err |= get_user(p, &inv32->crc);
  272. memcpy(&inv->crc, &p, sizeof(p));
  273. }
  274. if (cmd == FASTRPC_INVOKE2_ASYNC) {
  275. err |= get_user(p, &inv32->job);
  276. memcpy(&inv->job, &p, sizeof(p));
  277. }
  278. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) || (cmd == FASTRPC_INVOKE2_ASYNC)) {
  279. err |= get_user(k, &inv32->perf_kernel);
  280. err |= get_user(p, &inv32->perf_dsp);
  281. memcpy(&inv->perf_kernel, &k, sizeof(k));
  282. memcpy(&inv->perf_dsp, &p, sizeof(p));
  283. }
  284. return err;
  285. }
  286. static int compat_fastrpc_ioctl_invoke(struct file *filp,
  287. unsigned int cmd, unsigned long arg)
  288. {
  289. struct compat_fastrpc_ioctl_invoke_async __user *inv32;
  290. struct fastrpc_ioctl_invoke_async *inv = NULL;
  291. compat_uint_t sc = 0;
  292. int err = 0, len = 0;
  293. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  294. inv32 = compat_ptr(arg);
  295. err = get_user(sc, &inv32->inv.sc);
  296. if (err)
  297. return err;
  298. len = REMOTE_SCALARS_LENGTH(sc);
  299. VERIFY(err, NULL != (inv = kzalloc(
  300. sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL)));
  301. if (err)
  302. return -EFAULT;
  303. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
  304. inv, cmd, sc));
  305. if (err) {
  306. kfree(inv);
  307. return err;
  308. }
  309. VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
  310. fl->mode, COMPAT_MSG, inv)));
  311. kfree(inv);
  312. return err;
  313. }
  314. static int compat_get_fastrpc_ioctl_invoke2(
  315. struct compat_fastrpc_ioctl_invoke2 __user *inv32,
  316. struct fastrpc_ioctl_invoke2 **inva,
  317. unsigned int cmd)
  318. {
  319. int err = 0;
  320. compat_uptr_t pparam, p;
  321. compat_uint_t req, size, ref_size = 0;
  322. struct fastrpc_ioctl_invoke2 *inv2_user = NULL;
  323. struct fastrpc_ioctl_invoke_async *asyncinv_user;
  324. err = get_user(req, &inv32->req);
  325. err |= get_user(pparam, &inv32->invparam);
  326. err |= get_user(size, &inv32->size);
  327. if (err)
  328. goto bail;
  329. switch (req) {
  330. case FASTRPC_INVOKE2_ASYNC:
  331. {
  332. struct compat_fastrpc_ioctl_invoke_async __user *lasync32;
  333. struct compat_fastrpc_ioctl_invoke_async_no_perf __user *lasync32_old;
  334. compat_uint_t sc = 0;
  335. int len = 0;
  336. VERIFY(err, size <= sizeof(*lasync32));
  337. if (err) {
  338. err = -EBADE;
  339. goto bail;
  340. }
  341. lasync32 = compat_ptr(pparam);
  342. err = get_user(sc, &lasync32->inv.sc);
  343. if (err)
  344. goto bail;
  345. len = REMOTE_SCALARS_LENGTH(sc);
  346. VERIFY(err, NULL != (inv2_user = kzalloc(
  347. sizeof(*inv2_user) + sizeof(*asyncinv_user) +
  348. len * sizeof(union remote_arg), GFP_KERNEL)));
  349. if (err) {
  350. err = -EFAULT;
  351. goto bail;
  352. }
  353. asyncinv_user =
  354. (struct fastrpc_ioctl_invoke_async *)(inv2_user + 1);
  355. if (size < sizeof(struct compat_fastrpc_ioctl_invoke_async)) {
  356. lasync32_old = compat_ptr(pparam);
  357. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
  358. asyncinv_user, COMPAT_FASTRPC_IOCTL_INVOKE_CRC, sc));
  359. if (err)
  360. goto bail;
  361. err |= get_user(p, &lasync32_old->job);
  362. memcpy(&asyncinv_user->job, &p, sizeof(p));
  363. } else {
  364. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
  365. asyncinv_user, req, sc));
  366. }
  367. if (err)
  368. goto bail;
  369. memcpy(&inv2_user->req, &req, sizeof(req));
  370. inv2_user->invparam = (uintptr_t)asyncinv_user;
  371. inv2_user->size = sizeof(*asyncinv_user);
  372. break;
  373. }
  374. case FASTRPC_INVOKE2_ASYNC_RESPONSE:
  375. ref_size = sizeof(struct compat_fastrpc_ioctl_async_response);
  376. VERIFY(err, size <= ref_size);
  377. if (err) {
  378. err = -EBADE;
  379. goto bail;
  380. }
  381. fallthrough;
  382. case FASTRPC_INVOKE2_KERNEL_OPTIMIZATIONS:
  383. if (!ref_size) {
  384. ref_size = sizeof(uint32_t);
  385. VERIFY(err, size == ref_size);
  386. if (err) {
  387. err = -EBADE;
  388. goto bail;
  389. }
  390. }
  391. fallthrough;
  392. case FASTRPC_INVOKE2_STATUS_NOTIF:
  393. {
  394. if (!ref_size) {
  395. ref_size = sizeof(struct compat_fastrpc_ioctl_notif_rsp);
  396. VERIFY(err, size == ref_size);
  397. if (err) {
  398. err = -EBADE;
  399. goto bail;
  400. }
  401. }
  402. VERIFY(err, NULL != (inv2_user = kzalloc(
  403. sizeof(*inv2_user), GFP_KERNEL)));
  404. if (err) {
  405. err = -EFAULT;
  406. goto bail;
  407. }
  408. memcpy(&inv2_user->req, &req, sizeof(req));
  409. memcpy(&inv2_user->invparam, &pparam, sizeof(pparam));
  410. memcpy(&inv2_user->size, &size, sizeof(size));
  411. break;
  412. }
  413. default:
  414. err = -ENOTTY;
  415. break;
  416. }
  417. bail:
  418. *inva = inv2_user;
  419. return err;
  420. }
  421. static int compat_fastrpc_ioctl_invoke2(struct file *filp,
  422. unsigned int cmd, unsigned long arg)
  423. {
  424. struct compat_fastrpc_ioctl_invoke2 __user *inv32;
  425. struct fastrpc_ioctl_invoke2 *inv = NULL;
  426. int err = 0;
  427. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  428. inv32 = compat_ptr(arg);
  429. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32,
  430. &inv, cmd));
  431. if (err) {
  432. kfree(inv);
  433. return err;
  434. }
  435. VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv, true)));
  436. kfree(inv);
  437. return err;
  438. }
  439. static int compat_get_fastrpc_ioctl_mem_map(
  440. struct compat_fastrpc_ioctl_mem_map __user *map32,
  441. struct fastrpc_ioctl_mem_map *map)
  442. {
  443. compat_uint_t u = 0;
  444. compat_int_t i = 0;
  445. compat_size_t s = 0;
  446. compat_uptr_t p = 0;
  447. int err;
  448. err = get_user(i, &map32->version);
  449. if (err || i != 0)
  450. return -EINVAL;
  451. memcpy(&map->version, &i, sizeof(i));
  452. err |= get_user(i, &map32->m.fd);
  453. memcpy(&map->m.fd, &i, sizeof(i));
  454. err |= get_user(i, &map32->m.offset);
  455. memcpy(&map->m.offset, &i, sizeof(i));
  456. err |= get_user(u, &map32->m.flags);
  457. memcpy(&map->m.flags, &u, sizeof(u));
  458. err |= get_user(p, &map32->m.vaddrin);
  459. memcpy(&map->m.vaddrin, &s, sizeof(s));
  460. err |= get_user(s, &map32->m.length);
  461. memcpy(&map->m.length, &s, sizeof(s));
  462. err |= get_user(u, &map32->m.attrs);
  463. memcpy(&map->m.attrs, &u, sizeof(u));
  464. return err;
  465. }
  466. static int compat_put_fastrpc_ioctl_mem_map(
  467. struct compat_fastrpc_ioctl_mem_map __user *map32,
  468. struct fastrpc_ioctl_mem_map *map)
  469. {
  470. compat_u64 p;
  471. int err = 0;
  472. memcpy(&p, &map->m.vaddrout, sizeof(map->m.vaddrout));
  473. err |= put_user(p, &map32->m.vaddrout);
  474. return err;
  475. }
  476. static int compat_get_fastrpc_ioctl_mem_unmap(
  477. struct compat_fastrpc_ioctl_mem_unmap __user *unmap32,
  478. struct fastrpc_ioctl_mem_unmap __user *unmap)
  479. {
  480. compat_int_t i;
  481. compat_size_t s;
  482. compat_u64 p;
  483. int err;
  484. err = get_user(i, &unmap32->version);
  485. if (err || i != 0)
  486. return -EINVAL;
  487. memcpy(&unmap->version, &i, sizeof(i));
  488. err |= get_user(i, &unmap32->um.fd);
  489. memcpy(&unmap->um.fd, &i, sizeof(i));
  490. err |= get_user(p, &unmap32->um.vaddr);
  491. memcpy(&unmap->um.vaddr, &p, sizeof(p));
  492. err |= get_user(s, &unmap32->um.length);
  493. memcpy(&unmap->um.length, &s, sizeof(s));
  494. return err;
  495. }
  496. static int compat_get_fastrpc_ioctl_mmap(
  497. struct compat_fastrpc_ioctl_mmap __user *map32,
  498. struct fastrpc_ioctl_mmap __user *map)
  499. {
  500. compat_uint_t u;
  501. compat_int_t i;
  502. compat_size_t s;
  503. compat_uptr_t p;
  504. int err;
  505. err = get_user(i, &map32->fd);
  506. memcpy(&map->fd, &i, sizeof(i));
  507. err |= get_user(u, &map32->flags);
  508. memcpy(&map->flags, &u, sizeof(u));
  509. err |= get_user(p, &map32->vaddrin);
  510. memcpy((uintptr_t *)&map->vaddrin, &p, sizeof(p));
  511. err |= get_user(s, &map32->size);
  512. memcpy(&map->size, &s, sizeof(s));
  513. return err;
  514. }
  515. static int compat_get_fastrpc_ioctl_mmap_64(
  516. struct compat_fastrpc_ioctl_mmap_64 __user *map32,
  517. struct fastrpc_ioctl_mmap __user *map)
  518. {
  519. compat_uint_t u;
  520. compat_int_t i;
  521. compat_size_t s;
  522. compat_u64 p;
  523. int err;
  524. err = get_user(i, &map32->fd);
  525. memcpy(&map->fd, &i, sizeof(i));
  526. err |= get_user(u, &map32->flags);
  527. memcpy(&map->flags, &u, sizeof(u));
  528. err |= get_user(p, &map32->vaddrin);
  529. memcpy(&map->vaddrin, &p, sizeof(p));
  530. err |= get_user(s, &map32->size);
  531. memcpy(&map->size, &s, sizeof(s));
  532. return err;
  533. }
  534. static int compat_put_fastrpc_ioctl_mmap(
  535. struct compat_fastrpc_ioctl_mmap __user *map32,
  536. struct fastrpc_ioctl_mmap __user *map)
  537. {
  538. compat_uptr_t p;
  539. int err = 0;
  540. memcpy(&p, &map->vaddrout, sizeof(p));
  541. err |= put_user(p, &map32->vaddrout);
  542. return err;
  543. }
  544. static int compat_put_fastrpc_ioctl_mmap_64(
  545. struct compat_fastrpc_ioctl_mmap_64 __user *map32,
  546. struct fastrpc_ioctl_mmap __user *map)
  547. {
  548. compat_u64 p;
  549. int err = 0;
  550. memcpy(&p, &map->vaddrout, sizeof(map->vaddrout));
  551. err |= put_user(p, &map32->vaddrout);
  552. return err;
  553. }
  554. static int compat_get_fastrpc_ioctl_munmap(
  555. struct compat_fastrpc_ioctl_munmap __user *unmap32,
  556. struct fastrpc_ioctl_munmap __user *unmap)
  557. {
  558. compat_uptr_t p;
  559. compat_size_t s;
  560. int err;
  561. err = get_user(p, &unmap32->vaddrout);
  562. memcpy(&unmap->vaddrout, &p, sizeof(p));
  563. err |= get_user(s, &unmap32->size);
  564. memcpy(&unmap->size, &s, sizeof(s));
  565. return err;
  566. }
  567. static int compat_get_fastrpc_ioctl_munmap_64(
  568. struct compat_fastrpc_ioctl_munmap_64 __user *unmap32,
  569. struct fastrpc_ioctl_munmap *unmap)
  570. {
  571. compat_u64 p;
  572. compat_size_t s;
  573. int err;
  574. err = get_user(p, &unmap32->vaddrout);
  575. memcpy(&unmap->vaddrout, &p, sizeof(p));
  576. err |= get_user(s, &unmap32->size);
  577. memcpy(&unmap->size, &s, sizeof(s));
  578. return err;
  579. }
  580. static int compat_get_fastrpc_ioctl_control(
  581. struct compat_fastrpc_ioctl_control __user *ctrl32,
  582. struct fastrpc_ioctl_control *ctrl)
  583. {
  584. compat_uptr_t p;
  585. int err;
  586. err = get_user(p, &ctrl32->req);
  587. memcpy(&ctrl->req, &p, sizeof(p));
  588. if ((p == FASTRPC_CONTROL_LATENCY) || (p == FASTRPC_CONTROL_RPC_POLL)) {
  589. err |= get_user(p, &ctrl32->lp.enable);
  590. memcpy(&ctrl->lp.enable, &p, sizeof(p));
  591. err |= get_user(p, &ctrl32->lp.latency);
  592. memcpy(&ctrl->lp.latency, &p, sizeof(p));
  593. } else if (p == FASTRPC_CONTROL_WAKELOCK) {
  594. err |= get_user(p, &ctrl32->wp.enable);
  595. memcpy(&ctrl->wp.enable, &p, sizeof(p));
  596. } else if (p == FASTRPC_CONTROL_PM) {
  597. err |= get_user(p, &ctrl32->pm.timeout);
  598. memcpy(&ctrl->pm.timeout, &p, sizeof(p));
  599. }
  600. return err;
  601. }
  602. static int compat_get_fastrpc_ioctl_init(
  603. struct compat_fastrpc_ioctl_init_attrs __user *init32,
  604. struct fastrpc_ioctl_init_attrs *init,
  605. unsigned int cmd)
  606. {
  607. compat_uint_t u;
  608. compat_uptr_t p;
  609. compat_int_t i;
  610. int err;
  611. err = get_user(u, &init32->init.flags);
  612. memcpy(&init->init.flags, &u, sizeof(u));
  613. err |= get_user(p, &init32->init.file);
  614. memcpy(&init->init.file, &p, sizeof(p));
  615. err |= get_user(i, &init32->init.filelen);
  616. memcpy(&init->init.filelen, &i, sizeof(i));
  617. err |= get_user(i, &init32->init.filefd);
  618. memcpy(&init->init.filefd, &i, sizeof(i));
  619. err |= get_user(p, &init32->init.mem);
  620. memcpy(&init->init.mem, &p, sizeof(p));
  621. err |= get_user(i, &init32->init.memlen);
  622. memcpy(&init->init.memlen, &i, sizeof(i));
  623. err |= get_user(i, &init32->init.memfd);
  624. memcpy(&init->init.memfd, &i, sizeof(i));
  625. init->attrs = 0;
  626. if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
  627. err |= get_user(i, &init32->attrs);
  628. memcpy((compat_uptr_t *)&init->attrs, &i, sizeof(i));
  629. }
  630. init->siglen = 0;
  631. if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
  632. err |= get_user(i, &init32->siglen);
  633. memcpy((compat_uptr_t *)&init->siglen, &i, sizeof(i));
  634. }
  635. return err;
  636. }
  637. static int compat_put_fastrpc_ioctl_get_dsp_info(
  638. struct compat_fastrpc_ioctl_capability __user *info32,
  639. struct fastrpc_ioctl_capability __user *info)
  640. {
  641. compat_uint_t u;
  642. int err = 0;
  643. memcpy(&u, &info->capability, sizeof(u));
  644. err |= put_user(u, &info32->capability);
  645. return err;
  646. }
  647. static int compat_fastrpc_control(struct fastrpc_file *fl,
  648. unsigned long arg)
  649. {
  650. int err = 0;
  651. struct compat_fastrpc_ioctl_control __user *ctrl32;
  652. struct fastrpc_ioctl_control *ctrl = NULL;
  653. compat_uptr_t p;
  654. ctrl32 = compat_ptr(arg);
  655. VERIFY(err, NULL != (ctrl = kzalloc(
  656. sizeof(*ctrl), GFP_KERNEL)));
  657. if (err)
  658. return -EFAULT;
  659. VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
  660. ctrl));
  661. if (err)
  662. goto bail;
  663. VERIFY(err, 0 == (err = fastrpc_internal_control(fl, ctrl)));
  664. if (err)
  665. goto bail;
  666. err = get_user(p, &ctrl32->req);
  667. if (err)
  668. goto bail;
  669. if (p == FASTRPC_CONTROL_KALLOC) {
  670. memcpy(&p, &ctrl->kalloc.kalloc_support, sizeof(ctrl->kalloc.kalloc_support));
  671. err |= put_user(p, &ctrl32->kalloc.kalloc_support);
  672. }
  673. bail:
  674. kfree(ctrl);
  675. return err;
  676. }
  677. static int compat_fastrpc_get_dsp_info(struct fastrpc_file *fl,
  678. unsigned long arg)
  679. {
  680. struct compat_fastrpc_ioctl_capability __user *info32 = NULL;
  681. struct fastrpc_ioctl_capability *info = NULL;
  682. compat_uint_t u;
  683. int err = 0;
  684. size_t info_size = 0;
  685. info32 = compat_ptr(arg);
  686. VERIFY(err, NULL != (info = kzalloc(
  687. sizeof(*info), GFP_KERNEL)));
  688. info_size = sizeof(*info);
  689. if (err) {
  690. ADSPRPC_ERR("allocation failed for size 0x%zx\n", info_size);
  691. return err;
  692. }
  693. err = get_user(u, &info32->domain);
  694. if (err)
  695. goto bail;
  696. memcpy(&info->domain, &u, sizeof(info->domain));
  697. err = get_user(u, &info32->attribute_ID);
  698. if (err)
  699. goto bail;
  700. memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID));
  701. err = fastrpc_get_info_from_kernel(info, fl);
  702. if (err)
  703. goto bail;
  704. err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
  705. bail:
  706. kfree(info);
  707. return err;
  708. }
  709. static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
  710. unsigned int cmd, unsigned long arg)
  711. {
  712. int err = 0;
  713. switch (cmd) {
  714. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  715. {
  716. struct compat_fastrpc_ioctl_mem_map __user *map32;
  717. struct fastrpc_ioctl_mem_map *map = NULL;
  718. map32 = compat_ptr(arg);
  719. VERIFY(err, NULL != (map = kzalloc(
  720. sizeof(*map), GFP_KERNEL)));
  721. if (err)
  722. return -EFAULT;
  723. err = compat_get_fastrpc_ioctl_mem_map(map32, map);
  724. if (err) {
  725. kfree(map);
  726. return err;
  727. }
  728. VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl,
  729. map)));
  730. if (err) {
  731. kfree(map);
  732. return err;
  733. }
  734. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map));
  735. kfree(map);
  736. return err;
  737. }
  738. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  739. {
  740. struct compat_fastrpc_ioctl_mem_unmap __user *unmap32;
  741. struct fastrpc_ioctl_mem_unmap *unmap = NULL;
  742. unmap32 = compat_ptr(arg);
  743. unmap = kzalloc(sizeof(*unmap), GFP_KERNEL);
  744. if (unmap == NULL)
  745. return -EFAULT;
  746. err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap);
  747. if (err) {
  748. kfree(unmap);
  749. return err;
  750. }
  751. VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl,
  752. unmap)));
  753. kfree(unmap);
  754. return err;
  755. }
  756. case COMPAT_FASTRPC_IOCTL_MMAP:
  757. {
  758. struct compat_fastrpc_ioctl_mmap __user *map32;
  759. struct fastrpc_ioctl_mmap *map = NULL;
  760. map32 = compat_ptr(arg);
  761. VERIFY(err, NULL != (map = kzalloc(
  762. sizeof(*map), GFP_KERNEL)));
  763. if (err)
  764. return -EFAULT;
  765. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
  766. if (err) {
  767. kfree(map);
  768. return err;
  769. }
  770. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  771. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
  772. kfree(map);
  773. return err;
  774. }
  775. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  776. {
  777. struct compat_fastrpc_ioctl_mmap_64 __user *map32;
  778. struct fastrpc_ioctl_mmap *map = NULL;
  779. map32 = compat_ptr(arg);
  780. VERIFY(err, NULL != (map = kzalloc(
  781. sizeof(*map), GFP_KERNEL)));
  782. if (err)
  783. return -EFAULT;
  784. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
  785. if (err) {
  786. kfree(map);
  787. return err;
  788. }
  789. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  790. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
  791. kfree(map);
  792. return err;
  793. }
  794. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  795. {
  796. struct compat_fastrpc_ioctl_munmap __user *unmap32;
  797. struct fastrpc_ioctl_munmap *unmap = NULL;
  798. unmap32 = compat_ptr(arg);
  799. VERIFY(err, NULL != (unmap = kzalloc(
  800. sizeof(*unmap), GFP_KERNEL)));
  801. if (err)
  802. return -EFAULT;
  803. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
  804. unmap));
  805. if (err) {
  806. kfree(unmap);
  807. return err;
  808. }
  809. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  810. unmap)));
  811. kfree(unmap);
  812. return err;
  813. }
  814. default:
  815. return -ENOIOCTLCMD;
  816. }
  817. }
  818. static long compat_fastrpc_dspsignal_create(struct fastrpc_file *fl, unsigned long arg)
  819. {
  820. struct fastrpc_ioctl_dspsignal_create __user *uc = compat_ptr(arg);
  821. struct fastrpc_ioctl_dspsignal_create c;
  822. int err = 0;
  823. err = copy_from_user(&c, uc, sizeof(c));
  824. if (err)
  825. return -EFAULT;
  826. return fastrpc_dspsignal_create(fl, &c);
  827. }
  828. static long compat_fastrpc_dspsignal_destroy(struct fastrpc_file *fl, unsigned long arg)
  829. {
  830. struct fastrpc_ioctl_dspsignal_destroy __user *uc = compat_ptr(arg);
  831. struct fastrpc_ioctl_dspsignal_destroy c;
  832. int err = 0;
  833. err = copy_from_user(&c, uc, sizeof(c));
  834. if (err)
  835. return -EFAULT;
  836. return fastrpc_dspsignal_destroy(fl, &c);
  837. }
  838. static long compat_fastrpc_dspsignal_signal(struct fastrpc_file *fl, unsigned long arg)
  839. {
  840. struct fastrpc_ioctl_dspsignal_signal __user *uc = compat_ptr(arg);
  841. struct fastrpc_ioctl_dspsignal_signal c;
  842. int err = 0;
  843. err = copy_from_user(&c, uc, sizeof(c));
  844. if (err)
  845. return -EFAULT;
  846. return fastrpc_dspsignal_signal(fl, &c);
  847. }
  848. static long compat_fastrpc_dspsignal_wait(struct fastrpc_file *fl, unsigned long arg)
  849. {
  850. struct fastrpc_ioctl_dspsignal_wait __user *uc = compat_ptr(arg);
  851. struct fastrpc_ioctl_dspsignal_wait c;
  852. int err = 0;
  853. err = copy_from_user(&c, uc, sizeof(c));
  854. if (err)
  855. return -EFAULT;
  856. return fastrpc_dspsignal_wait(fl, &c);
  857. }
  858. static long compat_fastrpc_dspsignal_cancel_wait(struct fastrpc_file *fl, unsigned long arg)
  859. {
  860. struct fastrpc_ioctl_dspsignal_cancel_wait __user *uc = compat_ptr(arg);
  861. struct fastrpc_ioctl_dspsignal_cancel_wait c;
  862. int err = 0;
  863. err = copy_from_user(&c, uc, sizeof(c));
  864. if (err)
  865. return -EFAULT;
  866. return fastrpc_dspsignal_cancel_wait(fl, &c);
  867. }
  868. long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
  869. unsigned long arg)
  870. {
  871. int err = 0;
  872. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  873. if (!filp->f_op || !filp->f_op->unlocked_ioctl)
  874. return -ENOTTY;
  875. switch (cmd) {
  876. case COMPAT_FASTRPC_IOCTL_INVOKE:
  877. case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
  878. case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
  879. case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
  880. case COMPAT_FASTRPC_IOCTL_INVOKE_PERF:
  881. {
  882. return compat_fastrpc_ioctl_invoke(filp, cmd, arg);
  883. }
  884. case COMPAT_FASTRPC_IOCTL_INVOKE2:
  885. {
  886. return compat_fastrpc_ioctl_invoke2(filp, cmd, arg);
  887. }
  888. case COMPAT_FASTRPC_IOCTL_MUNMAP_64:
  889. {
  890. struct compat_fastrpc_ioctl_munmap_64 __user *unmap32;
  891. struct fastrpc_ioctl_munmap *unmap = NULL;
  892. unmap32 = compat_ptr(arg);
  893. VERIFY(err, NULL != (unmap = kzalloc(
  894. sizeof(*unmap), GFP_KERNEL)));
  895. if (err)
  896. return -EFAULT;
  897. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
  898. unmap));
  899. if (err) {
  900. kfree(unmap);
  901. return err;
  902. }
  903. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  904. unmap)));
  905. kfree(unmap);
  906. return err;
  907. }
  908. case COMPAT_FASTRPC_IOCTL_INIT:
  909. fallthrough;
  910. case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
  911. {
  912. struct compat_fastrpc_ioctl_init_attrs __user *init32;
  913. struct fastrpc_ioctl_init_attrs *init = NULL;
  914. init32 = compat_ptr(arg);
  915. VERIFY(err, NULL != (init = kzalloc(
  916. sizeof(*init), GFP_KERNEL)));
  917. if (err)
  918. return -EFAULT;
  919. VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
  920. init, cmd));
  921. if (err) {
  922. kfree(init);
  923. return err;
  924. }
  925. VERIFY(err, 0 == (err = fastrpc_init_process(fl, init)));
  926. kfree(init);
  927. return err;
  928. }
  929. case FASTRPC_IOCTL_GETINFO:
  930. {
  931. compat_uptr_t __user *info32;
  932. uint32_t *info = NULL;
  933. compat_uint_t u;
  934. info32 = compat_ptr(arg);
  935. VERIFY(err, NULL != (info = kzalloc(
  936. sizeof(*info), GFP_KERNEL)));
  937. if (err)
  938. return -EFAULT;
  939. err = get_user(u, info32);
  940. memcpy(info, &u, sizeof(u));
  941. if (err) {
  942. kfree(info);
  943. return err;
  944. }
  945. VERIFY(err, 0 == (err = fastrpc_get_info(fl, info)));
  946. memcpy(&u, info, sizeof(*info));
  947. err |= put_user(u, info32);
  948. kfree(info);
  949. return err;
  950. }
  951. case FASTRPC_IOCTL_SETMODE:
  952. return fastrpc_setmode(arg, fl);
  953. case COMPAT_FASTRPC_IOCTL_CONTROL:
  954. {
  955. return compat_fastrpc_control(fl, arg);
  956. }
  957. case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
  958. {
  959. return compat_fastrpc_get_dsp_info(fl, arg);
  960. }
  961. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  962. fallthrough;
  963. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  964. fallthrough;
  965. case COMPAT_FASTRPC_IOCTL_MMAP:
  966. fallthrough;
  967. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  968. fallthrough;
  969. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  970. return compat_fastrpc_mmap_device_ioctl(fl, cmd, arg);
  971. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE:
  972. return compat_fastrpc_dspsignal_create(fl, arg);
  973. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY:
  974. return compat_fastrpc_dspsignal_destroy(fl, arg);
  975. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL:
  976. return compat_fastrpc_dspsignal_signal(fl, arg);
  977. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT:
  978. return compat_fastrpc_dspsignal_wait(fl, arg);
  979. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT:
  980. return compat_fastrpc_dspsignal_cancel_wait(fl, arg);
  981. default:
  982. return -ENOTTY;
  983. }
  984. }