supp.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (c) 2015, Linaro Limited
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  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. #include <linux/device.h>
  15. #include <linux/slab.h>
  16. #include <linux/uaccess.h>
  17. #include "optee_private.h"
  18. void optee_supp_init(struct optee_supp *supp)
  19. {
  20. memset(supp, 0, sizeof(*supp));
  21. mutex_init(&supp->ctx_mutex);
  22. mutex_init(&supp->thrd_mutex);
  23. mutex_init(&supp->supp_mutex);
  24. init_completion(&supp->data_to_supp);
  25. init_completion(&supp->data_from_supp);
  26. }
  27. void optee_supp_uninit(struct optee_supp *supp)
  28. {
  29. mutex_destroy(&supp->ctx_mutex);
  30. mutex_destroy(&supp->thrd_mutex);
  31. mutex_destroy(&supp->supp_mutex);
  32. }
  33. /**
  34. * optee_supp_thrd_req() - request service from supplicant
  35. * @ctx: context doing the request
  36. * @func: function requested
  37. * @num_params: number of elements in @param array
  38. * @param: parameters for function
  39. *
  40. * Returns result of operation to be passed to secure world
  41. */
  42. u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
  43. struct tee_param *param)
  44. {
  45. bool interruptable;
  46. struct optee *optee = tee_get_drvdata(ctx->teedev);
  47. struct optee_supp *supp = &optee->supp;
  48. u32 ret;
  49. /*
  50. * Other threads blocks here until we've copied our answer from
  51. * supplicant.
  52. */
  53. while (mutex_lock_interruptible(&supp->thrd_mutex)) {
  54. /* See comment below on when the RPC can be interrupted. */
  55. mutex_lock(&supp->ctx_mutex);
  56. interruptable = !supp->ctx;
  57. mutex_unlock(&supp->ctx_mutex);
  58. if (interruptable)
  59. return TEEC_ERROR_COMMUNICATION;
  60. }
  61. /*
  62. * We have exclusive access now since the supplicant at this
  63. * point is either doing a
  64. * wait_for_completion_interruptible(&supp->data_to_supp) or is in
  65. * userspace still about to do the ioctl() to enter
  66. * optee_supp_recv() below.
  67. */
  68. supp->func = func;
  69. supp->num_params = num_params;
  70. supp->param = param;
  71. supp->req_posted = true;
  72. /* Let supplicant get the data */
  73. complete(&supp->data_to_supp);
  74. /*
  75. * Wait for supplicant to process and return result, once we've
  76. * returned from wait_for_completion(data_from_supp) we have
  77. * exclusive access again.
  78. */
  79. while (wait_for_completion_interruptible(&supp->data_from_supp)) {
  80. mutex_lock(&supp->ctx_mutex);
  81. interruptable = !supp->ctx;
  82. if (interruptable) {
  83. /*
  84. * There's no supplicant available and since the
  85. * supp->ctx_mutex currently is held none can
  86. * become available until the mutex released
  87. * again.
  88. *
  89. * Interrupting an RPC to supplicant is only
  90. * allowed as a way of slightly improving the user
  91. * experience in case the supplicant hasn't been
  92. * started yet. During normal operation the supplicant
  93. * will serve all requests in a timely manner and
  94. * interrupting then wouldn't make sense.
  95. */
  96. supp->ret = TEEC_ERROR_COMMUNICATION;
  97. init_completion(&supp->data_to_supp);
  98. }
  99. mutex_unlock(&supp->ctx_mutex);
  100. if (interruptable)
  101. break;
  102. }
  103. ret = supp->ret;
  104. supp->param = NULL;
  105. supp->req_posted = false;
  106. /* We're done, let someone else talk to the supplicant now. */
  107. mutex_unlock(&supp->thrd_mutex);
  108. return ret;
  109. }
  110. /**
  111. * optee_supp_recv() - receive request for supplicant
  112. * @ctx: context receiving the request
  113. * @func: requested function in supplicant
  114. * @num_params: number of elements allocated in @param, updated with number
  115. * used elements
  116. * @param: space for parameters for @func
  117. *
  118. * Returns 0 on success or <0 on failure
  119. */
  120. int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
  121. struct tee_param *param)
  122. {
  123. struct tee_device *teedev = ctx->teedev;
  124. struct optee *optee = tee_get_drvdata(teedev);
  125. struct optee_supp *supp = &optee->supp;
  126. int rc;
  127. /*
  128. * In case two threads in one supplicant is calling this function
  129. * simultaneously we need to protect the data with a mutex which
  130. * we'll release before returning.
  131. */
  132. mutex_lock(&supp->supp_mutex);
  133. if (supp->supp_next_send) {
  134. /*
  135. * optee_supp_recv() has been called again without
  136. * a optee_supp_send() in between. Supplicant has
  137. * probably been restarted before it was able to
  138. * write back last result. Abort last request and
  139. * wait for a new.
  140. */
  141. if (supp->req_posted) {
  142. supp->ret = TEEC_ERROR_COMMUNICATION;
  143. supp->supp_next_send = false;
  144. complete(&supp->data_from_supp);
  145. }
  146. }
  147. /*
  148. * This is where supplicant will be hanging most of the
  149. * time, let's make this interruptable so we can easily
  150. * restart supplicant if needed.
  151. */
  152. if (wait_for_completion_interruptible(&supp->data_to_supp)) {
  153. rc = -ERESTARTSYS;
  154. goto out;
  155. }
  156. /* We have exlusive access to the data */
  157. if (*num_params < supp->num_params) {
  158. /*
  159. * Not enough room for parameters, tell supplicant
  160. * it failed and abort last request.
  161. */
  162. supp->ret = TEEC_ERROR_COMMUNICATION;
  163. rc = -EINVAL;
  164. complete(&supp->data_from_supp);
  165. goto out;
  166. }
  167. *func = supp->func;
  168. *num_params = supp->num_params;
  169. memcpy(param, supp->param,
  170. sizeof(struct tee_param) * supp->num_params);
  171. /* Allow optee_supp_send() below to do its work */
  172. supp->supp_next_send = true;
  173. rc = 0;
  174. out:
  175. mutex_unlock(&supp->supp_mutex);
  176. return rc;
  177. }
  178. /**
  179. * optee_supp_send() - send result of request from supplicant
  180. * @ctx: context sending result
  181. * @ret: return value of request
  182. * @num_params: number of parameters returned
  183. * @param: returned parameters
  184. *
  185. * Returns 0 on success or <0 on failure.
  186. */
  187. int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
  188. struct tee_param *param)
  189. {
  190. struct tee_device *teedev = ctx->teedev;
  191. struct optee *optee = tee_get_drvdata(teedev);
  192. struct optee_supp *supp = &optee->supp;
  193. size_t n;
  194. int rc = 0;
  195. /*
  196. * We still have exclusive access to the data since that's how we
  197. * left it when returning from optee_supp_read().
  198. */
  199. /* See comment on mutex in optee_supp_read() above */
  200. mutex_lock(&supp->supp_mutex);
  201. if (!supp->supp_next_send) {
  202. /*
  203. * Something strange is going on, supplicant shouldn't
  204. * enter optee_supp_send() in this state
  205. */
  206. rc = -ENOENT;
  207. goto out;
  208. }
  209. if (num_params != supp->num_params) {
  210. /*
  211. * Something is wrong, let supplicant restart. Next call to
  212. * optee_supp_recv() will give an error to the requesting
  213. * thread and release it.
  214. */
  215. rc = -EINVAL;
  216. goto out;
  217. }
  218. /* Update out and in/out parameters */
  219. for (n = 0; n < num_params; n++) {
  220. struct tee_param *p = supp->param + n;
  221. switch (p->attr) {
  222. case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
  223. case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
  224. p->u.value.a = param[n].u.value.a;
  225. p->u.value.b = param[n].u.value.b;
  226. p->u.value.c = param[n].u.value.c;
  227. break;
  228. case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
  229. case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
  230. p->u.memref.size = param[n].u.memref.size;
  231. break;
  232. default:
  233. break;
  234. }
  235. }
  236. supp->ret = ret;
  237. /* Allow optee_supp_recv() above to do its work */
  238. supp->supp_next_send = false;
  239. /* Let the requesting thread continue */
  240. complete(&supp->data_from_supp);
  241. out:
  242. mutex_unlock(&supp->supp_mutex);
  243. return rc;
  244. }