1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, Linaro Limited 4 */ 5 #include <linux/device.h> 6 #include <linux/slab.h> 7 #include <linux/uaccess.h> 8 #include "optee_private.h" 9 10 struct optee_supp_req { 11 struct list_head link; 12 13 int id; 14 15 bool in_queue; 16 bool processed; 17 18 u32 func; 19 u32 ret; 20 size_t num_params; 21 struct tee_param *param; 22 23 struct completion c; 24 }; 25 26 /* It is temporary request used for revoked pending request in supp->idr. */ 27 #define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF)) 28 29 void optee_supp_init(struct optee_supp *supp) 30 { 31 memset(supp, 0, sizeof(*supp)); 32 mutex_init(&supp->mutex); 33 init_completion(&supp->reqs_c); 34 idr_init(&supp->idr); 35 INIT_LIST_HEAD(&supp->reqs); 36 supp->req_id = -1; 37 } 38 39 void optee_supp_uninit(struct optee_supp *supp) 40 { 41 mutex_destroy(&supp->mutex); 42 idr_destroy(&supp->idr); 43 } 44 45 void optee_supp_release(struct optee_supp *supp) 46 { 47 int id; 48 struct optee_supp_req *req; 49 50 mutex_lock(&supp->mutex); 51 52 /* Abort all request */ 53 idr_for_each_entry(&supp->idr, req, id) { 54 idr_remove(&supp->idr, id); 55 /* Skip if request was already marked invalid */ 56 if (IS_ERR(req)) 57 continue; 58 59 /* For queued requests where supplicant has not seen it */ 60 if (req->in_queue) { 61 list_del(&req->link); 62 req->in_queue = false; 63 } 64 65 req->processed = true; 66 req->ret = TEEC_ERROR_COMMUNICATION; 67 complete(&req->c); 68 } 69 70 supp->ctx = NULL; 71 supp->req_id = -1; 72 73 mutex_unlock(&supp->mutex); 74 } 75 76 /** 77 * optee_supp_thrd_req() - request service from supplicant 78 * @ctx: context doing the request 79 * @func: function requested 80 * @num_params: number of elements in @param array 81 * @param: parameters for function 82 * 83 * Returns result of operation to be passed to secure world 84 */ 85 u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, 86 struct tee_param *param) 87 88 { 89 struct optee *optee = tee_get_drvdata(ctx->teedev); 90 struct optee_supp *supp = &optee->supp; 91 struct optee_supp_req *req; 92 u32 ret; 93 94 /* 95 * Return in case there is no supplicant available and 96 * non-blocking request. 97 */ 98 if (!supp->ctx && ctx->supp_nowait) 99 return TEEC_ERROR_COMMUNICATION; 100 101 req = kzalloc_obj(*req); 102 if (!req) 103 return TEEC_ERROR_OUT_OF_MEMORY; 104 105 init_completion(&req->c); 106 req->func = func; 107 req->num_params = num_params; 108 req->param = param; 109 110 /* Insert the request in the request list */ 111 mutex_lock(&supp->mutex); 112 req->id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL); 113 if (req->id < 0) { 114 mutex_unlock(&supp->mutex); 115 kfree(req); 116 return TEEC_ERROR_OUT_OF_MEMORY; 117 } 118 119 list_add_tail(&req->link, &supp->reqs); 120 req->in_queue = true; 121 req->processed = false; 122 mutex_unlock(&supp->mutex); 123 124 /* Tell an eventual waiter there's a new request */ 125 complete(&supp->reqs_c); 126 127 /* 128 * Wait for supplicant to process and return result, once we've 129 * returned from wait_for_completion(&req->c) successfully we have 130 * exclusive access again. Allow the wait to be killable such that 131 * the wait doesn't turn into an indefinite state if the supplicant 132 * gets hung for some reason. 133 */ 134 if (wait_for_completion_killable(&req->c)) { 135 mutex_lock(&supp->mutex); 136 if (req->in_queue) { 137 /* Supplicant has not seen this request yet. */ 138 idr_remove(&supp->idr, req->id); 139 list_del(&req->link); 140 req->in_queue = false; 141 142 ret = TEEC_ERROR_COMMUNICATION; 143 } else if (req->processed) { 144 /* 145 * Supplicant has processed this request. Ignore the 146 * kill signal for now and submit the result. req is not 147 * in supp->reqs (removed by supp_pop_entry()) nor in 148 * supp->idr (removed by supp_pop_req()). 149 */ 150 ret = req->ret; 151 } else { 152 /* 153 * Supplicant is in the middle of processing this 154 * request. Replace req with INVALID_REQ_PTR so that 155 * the ID remains busy, causing optee_supp_send() to 156 * fail on the next call to supp_pop_req() with this ID. 157 */ 158 idr_replace(&supp->idr, INVALID_REQ_PTR, req->id); 159 ret = TEEC_ERROR_COMMUNICATION; 160 } 161 162 mutex_unlock(&supp->mutex); 163 } else { 164 ret = req->ret; 165 } 166 167 kfree(req); 168 169 return ret; 170 } 171 172 static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp, 173 int num_params) 174 { 175 struct optee_supp_req *req; 176 177 if (supp->req_id != -1) { 178 /* 179 * Supplicant should not mix synchronous and asnynchronous 180 * requests. 181 */ 182 return ERR_PTR(-EINVAL); 183 } 184 185 if (list_empty(&supp->reqs)) 186 return NULL; 187 188 req = list_first_entry(&supp->reqs, struct optee_supp_req, link); 189 190 if (num_params < req->num_params) { 191 /* Not enough room for parameters */ 192 return ERR_PTR(-EINVAL); 193 } 194 195 list_del(&req->link); 196 req->in_queue = false; 197 198 return req; 199 } 200 201 static int supp_check_recv_params(size_t num_params, struct tee_param *params, 202 size_t *num_meta) 203 { 204 size_t n; 205 206 if (!num_params) 207 return -EINVAL; 208 209 /* 210 * If there's memrefs we need to decrease those as they where 211 * increased earlier and we'll even refuse to accept any below. 212 */ 213 for (n = 0; n < num_params; n++) 214 if (tee_param_is_memref(params + n) && params[n].u.memref.shm) 215 tee_shm_put(params[n].u.memref.shm); 216 217 /* 218 * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with 219 * or without the TEE_IOCTL_PARAM_ATTR_META bit set. 220 */ 221 for (n = 0; n < num_params; n++) 222 if (params[n].attr && 223 params[n].attr != TEE_IOCTL_PARAM_ATTR_META) 224 return -EINVAL; 225 226 /* At most we'll need one meta parameter so no need to check for more */ 227 if (params->attr == TEE_IOCTL_PARAM_ATTR_META) 228 *num_meta = 1; 229 else 230 *num_meta = 0; 231 232 return 0; 233 } 234 235 /** 236 * optee_supp_recv() - receive request for supplicant 237 * @ctx: context receiving the request 238 * @func: requested function in supplicant 239 * @num_params: number of elements allocated in @param, updated with number 240 * used elements 241 * @param: space for parameters for @func 242 * 243 * Returns 0 on success or <0 on failure 244 */ 245 int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, 246 struct tee_param *param) 247 { 248 struct tee_device *teedev = ctx->teedev; 249 struct optee *optee = tee_get_drvdata(teedev); 250 struct optee_supp *supp = &optee->supp; 251 struct optee_supp_req *req = NULL; 252 size_t num_meta; 253 int rc; 254 255 rc = supp_check_recv_params(*num_params, param, &num_meta); 256 if (rc) 257 return rc; 258 259 while (true) { 260 mutex_lock(&supp->mutex); 261 req = supp_pop_entry(supp, *num_params - num_meta); 262 if (req) 263 break; /* Keep mutex held. */ 264 mutex_unlock(&supp->mutex); 265 266 /* 267 * If we didn't get a request we'll block in 268 * wait_for_completion() to avoid needless spinning. 269 * 270 * This is where supplicant will be hanging most of 271 * the time, let's make this interruptable so we 272 * can easily restart supplicant if needed. 273 */ 274 if (wait_for_completion_interruptible(&supp->reqs_c)) 275 return -ERESTARTSYS; 276 } 277 278 /* supp->mutex held and req != NULL. */ 279 280 if (IS_ERR(req)) { 281 mutex_unlock(&supp->mutex); 282 return PTR_ERR(req); 283 } 284 285 if (num_meta) { 286 /* 287 * tee-supplicant support meta parameters -> requsts can be 288 * processed asynchronously. 289 */ 290 param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT | 291 TEE_IOCTL_PARAM_ATTR_META; 292 param->u.value.a = req->id; 293 param->u.value.b = 0; 294 param->u.value.c = 0; 295 } else { 296 supp->req_id = req->id; 297 } 298 299 *func = req->func; 300 *num_params = req->num_params + num_meta; 301 memcpy(param + num_meta, req->param, 302 sizeof(struct tee_param) * req->num_params); 303 304 mutex_unlock(&supp->mutex); 305 return 0; 306 } 307 308 static struct optee_supp_req *supp_pop_req(struct optee_supp *supp, 309 size_t num_params, 310 struct tee_param *param, 311 size_t *num_meta) 312 { 313 struct optee_supp_req *req; 314 int id; 315 size_t nm; 316 const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT | 317 TEE_IOCTL_PARAM_ATTR_META; 318 319 if (!num_params) 320 return ERR_PTR(-EINVAL); 321 322 if (supp->req_id == -1) { 323 if (param->attr != attr) 324 return ERR_PTR(-EINVAL); 325 id = param->u.value.a; 326 nm = 1; 327 } else { 328 id = supp->req_id; 329 nm = 0; 330 } 331 332 req = idr_find(&supp->idr, id); 333 if (!req) 334 return ERR_PTR(-ENOENT); 335 336 /* optee_supp_thrd_req() already returned to optee. */ 337 if (IS_ERR(req)) 338 goto failed_req; 339 340 if ((num_params - nm) != req->num_params) 341 return ERR_PTR(-EINVAL); 342 343 *num_meta = nm; 344 failed_req: 345 idr_remove(&supp->idr, id); 346 supp->req_id = -1; 347 348 return req; 349 } 350 351 /** 352 * optee_supp_send() - send result of request from supplicant 353 * @ctx: context sending result 354 * @ret: return value of request 355 * @num_params: number of parameters returned 356 * @param: returned parameters 357 * 358 * Returns 0 on success or <0 on failure. 359 */ 360 int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params, 361 struct tee_param *param) 362 { 363 struct tee_device *teedev = ctx->teedev; 364 struct optee *optee = tee_get_drvdata(teedev); 365 struct optee_supp *supp = &optee->supp; 366 struct optee_supp_req *req; 367 size_t n; 368 size_t num_meta; 369 370 mutex_lock(&supp->mutex); 371 req = supp_pop_req(supp, num_params, param, &num_meta); 372 if (IS_ERR(req)) { 373 mutex_unlock(&supp->mutex); 374 /* Something is wrong, let supplicant handel it. */ 375 return PTR_ERR(req); 376 } 377 378 /* Update out and in/out parameters */ 379 for (n = 0; n < req->num_params; n++) { 380 struct tee_param *p = req->param + n; 381 382 switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { 383 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: 384 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: 385 p->u.value.a = param[n + num_meta].u.value.a; 386 p->u.value.b = param[n + num_meta].u.value.b; 387 p->u.value.c = param[n + num_meta].u.value.c; 388 break; 389 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: 390 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: 391 p->u.memref.size = param[n + num_meta].u.memref.size; 392 break; 393 default: 394 break; 395 } 396 } 397 req->ret = ret; 398 req->processed = true; 399 /* Let the requesting thread continue */ 400 complete(&req->c); 401 mutex_unlock(&supp->mutex); 402 403 return 0; 404 } 405