Commit d4ee2d35 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'tee-memref-null-for-v5.10' of...

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: default avatarOlof Johansson <olof@lixom.net>
parents 0f863bb6 ba171d3f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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;
}
+3 −0
Original line number Diff line number Diff line
@@ -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)
+31 −18
Original line number Diff line number Diff line
@@ -383,27 +383,40 @@ 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.
			 */
			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.
				 * 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;
			}

			params[n].u.memref.shm_offs = ip.a;
			params[n].u.memref.size = ip.b;
+3 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ struct tee_shm_pool;
 *              and just return with an error code. It is needed for requests
 *              that arises from TEE based kernel drivers that should be
 *              non-blocking in nature.
 * @cap_memref_null: flag indicating if the TEE Client support shared
 *                   memory buffer with a NULL pointer.
 */
struct tee_context {
	struct tee_device *teedev;
@@ -54,6 +56,7 @@ struct tee_context {
	struct kref refcount;
	bool releasing;
	bool supp_nowait;
	bool cap_memref_null;
};

struct tee_param_memref {
+13 −0
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@
#define TEE_GEN_CAP_GP		(1 << 0)/* GlobalPlatform compliant TEE */
#define TEE_GEN_CAP_PRIVILEGED	(1 << 1)/* Privileged device (for supplicant) */
#define TEE_GEN_CAP_REG_MEM	(1 << 2)/* Supports registering shared memory */
#define TEE_GEN_CAP_MEMREF_NULL	(1 << 3)/* NULL MemRef support */

#define TEE_MEMREF_NULL		(__u64)(-1) /* NULL MemRef Buffer */

/*
 * TEE Implementation ID
@@ -200,6 +203,16 @@ struct tee_ioctl_buf_data {
 * a part of a shared memory by specifying an offset (@a) and size (@b) of
 * the object. To supply the entire shared memory object set the offset
 * (@a) to 0 and size (@b) to the previously returned size of the object.
 *
 * A client may need to present a NULL pointer in the argument
 * passed to a trusted application in the TEE.
 * This is also a requirement in GlobalPlatform Client API v1.0c
 * (section 3.2.5 memory references), which can be found at
 * http://www.globalplatform.org/specificationsdevice.asp
 *
 * If a NULL pointer is passed to a TA in the TEE, the (@c)
 * IOCTL parameters value must be set to TEE_MEMREF_NULL indicating a NULL
 * memory reference.
 */
struct tee_ioctl_param {
	__u64 attr;