Skip to content

Commit 217e025

Browse files
lorcjenswi-linaro
authored andcommitted
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: Volodymyr Babchuk <[email protected]> Signed-off-by: Jens Wiklander <[email protected]>
1 parent f58e236 commit 217e025

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

drivers/tee/tee_core.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static int tee_open(struct inode *inode, struct file *filp)
5454
goto err;
5555
}
5656

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

71-
static int tee_release(struct inode *inode, struct file *filp)
72+
void teedev_ctx_get(struct tee_context *ctx)
7273
{
73-
struct tee_context *ctx = filp->private_data;
74-
struct tee_device *teedev = ctx->teedev;
75-
struct tee_shm *shm;
74+
if (ctx->releasing)
75+
return;
76+
77+
kref_get(&ctx->refcount);
78+
}
7679

80+
static void teedev_ctx_release(struct kref *ref)
81+
{
82+
struct tee_context *ctx = container_of(ref, struct tee_context,
83+
refcount);
84+
ctx->releasing = true;
7785
ctx->teedev->desc->ops->release(ctx);
78-
mutex_lock(&ctx->teedev->mutex);
79-
list_for_each_entry(shm, &ctx->list_shm, link)
80-
shm->ctx = NULL;
81-
mutex_unlock(&ctx->teedev->mutex);
8286
kfree(ctx);
83-
tee_device_put(teedev);
87+
}
88+
89+
void teedev_ctx_put(struct tee_context *ctx)
90+
{
91+
if (ctx->releasing)
92+
return;
93+
94+
kref_put(&ctx->refcount, teedev_ctx_release);
95+
}
96+
97+
static void teedev_close_context(struct tee_context *ctx)
98+
{
99+
tee_device_put(ctx->teedev);
100+
teedev_ctx_put(ctx);
101+
}
102+
103+
static int tee_release(struct inode *inode, struct file *filp)
104+
{
105+
teedev_close_context(filp->private_data);
84106
return 0;
85107
}
86108

drivers/tee/tee_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,7 @@ int tee_shm_get_fd(struct tee_shm *shm);
7373
bool tee_device_get(struct tee_device *teedev);
7474
void tee_device_put(struct tee_device *teedev);
7575

76+
void teedev_ctx_get(struct tee_context *ctx);
77+
void teedev_ctx_put(struct tee_context *ctx);
78+
7679
#endif /*TEE_PRIVATE_H*/

drivers/tee/tee_shm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ static void tee_shm_release(struct tee_shm *shm)
5353
kfree(shm->pages);
5454
}
5555

56+
if (shm->ctx)
57+
teedev_ctx_put(shm->ctx);
58+
5659
kfree(shm);
5760

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

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

260+
teedev_ctx_get(ctx);
261+
256262
shm = kzalloc(sizeof(*shm), GFP_KERNEL);
257263
if (!shm) {
258264
ret = ERR_PTR(-ENOMEM);
@@ -334,6 +340,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
334340
kfree(shm->pages);
335341
}
336342
kfree(shm);
343+
teedev_ctx_put(ctx);
337344
tee_device_put(teedev);
338345
return ret;
339346
}

include/linux/tee_drv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <linux/types.h>
1919
#include <linux/idr.h>
20+
#include <linux/kref.h>
2021
#include <linux/list.h>
2122
#include <linux/tee.h>
2223

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

5259
struct tee_param_memref {

0 commit comments

Comments
 (0)