Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 217e0250 authored by Volodymyr Babchuk's avatar Volodymyr Babchuk Committed by Jens Wiklander
Browse files

tee: use reference counting for tee_context



We need to ensure that tee_context is present until last
shared buffer will be freed.

Signed-off-by: default avatarVolodymyr Babchuk <vlad.babchuk@gmail.com>
Signed-off-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
parent f58e236c
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ static int tee_open(struct inode *inode, struct file *filp)
		goto err;
	}

	kref_init(&ctx->refcount);
	ctx->teedev = teedev;
	INIT_LIST_HEAD(&ctx->list_shm);
	filp->private_data = ctx;
@@ -68,19 +69,40 @@ static int tee_open(struct inode *inode, struct file *filp)
	return rc;
}

static int tee_release(struct inode *inode, struct file *filp)
void teedev_ctx_get(struct tee_context *ctx)
{
	struct tee_context *ctx = filp->private_data;
	struct tee_device *teedev = ctx->teedev;
	struct tee_shm *shm;
	if (ctx->releasing)
		return;

	kref_get(&ctx->refcount);
}

static void teedev_ctx_release(struct kref *ref)
{
	struct tee_context *ctx = container_of(ref, struct tee_context,
					       refcount);
	ctx->releasing = true;
	ctx->teedev->desc->ops->release(ctx);
	mutex_lock(&ctx->teedev->mutex);
	list_for_each_entry(shm, &ctx->list_shm, link)
		shm->ctx = NULL;
	mutex_unlock(&ctx->teedev->mutex);
	kfree(ctx);
	tee_device_put(teedev);
}

void teedev_ctx_put(struct tee_context *ctx)
{
	if (ctx->releasing)
		return;

	kref_put(&ctx->refcount, teedev_ctx_release);
}

static void teedev_close_context(struct tee_context *ctx)
{
	tee_device_put(ctx->teedev);
	teedev_ctx_put(ctx);
}

static int tee_release(struct inode *inode, struct file *filp)
{
	teedev_close_context(filp->private_data);
	return 0;
}

+3 −0
Original line number Diff line number Diff line
@@ -73,4 +73,7 @@ int tee_shm_get_fd(struct tee_shm *shm);
bool tee_device_get(struct tee_device *teedev);
void tee_device_put(struct tee_device *teedev);

void teedev_ctx_get(struct tee_context *ctx);
void teedev_ctx_put(struct tee_context *ctx);

#endif /*TEE_PRIVATE_H*/
+7 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@ static void tee_shm_release(struct tee_shm *shm)
		kfree(shm->pages);
	}

	if (shm->ctx)
		teedev_ctx_put(shm->ctx);

	kfree(shm);

	tee_device_put(teedev);
@@ -187,6 +190,7 @@ struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
	}

	if (ctx) {
		teedev_ctx_get(ctx);
		mutex_lock(&teedev->mutex);
		list_add_tail(&shm->link, &ctx->list_shm);
		mutex_unlock(&teedev->mutex);
@@ -253,6 +257,8 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
		return ERR_PTR(-ENOTSUPP);
	}

	teedev_ctx_get(ctx);

	shm = kzalloc(sizeof(*shm), GFP_KERNEL);
	if (!shm) {
		ret = ERR_PTR(-ENOMEM);
@@ -334,6 +340,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
		kfree(shm->pages);
	}
	kfree(shm);
	teedev_ctx_put(ctx);
	tee_device_put(teedev);
	return ret;
}
+7 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

#include <linux/types.h>
#include <linux/idr.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/tee.h>

@@ -42,11 +43,17 @@ struct tee_shm_pool;
 * @teedev:	pointer to this drivers struct tee_device
 * @list_shm:	List of shared memory object owned by this context
 * @data:	driver specific context data, managed by the driver
 * @refcount:	reference counter for this structure
 * @releasing:  flag that indicates if context is being released right now.
 *		It is needed to break circular dependency on context during
 *              shared memory release.
 */
struct tee_context {
	struct tee_device *teedev;
	struct list_head list_shm;
	void *data;
	struct kref refcount;
	bool releasing;
};

struct tee_param_memref {