diff options
author | Olof Johansson | 2020-08-21 09:20:29 -0700 |
---|---|---|
committer | Olof Johansson | 2020-08-21 09:20:30 -0700 |
commit | d4ee2d35009adec016dccb47416dda411a791072 (patch) | |
tree | 4c5003c378914b0e2c7874b32363159b280add14 /drivers/tee | |
parent | 0f863bb6b80af0465d3ff13a72f77760648f1895 (diff) | |
parent | ba171d3f0850003216fd1a85190d17b1feddb961 (diff) |
Merge tag 'tee-memref-null-for-v5.10' of git://git.linaro.org/people/jens.wiklander/linux-tee into arm/drivers
Handle NULL pointer indication from tee client
Adds support to indicate NULL pointers instead of a valid buffer when
querying the needed size of a buffer.
* tag 'tee-memref-null-for-v5.10' of git://git.linaro.org/people/jens.wiklander/linux-tee:
driver: tee: Handle NULL pointer indication from client
Link: https://lore.kernel.org/r/20200821102535.GA1872111@jade
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/tee')
-rw-r--r-- | drivers/tee/optee/core.c | 7 | ||||
-rw-r--r-- | drivers/tee/optee/optee_smc.h | 3 | ||||
-rw-r--r-- | drivers/tee/tee_core.c | 49 |
3 files changed, 41 insertions, 18 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index b373b1b08b6d..cf4718c6d35d 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -216,6 +216,8 @@ static void optee_get_version(struct tee_device *teedev, if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) v.gen_caps |= TEE_GEN_CAP_REG_MEM; + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + v.gen_caps |= TEE_GEN_CAP_MEMREF_NULL; *vers = v; } @@ -262,6 +264,11 @@ static int optee_open(struct tee_context *ctx) mutex_init(&ctxdata->mutex); INIT_LIST_HEAD(&ctxdata->sess_list); + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + ctx->cap_memref_null = true; + else + ctx->cap_memref_null = false; + ctx->data = ctxdata; return 0; } diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index c72122d9c997..777ad54d4c2c 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -215,6 +215,9 @@ struct optee_smc_get_shm_config_result { */ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) +/* Secure world supports Shared Memory with a NULL buffer reference */ +#define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) + #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 64637e09a095..ce0f0309b6ac 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -383,25 +383,38 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: /* - * If we fail to get a pointer to a shared memory - * object (and increase the ref count) from an - * identifier we return an error. All pointers that - * has been added in params have an increased ref - * count. It's the callers responibility to do - * tee_shm_put() on all resolved pointers. + * If a NULL pointer is passed to a TA in the TEE, + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL + * indicating a NULL memory reference. */ - shm = tee_shm_get_from_id(ctx, ip.c); - if (IS_ERR(shm)) - return PTR_ERR(shm); - - /* - * Ensure offset + size does not overflow offset - * and does not overflow the size of the referred - * shared memory object. - */ - if ((ip.a + ip.b) < ip.a || - (ip.a + ip.b) > shm->size) { - tee_shm_put(shm); + if (ip.c != TEE_MEMREF_NULL) { + /* + * If we fail to get a pointer to a shared + * memory object (and increase the ref count) + * from an identifier we return an error. All + * pointers that has been added in params have + * an increased ref count. It's the callers + * responibility to do tee_shm_put() on all + * resolved pointers. + */ + shm = tee_shm_get_from_id(ctx, ip.c); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + /* + * Ensure offset + size does not overflow + * offset and does not overflow the size of + * the referred shared memory object. + */ + if ((ip.a + ip.b) < ip.a || + (ip.a + ip.b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + } else if (ctx->cap_memref_null) { + /* Pass NULL pointer to OP-TEE */ + shm = NULL; + } else { return -EINVAL; } |