Skip to content

Commit aceeafe

Browse files
committed
optee: use driver internal tee_context for some rpc
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 f25889f ("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: f25889f ("optee: fix tee out of memory failure seen during kexec reboot") Fixes: 217e025 ("tee: use reference counting for tee_context") Reported-by: Lars Persson <[email protected]> Cc: [email protected] Reviewed-by: Sumit Garg <[email protected]> Signed-off-by: Jens Wiklander <[email protected]>
1 parent 26291c5 commit aceeafe

File tree

4 files changed

+64
-67
lines changed

4 files changed

+64
-67
lines changed

drivers/tee/optee/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ void optee_remove_common(struct optee *optee)
158158
optee_unregister_devices();
159159

160160
optee_notif_uninit(optee);
161+
teedev_close_context(optee->ctx);
161162
/*
162163
* The two devices have to be unregistered before we can free the
163164
* other resources.

drivers/tee/optee/ffa_abi.c

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ static struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void)
424424
*/
425425

426426
static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
427+
struct optee *optee,
427428
struct optee_msg_arg *arg)
428429
{
429430
struct tee_shm *shm;
@@ -439,7 +440,7 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
439440
shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
440441
break;
441442
case OPTEE_RPC_SHM_TYPE_KERNEL:
442-
shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
443+
shm = tee_shm_alloc(optee->ctx, arg->params[0].u.value.b,
443444
TEE_SHM_MAPPED | TEE_SHM_PRIV);
444445
break;
445446
default:
@@ -493,14 +494,13 @@ static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
493494
}
494495

495496
static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
497+
struct optee *optee,
496498
struct optee_msg_arg *arg)
497499
{
498-
struct optee *optee = tee_get_drvdata(ctx->teedev);
499-
500500
arg->ret_origin = TEEC_ORIGIN_COMMS;
501501
switch (arg->cmd) {
502502
case OPTEE_RPC_CMD_SHM_ALLOC:
503-
handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
503+
handle_ffa_rpc_func_cmd_shm_alloc(ctx, optee, arg);
504504
break;
505505
case OPTEE_RPC_CMD_SHM_FREE:
506506
handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
@@ -510,12 +510,12 @@ static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
510510
}
511511
}
512512

