drivers/misc/optee: Fix non-registered memory ref passing

So far the NuttX implementation of OP-TEE has been using
registered memory references to pass non-registered memory
to OP-TEE OS, passing the physical address of the memory
in what is normally used as a 'cookie'. This was compatible
with the Openvela framework, but no other OP-TEE OS.

Fix this by passing temporary memory instead with the standard
non-contiguous (OPTEE_MSG_ATTR_NONCONTIG) flag.

Signed-off-by: George Poulios <gpoulios@census-labs.com>
This commit is contained in:
George Poulios
2025-05-10 21:39:54 +03:00
committed by Xiang Xiao
parent 6f77cb6dce
commit 47064e42df
2 changed files with 54 additions and 33 deletions
+53 -33
View File
@@ -562,48 +562,53 @@ static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
FAR const struct tee_ioctl_param *p)
{
FAR struct optee_shm *shm;
uintptr_t page_list_pa;
/* Warning: the case for non-registered memrefs below is a hack to work
* with openvela. Normally, non-registered memory should be specified as
* OPTEE_MSG_ATTR_TYPE_TMEM_* (note the 'T') and `buf_ptr` should be set
* to the physical address of buffer.
*
* Related openvela patches:
* - external_optee_optee_os@1a29df42 core/tee/entry_std.c#L160
* - frameworks_security_optee_vela@54b377d5c compat/mobj_dyn_shm.c#L25
*
* Ideally, in the future, this should be wrapped around some
* CONFIG_OPTEE_OPENVELA_COMPAT guard.
*/
mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
if (p->c != TEE_MEMREF_NULL)
if (p->c == TEE_MEMREF_NULL)
{
shm = idr_find(priv->shms, p->c);
if (shm == NULL)
{
return -EINVAL;
}
mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
mp->u.tmem.buf_ptr = 0;
mp->u.tmem.shm_ref = 0;
mp->u.tmem.size = p->b;
return 0;
}
if (shm->flags & TEE_SHM_REGISTER)
{
mp->u.rmem.shm_ref = (uintptr_t)shm;
}
else
{
/* hack to comply with openvela */
shm = idr_find(priv->shms, p->c);
if (shm == NULL)
{
return -EINVAL;
}
mp->u.rmem.shm_ref = shm->addr;
}
if (shm->flags & TEE_SHM_REGISTER)
{
/* registered memory */
mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
mp->u.rmem.offs = p->a;
mp->u.rmem.size = p->b;
mp->u.rmem.shm_ref = (uintptr_t)shm;
}
else
{
mp->u.rmem.shm_ref = 0;
/* non-registered memory (temporary) */
mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
mp->attr |= OPTEE_MSG_ATTR_NONCONTIG;
shm->page_list = optee_shm_to_page_list(shm, &page_list_pa);
if (shm->page_list == NULL)
{
return -ENOMEM;
}
mp->u.tmem.buf_ptr = page_list_pa;
mp->u.tmem.shm_ref = (uintptr_t)shm;
mp->u.tmem.size = shm->length;
}
mp->u.rmem.size = p->b;
mp->u.rmem.offs = p->a;
return 0;
}
@@ -666,6 +671,7 @@ static int optee_from_msg_param(FAR struct tee_ioctl_param *params,
{
FAR const struct optee_msg_param *mp = mparams + n;
FAR struct tee_ioctl_param *p = params + n;
FAR struct optee_shm *shm;
switch (mp->attr & OPTEE_MSG_ATTR_TYPE_MASK)
{
@@ -684,6 +690,20 @@ static int optee_from_msg_param(FAR struct tee_ioctl_param *params,
p->b = mp->u.value.b;
p->c = mp->u.value.c;
break;
case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
mp->attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
p->b = mp->u.tmem.size;
shm = (FAR struct optee_shm *)(uintptr_t)mp->u.tmem.shm_ref;
if (shm && shm->page_list)
{
kmm_free(shm->page_list);
shm->page_list = NULL;
}
break;
case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+1
View File
@@ -58,6 +58,7 @@ struct optee_shm
int32_t id;
uint64_t addr;
uint64_t length;
FAR void *page_list;
uint32_t flags;
};