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