From f4b2209fdf9cdeb5678bd786ea218dfef980f248 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Feb 2022 14:02:54 +0100 Subject: [PATCH] 5.16-stable patches added patches: optee-use-driver-internal-tee_context-for-some-rpc.patch --- ...er-internal-tee_context-for-some-rpc.patch | 302 ++++++++++++++++++ queue-5.16/series | 1 + 2 files changed, 303 insertions(+) create mode 100644 queue-5.16/optee-use-driver-internal-tee_context-for-some-rpc.patch diff --git a/queue-5.16/optee-use-driver-internal-tee_context-for-some-rpc.patch b/queue-5.16/optee-use-driver-internal-tee_context-for-some-rpc.patch new file mode 100644 index 00000000000..06691795317 --- /dev/null +++ b/queue-5.16/optee-use-driver-internal-tee_context-for-some-rpc.patch @@ -0,0 +1,302 @@ +From aceeafefff736057e8f93f19bbfbef26abd94604 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Thu, 27 Jan 2022 15:29:39 +0100 +Subject: optee: use driver internal tee_context for some rpc + +From: Jens Wiklander + +commit aceeafefff736057e8f93f19bbfbef26abd94604 upstream. + +Adds a driver private tee_context by moving the tee_context in struct +optee_notif to struct optee. This tee_context was previously used when +doing internal calls to secure world to deliver notification. + +The new driver internal tee_context is now also when allocating driver +private shared memory. This decouples the shared memory object from its +original tee_context. This is needed when the life time of such a memory +allocation outlives the client tee_context. + +This patch fixes the problem described below: + +The addition of a shutdown hook by commit f25889f93184 ("optee: fix tee out +of memory failure seen during kexec reboot") introduced a kernel shutdown +regression that can be triggered after running the OP-TEE xtest suites. + +Once the shutdown hook is called it is not possible to communicate any more +with the supplicant process because the system is not scheduling task any +longer. Thus if the optee driver shutdown path receives a supplicant RPC +request from the OP-TEE we will deadlock the kernel's shutdown. + +Fixes: f25889f93184 ("optee: fix tee out of memory failure seen during kexec reboot") +Fixes: 217e0250cccb ("tee: use reference counting for tee_context") +Reported-by: Lars Persson +Cc: stable@vger.kernel.org +Reviewed-by: Sumit Garg +[JW: backport to 5.16-stable + update commit message] +Signed-off-by: Jens Wiklander +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tee/optee/core.c | 1 + drivers/tee/optee/ffa_abi.c | 70 +++++++++++++++++++++----------------- + drivers/tee/optee/optee_private.h | 4 +- + drivers/tee/optee/smc_abi.c | 13 +++++-- + 4 files changed, 54 insertions(+), 34 deletions(-) + +--- a/drivers/tee/optee/core.c ++++ b/drivers/tee/optee/core.c +@@ -157,6 +157,7 @@ void optee_remove_common(struct optee *o + /* Unregister OP-TEE specific client devices on TEE bus */ + optee_unregister_devices(); + ++ teedev_close_context(optee->ctx); + /* + * The two devices have to be unregistered before we can free the + * other resources. +--- a/drivers/tee/optee/ffa_abi.c ++++ b/drivers/tee/optee/ffa_abi.c +@@ -424,6 +424,7 @@ static struct tee_shm_pool_mgr *optee_ff + */ + + static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx, ++ struct optee *optee, + struct optee_msg_arg *arg) + { + struct tee_shm *shm; +@@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_ + shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: +- shm = tee_shm_alloc(ctx, arg->params[0].u.value.b, ++ shm = tee_shm_alloc(optee->ctx, arg->params[0].u.value.b, + TEE_SHM_MAPPED | TEE_SHM_PRIV); + break; + default: +@@ -493,14 +494,13 @@ err_bad_param: + } + + static void handle_ffa_rpc_func_cmd(struct tee_context *ctx, ++ struct optee *optee, + struct optee_msg_arg *arg) + { +- struct optee *optee = tee_get_drvdata(ctx->teedev); +- + arg->ret_origin = TEEC_ORIGIN_COMMS; + switch (arg->cmd) { + case OPTEE_RPC_CMD_SHM_ALLOC: +- handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg); ++ handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg); + break; + case OPTEE_RPC_CMD_SHM_FREE: + handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg); +@@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(stru + } + } + +-static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd, +- struct optee_msg_arg *arg) ++static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee, ++ u32 cmd, struct optee_msg_arg *arg) + { + switch (cmd) { + case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD: +- handle_ffa_rpc_func_cmd(ctx, arg); ++ handle_ffa_rpc_func_cmd(ctx, optee, arg); + break; + case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT: + /* Interrupt delivered by now */ +@@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struc + * above. + */ + cond_resched(); +- optee_handle_ffa_rpc(ctx, data->data1, rpc_arg); ++ optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg); + cmd = OPTEE_FFA_YIELDING_CALL_RESUME; + data->data0 = cmd; + data->data1 = 0; +@@ -802,7 +802,9 @@ static int optee_ffa_probe(struct ffa_de + { + const struct ffa_dev_ops *ffa_ops; + unsigned int rpc_arg_count; ++ struct tee_shm_pool *pool; + struct tee_device *teedev; ++ struct tee_context *ctx; + struct optee *optee; + int rc; + +@@ -822,12 +824,12 @@ static int optee_ffa_probe(struct ffa_de + if (!optee) + return -ENOMEM; + +- optee->pool = optee_ffa_config_dyn_shm(); +- if (IS_ERR(optee->pool)) { +- rc = PTR_ERR(optee->pool); +- optee->pool = NULL; +- goto err; ++ pool = optee_ffa_config_dyn_shm(); ++ if (IS_ERR(pool)) { ++ rc = PTR_ERR(pool); ++ goto err_free_optee; + } ++ optee->pool = pool; + + optee->ops = &optee_ffa_ops; + optee->ffa.ffa_dev = ffa_dev; +@@ -838,7 +840,7 @@ static int optee_ffa_probe(struct ffa_de + optee); + if (IS_ERR(teedev)) { + rc = PTR_ERR(teedev); +- goto err; ++ goto err_free_pool; + } + optee->teedev = teedev; + +@@ -846,46 +848,54 @@ static int optee_ffa_probe(struct ffa_de + optee); + if (IS_ERR(teedev)) { + rc = PTR_ERR(teedev); +- goto err; ++ goto err_unreg_teedev; + } + optee->supp_teedev = teedev; + + rc = tee_device_register(optee->teedev); + if (rc) +- goto err; ++ goto err_unreg_supp_teedev; + + rc = tee_device_register(optee->supp_teedev); + if (rc) +- goto err; ++ goto err_unreg_supp_teedev; + + rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params); + if (rc) +- goto err; ++ goto err_unreg_supp_teedev; + mutex_init(&optee->ffa.mutex); + mutex_init(&optee->call_queue.mutex); + INIT_LIST_HEAD(&optee->call_queue.waiters); + optee_wait_queue_init(&optee->wait_queue); + optee_supp_init(&optee->supp); + ffa_dev_set_drvdata(ffa_dev, optee); ++ ctx = teedev_open(optee->teedev); ++ if (IS_ERR(ctx)) ++ goto err_rhashtable_free; ++ optee->ctx = ctx; ++ + + rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES); +- if (rc) { +- optee_ffa_remove(ffa_dev); +- return rc; +- } ++ if (rc) ++ goto err_unregister_devices; + + pr_info("initialized driver\n"); + return 0; +-err: +- /* +- * tee_device_unregister() is safe to call even if the +- * devices hasn't been registered with +- * tee_device_register() yet. +- */ ++ ++err_unregister_devices: ++ optee_unregister_devices(); ++ teedev_close_context(ctx); ++err_rhashtable_free: ++ rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL); ++ optee_supp_uninit(&optee->supp); ++ mutex_destroy(&optee->call_queue.mutex); ++err_unreg_supp_teedev: + tee_device_unregister(optee->supp_teedev); ++err_unreg_teedev: + tee_device_unregister(optee->teedev); +- if (optee->pool) +- tee_shm_pool_free(optee->pool); ++err_free_pool: ++ tee_shm_pool_free(pool); ++err_free_optee: + kfree(optee); + return rc; + } +--- a/drivers/tee/optee/optee_private.h ++++ b/drivers/tee/optee/optee_private.h +@@ -123,9 +123,10 @@ struct optee_ops { + /** + * struct optee - main service struct + * @supp_teedev: supplicant device ++ * @teedev: client device + * @ops: internal callbacks for different ways to reach secure + * world +- * @teedev: client device ++ * @ctx: driver internal TEE context + * @smc: specific to SMC ABI + * @ffa: specific to FF-A ABI + * @call_queue: queue of threads waiting to call @invoke_fn +@@ -142,6 +143,7 @@ struct optee { + struct tee_device *supp_teedev; + struct tee_device *teedev; + const struct optee_ops *ops; ++ struct tee_context *ctx; + union { + struct optee_smc smc; + struct optee_ffa ffa; +--- a/drivers/tee/optee/smc_abi.c ++++ b/drivers/tee/optee/smc_abi.c +@@ -608,6 +608,7 @@ static void handle_rpc_func_cmd_shm_free + } + + static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, ++ struct optee *optee, + struct optee_msg_arg *arg, + struct optee_call_ctx *call_ctx) + { +@@ -637,7 +638,8 @@ static void handle_rpc_func_cmd_shm_allo + shm = optee_rpc_cmd_alloc_suppl(ctx, sz); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: +- shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV); ++ shm = tee_shm_alloc(optee->ctx, sz, ++ TEE_SHM_MAPPED | TEE_SHM_PRIV); + break; + default: + arg->ret = TEEC_ERROR_BAD_PARAMETERS; +@@ -733,7 +735,7 @@ static void handle_rpc_func_cmd(struct t + switch (arg->cmd) { + case OPTEE_RPC_CMD_SHM_ALLOC: + free_pages_list(call_ctx); +- handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); ++ handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx); + break; + case OPTEE_RPC_CMD_SHM_FREE: + handle_rpc_func_cmd_shm_free(ctx, arg); +@@ -762,7 +764,7 @@ static void optee_handle_rpc(struct tee_ + + switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { + case OPTEE_SMC_RPC_FUNC_ALLOC: +- shm = tee_shm_alloc(ctx, param->a1, ++ shm = tee_shm_alloc(optee->ctx, param->a1, + TEE_SHM_MAPPED | TEE_SHM_PRIV); + if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) { + reg_pair_from_64(¶m->a1, ¶m->a2, pa); +@@ -1207,6 +1209,7 @@ static int optee_probe(struct platform_d + struct optee *optee = NULL; + void *memremaped_shm = NULL; + struct tee_device *teedev; ++ struct tee_context *ctx; + u32 sec_caps; + int rc; + +@@ -1284,6 +1287,10 @@ static int optee_probe(struct platform_d + optee_supp_init(&optee->supp); + optee->smc.memremaped_shm = memremaped_shm; + optee->pool = pool; ++ ctx = teedev_open(optee->teedev); ++ if (IS_ERR(ctx)) ++ goto err; ++ optee->ctx = ctx; + + /* + * Ensure that there are no pre-existing shm objects before enabling diff --git a/queue-5.16/series b/queue-5.16/series index b543ca54dbc..83900242cf2 100644 --- a/queue-5.16/series +++ b/queue-5.16/series @@ -84,3 +84,4 @@ drm-i915-opregion-check-port-number-bounds-for-swsci-display-power-state.patch drm-i915-fix-dbuf-slice-config-lookup.patch drm-i915-fix-mbus-join-config-lookup.patch vsock-remove-vsock-from-connected-table-when-connect-is-interrupted-by-a-signal.patch +optee-use-driver-internal-tee_context-for-some-rpc.patch -- 2.47.3