tee: optee: interrupt an RPC when supplicant has been killed

check supplicant is dead or alive when get signal,
run normal program if supplicant is alive,
interrupting an RPC if supplicant is dead, Otherwise,
the current thread will be stuck in the optee driver.
The error is printed as follows:

INFO: task gatekeeper@1.0-:461 blocked for more than 20 seconds.
Not tainted 5.10.66 #2
task:gatekeeper@1.0- state:D stack: 0 pid: 461 ppid: 1 flags:0x0400002d
Call trace:
switch_to+0x180/0x230
__schedule+0x49c/0x704
schedule+0xa0/0xe8
schedule_timeout+0x38/0x124
wait_for_common+0xa4/0x134
wait_for_completion+0x1c/0x2c
optee_handle_rpc+0x1a4/0x6ec
optee_do_call_with_arg+0x1a4/0x298
optee_release+0x134/0x1bc
tee_release+0xa4/0x100

Change-Id: I2f82338ecccc1bc97bb5a6c25767eca4542cbcdf
Signed-off-by: Hisping Lin <hisping.lin@rock-chips.com>
This commit is contained in:
Hisping Lin
2023-02-28 10:17:52 +08:00
committed by Tao Huang
parent 2c94291de8
commit e6c7ea7d4d

View File

@@ -82,6 +82,9 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
struct optee_supp_req *req;
bool interruptable;
u32 ret;
unsigned long timeleft;
int id;
struct optee_supp_req *get_req;
/*
* Return in case there is no supplicant available and
@@ -114,8 +117,17 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
* exclusive access again.
*/
while (wait_for_completion_interruptible(&req->c)) {
pr_err("Warning, Interrupting an RPC to supplicant!\n");
timeleft = wait_for_completion_timeout(&req->c, msecs_to_jiffies(2000));
if (timeleft) {
/* get completion, it means tee-supplicant is alive. */
break;
} else {
/* timeout, it means tee-supplicant is dead, interrupting an RPC. */
interruptable = true;
}
mutex_lock(&supp->mutex);
interruptable = !supp->ctx;
if (interruptable) {
/*
* There's no supplicant available and since the
@@ -134,6 +146,14 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
list_del(&req->link);
req->in_queue = false;
}
idr_for_each_entry(&supp->idr, get_req, id) {
if (get_req == req) {
idr_remove(&supp->idr, id);
supp->req_id = -1;
break;
}
}
}
mutex_unlock(&supp->mutex);