Jerome Forissier | 8b80891 | 2022-05-04 00:12:28 +0200 | [diff] [blame] | 1 | From e6059b14107cc061cc35fad44afdd9ad25ba1181 Mon Sep 17 00:00:00 2001 |
| 2 | From: Jens Wiklander <jens.wiklander@linaro.org> |
| 3 | Date: Thu, 28 Apr 2022 09:07:41 +0200 |
| 4 | Subject: [PATCH] optee: immediately free RPC buffers that are released by |
| 5 | OP-TEE |
| 6 | |
| 7 | This commit fixes a case overlooked in [1]. |
| 8 | |
| 9 | There are two kinds of shared memory buffers used by OP-TEE: |
| 10 | 1. Normal payload buffer |
| 11 | 2. Internal command structure buffers |
| 12 | |
| 13 | The internal command structure buffers are represented with a shadow |
| 14 | copy internally in Xen since this buffer can contain physical addresses |
| 15 | that may need to be translated between real physical address and guest |
| 16 | physical address without leaking information to the guest. |
| 17 | |
| 18 | [1] fixes the problem when releasing the normal payload buffers. The |
| 19 | internal command structure buffers must be released in the same way. |
| 20 | Failure to follow this order opens a window where the guest has freed |
| 21 | the shared memory but Xen is still tracking the buffer. |
| 22 | |
| 23 | During this window the guest may happen to recycle this particular |
| 24 | shared memory in some other thread and try to use it. Xen will block |
| 25 | this which will lead to spurious failures to register a new shared |
| 26 | memory block. |
| 27 | |
| 28 | Fix this by freeing the internal command structure buffers first before |
| 29 | informing the guest that the buffer can be freed. |
| 30 | |
| 31 | [1] 5b13eb1d978e ("optee: immediately free buffers that are released by OP-TEE") |
| 32 | |
| 33 | Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> |
| 34 | --- |
| 35 | xen/arch/arm/tee/optee.c | 13 ++++++------- |
| 36 | 1 file changed, 6 insertions(+), 7 deletions(-) |
| 37 | |
| 38 | diff --git a/xen/arch/arm/tee/optee.c b/xen/arch/arm/tee/optee.c |
| 39 | index 8a39fe33b0ef..f6d2d689ab60 100644 |
| 40 | --- a/xen/arch/arm/tee/optee.c |
| 41 | +++ b/xen/arch/arm/tee/optee.c |
| 42 | @@ -1149,8 +1149,14 @@ static int handle_rpc_return(struct optee_domain *ctx, |
| 43 | call->rpc_data_cookie = 0; |
| 44 | } |
| 45 | unmap_domain_page(shm_rpc->xen_arg); |
| 46 | + } else if (call->rpc_op == OPTEE_SMC_RPC_FUNC_FREE) { |
| 47 | + uint64_t cookie = regpair_to_uint64(get_user_reg(regs, 1), |
| 48 | + get_user_reg(regs, 2)); |
| 49 | + |
| 50 | + free_shm_rpc(ctx, cookie); |
| 51 | } |
| 52 | |
| 53 | + |
| 54 | return ret; |
| 55 | } |
| 56 | |
| 57 | @@ -1598,13 +1604,6 @@ static void handle_rpc(struct optee_domain *ctx, struct cpu_user_regs *regs) |
| 58 | case OPTEE_SMC_RPC_FUNC_ALLOC: |
| 59 | handle_rpc_func_alloc(ctx, regs, call); |
| 60 | return; |
| 61 | - case OPTEE_SMC_RPC_FUNC_FREE: |
| 62 | - { |
| 63 | - uint64_t cookie = regpair_to_uint64(call->rpc_params[0], |
| 64 | - call->rpc_params[1]); |
| 65 | - free_shm_rpc(ctx, cookie); |
| 66 | - break; |
| 67 | - } |
| 68 | case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR: |
| 69 | break; |
| 70 | case OPTEE_SMC_RPC_FUNC_CMD: |