513-
static void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
514-
struct optee_msg_arg *arg)
513+
static void optee_handle_ffa_rpc(struct tee_context *ctx, struct optee *optee,
514+
u32 cmd, struct optee_msg_arg *arg)
515515
{
516516
switch (cmd) {
517517
case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
518-
handle_ffa_rpc_func_cmd(ctx, arg);
518+
handle_ffa_rpc_func_cmd(ctx, optee, arg);
519519
break;
520520
case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
521521
/* Interrupt delivered by now */
@@ -582,7 +582,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
582582
* above.
583583
*/
584584
cond_resched();
585-
optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
585+
optee_handle_ffa_rpc(ctx, optee, data->data1, rpc_arg);
586586
cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
587587
data->data0 = cmd;
588588
data->data1 = 0;
@@ -793,7 +793,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
793793
{
794794
const struct ffa_dev_ops *ffa_ops;
795795
unsigned int rpc_arg_count;
796+
struct tee_shm_pool *pool;
796797
struct tee_device *teedev;
798+
struct tee_context *ctx;
797799
struct optee *optee;
798800
int rc;
799801

@@ -813,12 +815,12 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
813815
if (!optee)
814816
return -ENOMEM;
815817

816-
optee->pool = optee_ffa_config_dyn_shm();
817-
if (IS_ERR(optee->pool)) {
818-
rc = PTR_ERR(optee->pool);
819-
optee->pool = NULL;
820-
goto err;
818+
pool = optee_ffa_config_dyn_shm();
819+
if (IS_ERR(pool)) {
820+
rc = PTR_ERR(pool);
821+
goto err_free_optee;
821822
}
823+
optee->pool = pool;
822824

823825
optee->ops = &optee_ffa_ops;
824826
optee->ffa.ffa_dev = ffa_dev;
@@ -829,58 +831,65 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
829831
optee);
830832
if (IS_ERR(teedev)) {
831833
rc = PTR_ERR(teedev);
832-
goto err;
834+
goto err_free_pool;
833835
}
834836
optee->teedev = teedev;
835837

836838
teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
837839
optee);
838840
if (IS_ERR(teedev)) {
839841
rc = PTR_ERR(teedev);
840-
goto err;
842+
goto err_unreg_teedev;
841843
}
842844
optee->supp_teedev = teedev;
843845

844846
rc = tee_device_register(optee->teedev);
845847
if (rc)
846-
goto err;
848+
goto err_unreg_supp_teedev;
847849

848850
rc = tee_device_register(optee->supp_teedev);
849851
if (rc)
850-
goto err;
852+
goto err_unreg_supp_teedev;
851853

852854
rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
853855
if (rc)
854-
goto err;
856+
goto err_unreg_supp_teedev;
855857
mutex_init(&optee->ffa.mutex);
856858
mutex_init(&optee->call_queue.mutex);
857859
INIT_LIST_HEAD(&optee->call_queue.waiters);
858860
optee_supp_init(&optee->supp);
859861
ffa_dev_set_drvdata(ffa_dev, optee);
862+
ctx = teedev_open(optee->teedev);
863+
if (IS_ERR(ctx))
864+
goto err_rhashtable_free;
865+
optee->ctx = ctx;
860866
rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
861-
if (rc) {
862-
optee_ffa_remove(ffa_dev);
863-
return rc;
864-
}
867+
if (rc)
868+
goto err_close_ctx;
865869

866870
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
867-
if (rc) {
868-
optee_ffa_remove(ffa_dev);
869-
return rc;
870-
}
871+
if (rc)
872+
goto err_unregister_devices;
871873

872874
pr_info("initialized driver\n");
873875
return 0;
874-
err:
875-
/*
876-
* tee_device_unregister() is safe to call even if the
877-
* devices hasn't been registered with
878-
* tee_device_register() yet.
879-
*/
876+
877+
err_unregister_devices:
878+
optee_unregister_devices();
879+
optee_notif_uninit(optee);
880+
err_close_ctx:
881+
teedev_close_context(ctx);
882+
err_rhashtable_free:
883+
rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
884+
optee_supp_uninit(&optee->supp);
885+
mutex_destroy(&optee->call_queue.mutex);
886+
err_unreg_supp_teedev:
880887
tee_device_unregister(optee->supp_teedev);
888+
err_unreg_teedev:
881889
tee_device_unregister(optee->teedev);
882-
if (optee->pool)
883-
tee_shm_pool_free(optee->pool);
890+
err_free_pool:
891+
tee_shm_pool_free(pool);
892+
err_free_optee:
884893
kfree(optee);
885894
return rc;
886895
}

drivers/tee/optee/optee_private.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ struct optee_call_queue {
5353

5454
struct optee_notif {
5555
u_int max_key;
56-
struct tee_context *ctx;
5756
/* Serializes access to the elements below in this struct */
5857
spinlock_t lock;
5958
struct list_head db;
@@ -134,9 +133,10 @@ struct optee_ops {
134133
/**
135134
* struct optee - main service struct
136135
* @supp_teedev: supplicant device
136+
* @teedev: client device
137137
* @ops: internal callbacks for different ways to reach secure
138138
* world
139-
* @teedev: client device
139+
* @ctx: driver internal TEE context
140140
* @smc: specific to SMC ABI
141141
* @ffa: specific to FF-A ABI
142142
* @call_queue: queue of threads waiting to call @invoke_fn
@@ -152,6 +152,7 @@ struct optee {
152152
struct tee_device *supp_teedev;
153153
struct tee_device *teedev;
154154
const struct optee_ops *ops;
155+
struct tee_context *ctx;
155156
union {
156157
struct optee_smc smc;
157158
struct optee_ffa ffa;

drivers/tee/optee/smc_abi.c

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
622622
}
623623

624624
static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
625+
struct optee *optee,
625626
struct optee_msg_arg *arg,
626627
struct optee_call_ctx *call_ctx)
627628
{
@@ -651,7 +652,8 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
651652
shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
652653
break;
653654
case OPTEE_RPC_SHM_TYPE_KERNEL:
654-
shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
655+
shm = tee_shm_alloc(optee->ctx, sz,
656+
TEE_SHM_MAPPED | TEE_SHM_PRIV);
655657
break;
656658
default:
657659
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -747,7 +749,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
747749
switch (arg->cmd) {
748750
case OPTEE_RPC_CMD_SHM_ALLOC:
749751
free_pages_list(call_ctx);
750-
handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
752+
handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
751753
break;
752754
case OPTEE_RPC_CMD_SHM_FREE:
753755
handle_rpc_func_cmd_shm_free(ctx, arg);
@@ -776,7 +778,7 @@ static void optee_handle_rpc(struct tee_context *ctx,
776778

777779
switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
778780
case OPTEE_SMC_RPC_FUNC_ALLOC:
779-
shm = tee_shm_alloc(ctx, param->a1,
781+
shm = tee_shm_alloc(optee->ctx, param->a1,
780782
TEE_SHM_MAPPED | TEE_SHM_PRIV);
781783
if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
782784
reg_pair_from_64(&param->a1, &param->a2, pa);
@@ -954,57 +956,34 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
954956
{
955957
struct optee *optee = dev_id;
956958

957-
optee_smc_do_bottom_half(optee->notif.ctx);
959+
optee_smc_do_bottom_half(optee->ctx);
958960

959961
return IRQ_HANDLED;
960962
}
961963

962964
static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
963965
{
964-
struct tee_context *ctx;
965966
int rc;
966967

967-
ctx = teedev_open(optee->teedev);
968-
if (IS_ERR(ctx))
969-
return PTR_ERR(ctx);
970-
971-
optee->notif.ctx = ctx;
972968
rc = request_threaded_irq(irq, notif_irq_handler,
973969
notif_irq_thread_fn,
974970
0, "optee_notification", optee);
975971
if (rc)
976-
goto err_close_ctx;
972+
return rc;
977973

978974
optee->smc.notif_irq = irq;
979975

980976
return 0;
981-
982-
err_close_ctx:
983-
teedev_close_context(optee->notif.ctx);
984-
optee->notif.ctx = NULL;
985-
986-
return rc;
987977
}
988978

989979
static void optee_smc_notif_uninit_irq(struct optee *optee)
990980
{
991-
if (optee->notif.ctx) {
992-
optee_smc_stop_async_notif(optee->notif.ctx);
981+
if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
982+
optee_smc_stop_async_notif(optee->ctx);
993983
if (optee->smc.notif_irq) {
994984
free_irq(optee->smc.notif_irq, optee);
995985
irq_dispose_mapping(optee->smc.notif_irq);
996986
}
997-
998-
/*
999-
* The thread normally working with optee->notif.ctx was
1000-
* stopped with free_irq() above.
1001-
*
1002-
* Note we're not using teedev_close_context() or
1003-
* tee_client_close_context() since we have already called
1004-
* tee_device_put() while initializing to avoid a circular
1005-
* reference counting.
1006-
*/
1007-
teedev_close_context(optee->notif.ctx);
1008987
}
1009988
}
1010989

@@ -1366,6 +1345,7 @@ static int optee_probe(struct platform_device *pdev)
13661345
struct optee *optee = NULL;
13671346
void *memremaped_shm = NULL;
13681347
struct tee_device *teedev;
1348+
struct tee_context *ctx;
13691349
u32 max_notif_value;
13701350
u32 sec_caps;
13711351
int rc;
@@ -1446,9 +1426,13 @@ static int optee_probe(struct platform_device *pdev)
14461426
optee->pool = pool;
14471427

14481428
platform_set_drvdata(pdev, optee);
1429+
ctx = teedev_open(optee->teedev);
1430+
if (IS_ERR(ctx))
1431+
goto err_supp_uninit;
1432+
optee->ctx = ctx;
14491433
rc = optee_notif_init(optee, max_notif_value);
14501434
if (rc)
1451-
goto err_supp_uninit;
1435+
goto err_close_ctx;
14521436

14531437
if (sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
14541438
unsigned int irq;
@@ -1496,6 +1480,8 @@ static int optee_probe(struct platform_device *pdev)
14961480
optee_unregister_devices();
14971481
err_notif_uninit:
14981482
optee_notif_uninit(optee);
1483+
err_close_ctx:
1484+
teedev_close_context(ctx);
14991485
err_supp_uninit:
15001486
optee_supp_uninit(&optee->supp);
15011487
mutex_destroy(&optee->call_queue.mutex);

0 commit comments

Comments
 (0)