]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Feb 2022 13:02:54 +0000 (14:02 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 18 Feb 2022 13:02:54 +0000 (14:02 +0100)
added patches:
optee-use-driver-internal-tee_context-for-some-rpc.patch

queue-5.16/optee-use-driver-internal-tee_context-for-some-rpc.patch [new file with mode: 0644]
queue-5.16/series

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 (file)
index 0000000..0669179
--- /dev/null
@@ -0,0 +1,302 @@
+From aceeafefff736057e8f93f19bbfbef26abd94604 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 27 Jan 2022 15:29:39 +0100
+Subject: optee: use driver internal tee_context for some rpc
+
+From: Jens Wiklander <jens.wiklander@linaro.org>
+
+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 <larper@axis.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
+[JW: backport to 5.16-stable + update commit message]
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(&param->a1, &param->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
index b543ca54dbc207498c0170e1221fa8f4980af949..83900242cf2f0f1cd4b3cb4a2cceee5184065ce5 100644 (file)
@@ -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