Upstream optee-os has recently added a new
TA_AVB_CMD_READ_PERSIST_VALUE2 method, which fixes a problem with the
ABI of the old TA_AVB_CMD_READ_PERSIST_VALUE method: Callers could not
know whether the buffer they supplied was big enough, or whether the
output was silently truncated. With the new method,
TEE_ERROR_SHORT_BUFFER is returned, but with the output size parameter
updated to what would be the correct buffer size.

A new method was added instead of modifying the ABI of the existing
method, as there might be callers that work with a truncated return
value, but which would not be able to cope with an unexpected error
return.

Commit 8800cbe9b83 ("tee: sandbox: check for buffer size") partially
updated the sandbox version of optee-os to have the semantics that the
new method in upstream optee-os now has. It added logic to also return
the actual value size, but only in the success case -
params[1].u.memref.size was left untouched in the "return
TEE_ERROR_SHORT_BUFFER" case.

Align the sandbox implementation with optee-os: Silently return a
truncated value for the old method, but do return
TEE_ERROR_SHORT_BUFFER for the new method while also updating the
output size parameter.

Signed-off-by: Rasmus Villemoes <[email protected]>
---
 drivers/tee/sandbox.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
index 86b16a3bb8d..16e5d95616c 100644
--- a/drivers/tee/sandbox.c
+++ b/drivers/tee/sandbox.c
@@ -248,6 +248,7 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 
func, uint num_params,
 
                return TEE_SUCCESS;
        case TA_AVB_CMD_READ_PERSIST_VALUE:
+       case TA_AVB_CMD_READ_PERSIST_VALUE2:
                res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
                                   TEE_PARAM_ATTR_TYPE_MEMREF_INOUT,
                                   TEE_PARAM_ATTR_TYPE_NONE,
@@ -268,8 +269,23 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 
func, uint num_params,
                        return TEE_ERROR_ITEM_NOT_FOUND;
 
                tmp_sz = strlen(ep->data) + 1;
-               if (value_sz < tmp_sz)
-                       return TEE_ERROR_SHORT_BUFFER;
+               if (value_sz < tmp_sz) {
+                       /*
+                        * For TA_AVB_CMD_READ_PERSIST_VALUE2, reject
+                        * a too short output buffer, but do inform
+                        * the caller of what would be the correct
+                        * size.
+                        */
+                       if (func == TA_AVB_CMD_READ_PERSIST_VALUE2) {
+                               params[1].u.memref.size = tmp_sz;
+                               return TEE_ERROR_SHORT_BUFFER;
+                       }
+                       /*
+                        * For TA_AVB_CMD_READ_PERSIST_VALUE, truncate
+                        * the value to the given size.
+                        */
+                       tmp_sz = value_sz;
+               }
 
                memcpy(value, ep->data, tmp_sz);
                params[1].u.memref.size = tmp_sz;
-- 
2.55.0

Reply via email to