1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015-2021, Linaro Limited 4 */ 5 #include <linux/device.h> 6 #include <linux/err.h> 7 #include <linux/errno.h> 8 #include <linux/mm.h> 9 #include <linux/slab.h> 10 #include <linux/tee_drv.h> 11 #include <linux/types.h> 12 #include "optee_private.h" 13 14 void optee_cq_wait_init(struct optee_call_queue *cq, 15 struct optee_call_waiter *w) 16 { 17 /* 18 * We're preparing to make a call to secure world. In case we can't 19 * allocate a thread in secure world we'll end up waiting in 20 * optee_cq_wait_for_completion(). 21 * 22 * Normally if there's no contention in secure world the call will 23 * complete and we can cleanup directly with optee_cq_wait_final(). 24 */ 25 mutex_lock(&cq->mutex); 26 27 /* 28 * We add ourselves to the queue, but we don't wait. This 29 * guarantees that we don't lose a completion if secure world 30 * returns busy and another thread just exited and try to complete 31 * someone. 32 */ 33 init_completion(&w->c); 34 list_add_tail(&w->list_node, &cq->waiters); 35 36 mutex_unlock(&cq->mutex); 37 } 38 39 void optee_cq_wait_for_completion(struct optee_call_queue *cq, 40 struct optee_call_waiter *w) 41 { 42 wait_for_completion(&w->c); 43 44 mutex_lock(&cq->mutex); 45 46 /* Move to end of list to get out of the way for other waiters */ 47 list_del(&w->list_node); 48 reinit_completion(&w->c); 49 list_add_tail(&w->list_node, &cq->waiters); 50 51 mutex_unlock(&cq->mutex); 52 } 53 54 static void optee_cq_complete_one(struct optee_call_queue *cq) 55 { 56 struct optee_call_waiter *w; 57 58 list_for_each_entry(w, &cq->waiters, list_node) { 59 if (!completion_done(&w->c)) { 60 complete(&w->c); 61 break; 62 } 63 } 64 } 65 66 void optee_cq_wait_final(struct optee_call_queue *cq, 67 struct optee_call_waiter *w) 68 { 69 /* 70 * We're done with the call to secure world. The thread in secure 71 * world that was used for this call is now available for some 72 * other task to use. 73 */ 74 mutex_lock(&cq->mutex); 75 76 /* Get out of the list */ 77 list_del(&w->list_node); 78 79 /* Wake up one eventual waiting task */ 80 optee_cq_complete_one(cq); 81 82 /* 83 * If we're completed we've got a completion from another task that 84 * was just done with its call to secure world. Since yet another 85 * thread now is available in secure world wake up another eventual 86 * waiting task. 87 */ 88 if (completion_done(&w->c)) 89 optee_cq_complete_one(cq); 90 91 mutex_unlock(&cq->mutex); 92 } 93 94 /* Requires the filpstate mutex to be held */ 95 static struct optee_session *find_session(struct optee_context_data *ctxdata, 96 u32 session_id) 97 { 98 struct optee_session *sess; 99 100 list_for_each_entry(sess, &ctxdata->sess_list, list_node) 101 if (sess->session_id == session_id) 102 return sess; 103 104 return NULL; 105 } 106 107 struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params, 108 struct optee_msg_arg **msg_arg) 109 { 110 struct optee *optee = tee_get_drvdata(ctx->teedev); 111 size_t sz = OPTEE_MSG_GET_ARG_SIZE(num_params); 112 struct tee_shm *shm; 113 struct optee_msg_arg *ma; 114 115 /* 116 * rpc_arg_count is set to the number of allocated parameters in 117 * the RPC argument struct if a second MSG arg struct is expected. 118 * The second arg struct will then be used for RPC. 119 */ 120 if (optee->rpc_arg_count) 121 sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count); 122 123 shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV); 124 if (IS_ERR(shm)) 125 return shm; 126 127 ma = tee_shm_get_va(shm, 0); 128 if (IS_ERR(ma)) { 129 tee_shm_free(shm); 130 return (void *)ma; 131 } 132 133 memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); 134 ma->num_params = num_params; 135 *msg_arg = ma; 136 137 return shm; 138 } 139 140 int optee_open_session(struct tee_context *ctx, 141 struct tee_ioctl_open_session_arg *arg, 142 struct tee_param *param) 143 { 144 struct optee *optee = tee_get_drvdata(ctx->teedev); 145 struct optee_context_data *ctxdata = ctx->data; 146 int rc; 147 struct tee_shm *shm; 148 struct optee_msg_arg *msg_arg; 149 struct optee_session *sess = NULL; 150 uuid_t client_uuid; 151 152 /* +2 for the meta parameters added below */ 153 shm = optee_get_msg_arg(ctx, arg->num_params + 2, &msg_arg); 154 if (IS_ERR(shm)) 155 return PTR_ERR(shm); 156 157 msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION; 158 msg_arg->cancel_id = arg->cancel_id; 159 160 /* 161 * Initialize and add the meta parameters needed when opening a 162 * session. 163 */ 164 msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 165 OPTEE_MSG_ATTR_META; 166 msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | 167 OPTEE_MSG_ATTR_META; 168 memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); 169 msg_arg->params[1].u.value.c = arg->clnt_login; 170 171 rc = tee_session_calc_client_uuid(&client_uuid, arg->clnt_login, 172 arg->clnt_uuid); 173 if (rc) 174 goto out; 175 export_uuid(msg_arg->params[1].u.octets, &client_uuid); 176 177 rc = optee->ops->to_msg_param(optee, msg_arg->params + 2, 178 arg->num_params, param); 179 if (rc) 180 goto out; 181 182 sess = kzalloc(sizeof(*sess), GFP_KERNEL); 183 if (!sess) { 184 rc = -ENOMEM; 185 goto out; 186 } 187 188 if (optee->ops->do_call_with_arg(ctx, shm)) { 189 msg_arg->ret = TEEC_ERROR_COMMUNICATION; 190 msg_arg->ret_origin = TEEC_ORIGIN_COMMS; 191 } 192 193 if (msg_arg->ret == TEEC_SUCCESS) { 194 /* A new session has been created, add it to the list. */ 195 sess->session_id = msg_arg->session; 196 mutex_lock(&ctxdata->mutex); 197 list_add(&sess->list_node, &ctxdata->sess_list); 198 mutex_unlock(&ctxdata->mutex); 199 } else { 200 kfree(sess); 201 } 202 203 if (optee->ops->from_msg_param(optee, param, arg->num_params, 204 msg_arg->params + 2)) { 205 arg->ret = TEEC_ERROR_COMMUNICATION; 206 arg->ret_origin = TEEC_ORIGIN_COMMS; 207 /* Close session again to avoid leakage */ 208 optee_close_session(ctx, msg_arg->session); 209 } else { 210 arg->session = msg_arg->session; 211 arg->ret = msg_arg->ret; 212 arg->ret_origin = msg_arg->ret_origin; 213 } 214 out: 215 tee_shm_free(shm); 216 217 return rc; 218 } 219 220 int optee_close_session_helper(struct tee_context *ctx, u32 session) 221 { 222 struct tee_shm *shm; 223 struct optee *optee = tee_get_drvdata(ctx->teedev); 224 struct optee_msg_arg *msg_arg; 225 226 shm = optee_get_msg_arg(ctx, 0, &msg_arg); 227 if (IS_ERR(shm)) 228 return PTR_ERR(shm); 229 230 msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION; 231 msg_arg->session = session; 232 optee->ops->do_call_with_arg(ctx, shm); 233 234 tee_shm_free(shm); 235 236 return 0; 237 } 238 239 int optee_close_session(struct tee_context *ctx, u32 session) 240 { 241 struct optee_context_data *ctxdata = ctx->data; 242 struct optee_session *sess; 243 244 /* Check that the session is valid and remove it from the list */ 245 mutex_lock(&ctxdata->mutex); 246 sess = find_session(ctxdata, session); 247 if (sess) 248 list_del(&sess->list_node); 249 mutex_unlock(&ctxdata->mutex); 250 if (!sess) 251 return -EINVAL; 252 kfree(sess); 253 254 return optee_close_session_helper(ctx, session); 255 } 256 257 int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, 258 struct tee_param *param) 259 { 260 struct optee *optee = tee_get_drvdata(ctx->teedev); 261 struct optee_context_data *ctxdata = ctx->data; 262 struct tee_shm *shm; 263 struct optee_msg_arg *msg_arg; 264 struct optee_session *sess; 265 int rc; 266 267 /* Check that the session is valid */ 268 mutex_lock(&ctxdata->mutex); 269 sess = find_session(ctxdata, arg->session); 270 mutex_unlock(&ctxdata->mutex); 271 if (!sess) 272 return -EINVAL; 273 274 shm = optee_get_msg_arg(ctx, arg->num_params, &msg_arg); 275 if (IS_ERR(shm)) 276 return PTR_ERR(shm); 277 msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND; 278 msg_arg->func = arg->func; 279 msg_arg->session = arg->session; 280 msg_arg->cancel_id = arg->cancel_id; 281 282 rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params, 283 param); 284 if (rc) 285 goto out; 286 287 if (optee->ops->do_call_with_arg(ctx, shm)) { 288 msg_arg->ret = TEEC_ERROR_COMMUNICATION; 289 msg_arg->ret_origin = TEEC_ORIGIN_COMMS; 290 } 291 292 if (optee->ops->from_msg_param(optee, param, arg->num_params, 293 msg_arg->params)) { 294 msg_arg->ret = TEEC_ERROR_COMMUNICATION; 295 msg_arg->ret_origin = TEEC_ORIGIN_COMMS; 296 } 297 298 arg->ret = msg_arg->ret; 299 arg->ret_origin = msg_arg->ret_origin; 300 out: 301 tee_shm_free(shm); 302 return rc; 303 } 304 305 int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session) 306 { 307 struct optee *optee = tee_get_drvdata(ctx->teedev); 308 struct optee_context_data *ctxdata = ctx->data; 309 struct tee_shm *shm; 310 struct optee_msg_arg *msg_arg; 311 struct optee_session *sess; 312 313 /* Check that the session is valid */ 314 mutex_lock(&ctxdata->mutex); 315 sess = find_session(ctxdata, session); 316 mutex_unlock(&ctxdata->mutex); 317 if (!sess) 318 return -EINVAL; 319 320 shm = optee_get_msg_arg(ctx, 0, &msg_arg); 321 if (IS_ERR(shm)) 322 return PTR_ERR(shm); 323 324 msg_arg->cmd = OPTEE_MSG_CMD_CANCEL; 325 msg_arg->session = session; 326 msg_arg->cancel_id = cancel_id; 327 optee->ops->do_call_with_arg(ctx, shm); 328 329 tee_shm_free(shm); 330 return 0; 331 } 332 333 static bool is_normal_memory(pgprot_t p) 334 { 335 #if defined(CONFIG_ARM) 336 return (((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC) || 337 ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEBACK)); 338 #elif defined(CONFIG_ARM64) 339 return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); 340 #else 341 #error "Unuspported architecture" 342 #endif 343 } 344 345 static int __check_mem_type(struct vm_area_struct *vma, unsigned long end) 346 { 347 while (vma && is_normal_memory(vma->vm_page_prot)) { 348 if (vma->vm_end >= end) 349 return 0; 350 vma = vma->vm_next; 351 } 352 353 return -EINVAL; 354 } 355 356 int optee_check_mem_type(unsigned long start, size_t num_pages) 357 { 358 struct mm_struct *mm = current->mm; 359 int rc; 360 361 /* 362 * Allow kernel address to register with OP-TEE as kernel 363 * pages are configured as normal memory only. 364 */ 365 if (virt_addr_valid(start)) 366 return 0; 367 368 mmap_read_lock(mm); 369 rc = __check_mem_type(find_vma(mm, start), 370 start + num_pages * PAGE_SIZE); 371 mmap_read_unlock(mm); 372 373 return rc; 374 } 375