Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+56 -17
+7
drivers/tee/optee/core.c
··· 216 216 217 217 if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) 218 218 v.gen_caps |= TEE_GEN_CAP_REG_MEM; 219 + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) 220 + v.gen_caps |= TEE_GEN_CAP_MEMREF_NULL; 219 221 *vers = v; 220 222 } 221 223 ··· 263 261 } 264 262 mutex_init(&ctxdata->mutex); 265 263 INIT_LIST_HEAD(&ctxdata->sess_list); 264 + 265 + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) 266 + ctx->cap_memref_null = true; 267 + else 268 + ctx->cap_memref_null = false; 266 269 267 270 ctx->data = ctxdata; 268 271 return 0;
+3
drivers/tee/optee/optee_smc.h
··· 215 215 */ 216 216 #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) 217 217 218 + /* Secure world supports Shared Memory with a NULL buffer reference */ 219 + #define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) 220 + 218 221 #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 219 222 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ 220 223 OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
+30 -17
drivers/tee/tee_core.c
··· 383 383 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: 384 384 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: 385 385 /* 386 - * If we fail to get a pointer to a shared memory 387 - * object (and increase the ref count) from an 388 - * identifier we return an error. All pointers that 389 - * has been added in params have an increased ref 390 - * count. It's the callers responibility to do 391 - * tee_shm_put() on all resolved pointers. 386 + * If a NULL pointer is passed to a TA in the TEE, 387 + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL 388 + * indicating a NULL memory reference. 392 389 */ 393 - shm = tee_shm_get_from_id(ctx, ip.c); 394 - if (IS_ERR(shm)) 395 - return PTR_ERR(shm); 390 + if (ip.c != TEE_MEMREF_NULL) { 391 + /* 392 + * If we fail to get a pointer to a shared 393 + * memory object (and increase the ref count) 394 + * from an identifier we return an error. All 395 + * pointers that has been added in params have 396 + * an increased ref count. It's the callers 397 + * responibility to do tee_shm_put() on all 398 + * resolved pointers. 399 + */ 400 + shm = tee_shm_get_from_id(ctx, ip.c); 401 + if (IS_ERR(shm)) 402 + return PTR_ERR(shm); 396 403 397 - /* 398 - * Ensure offset + size does not overflow offset 399 - * and does not overflow the size of the referred 400 - * shared memory object. 401 - */ 402 - if ((ip.a + ip.b) < ip.a || 403 - (ip.a + ip.b) > shm->size) { 404 - tee_shm_put(shm); 404 + /* 405 + * Ensure offset + size does not overflow 406 + * offset and does not overflow the size of 407 + * the referred shared memory object. 408 + */ 409 + if ((ip.a + ip.b) < ip.a || 410 + (ip.a + ip.b) > shm->size) { 411 + tee_shm_put(shm); 412 + return -EINVAL; 413 + } 414 + } else if (ctx->cap_memref_null) { 415 + /* Pass NULL pointer to OP-TEE */ 416 + shm = NULL; 417 + } else { 405 418 return -EINVAL; 406 419 } 407 420
+3
include/linux/tee_drv.h
··· 47 47 * and just return with an error code. It is needed for requests 48 48 * that arises from TEE based kernel drivers that should be 49 49 * non-blocking in nature. 50 + * @cap_memref_null: flag indicating if the TEE Client support shared 51 + * memory buffer with a NULL pointer. 50 52 */ 51 53 struct tee_context { 52 54 struct tee_device *teedev; ··· 56 54 struct kref refcount; 57 55 bool releasing; 58 56 bool supp_nowait; 57 + bool cap_memref_null; 59 58 }; 60 59 61 60 struct tee_param_memref {
+13
include/uapi/linux/tee.h
··· 51 51 #define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ 52 52 #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ 53 53 #define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ 54 + #define TEE_GEN_CAP_MEMREF_NULL (1 << 3)/* NULL MemRef support */ 55 + 56 + #define TEE_MEMREF_NULL (__u64)(-1) /* NULL MemRef Buffer */ 54 57 55 58 /* 56 59 * TEE Implementation ID ··· 203 200 * a part of a shared memory by specifying an offset (@a) and size (@b) of 204 201 * the object. To supply the entire shared memory object set the offset 205 202 * (@a) to 0 and size (@b) to the previously returned size of the object. 203 + * 204 + * A client may need to present a NULL pointer in the argument 205 + * passed to a trusted application in the TEE. 206 + * This is also a requirement in GlobalPlatform Client API v1.0c 207 + * (section 3.2.5 memory references), which can be found at 208 + * http://www.globalplatform.org/specificationsdevice.asp 209 + * 210 + * If a NULL pointer is passed to a TA in the TEE, the (@c) 211 + * IOCTL parameters value must be set to TEE_MEMREF_NULL indicating a NULL 212 + * memory reference. 206 213 */ 207 214 struct tee_ioctl_param { 208 215 __u64 attr;