summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDEEPAK SANNAPAREDDY <quic_sdeeredd@quicinc.com>2023-11-24 17:05:13 +0530
committerSantosh Sakore <quic_ssakore@quicinc.com>2024-05-17 04:25:06 -0700
commit605b4ceebfedc27d6b83ab4f0337973e43e02cc3 (patch)
tree98a0519b5dc71e48f09765e730811e580021eedc
parent4ce0e4a8d89f1df7a9fb1d7025543a743b244a23 (diff)
msm: adsprpc: Handle UAF in fastrpc internal munmap
Added reference count for contex map indicate memory under used in remote call. And, this memory would not removed in internal unmap to avoid UAF. Change-Id: Ieb4ff6b298ff9c48953bc5b3539fdfe19a14b442 Signed-off-by: DEEPAK SANNAPAREDDY <quic_sdeeredd@quicinc.com> (cherry picked from commit 98913b6855c765e36d95288b318826518c8b8e0d)
-rw-r--r--drivers/char/adsprpc.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index c94d93611d49..c452e23e7416 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -297,8 +297,8 @@ struct fastrpc_mmap {
int uncached;
int secure;
uintptr_t attr;
- bool is_filemap;
- /*flag to indicate map used in process init*/
+ bool is_filemap; /*flag to indicate map used in process init*/
+ unsigned int ctx_refs; /* Indicates reference count for context map */
};
struct fastrpc_perf {
@@ -574,7 +574,8 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
}
spin_lock(&fl->hlock);
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
- if (map->refs == 1 && map->raddr == va &&
+ /* Remove if only one reference map and no context map */
+ if (map->refs == 1 && !map->ctx_refs && map->raddr == va &&
map->raddr + map->len == va + len &&
/*Remove map if not used in process initialization*/
!map->is_filemap) {
@@ -616,13 +617,13 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
spin_lock(&me->hlock);
map->refs--;
- if (!map->refs)
+ if (!map->refs && !map->ctx_refs)
hlist_del_init(&map->hn);
spin_unlock(&me->hlock);
} else {
spin_lock(&fl->hlock);
map->refs--;
- if (!map->refs)
+ if (!map->refs && !map->ctx_refs)
hlist_del_init(&map->hn);
spin_unlock(&fl->hlock);
}
@@ -716,6 +717,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr,
map->fd = fd;
map->attr = attr;
map->is_filemap = false;
+ map->ctx_refs = 0;
if (mflags == ADSP_MMAP_HEAP_ADDR ||
mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
DEFINE_DMA_ATTRS(rh_attrs);
@@ -1133,8 +1135,11 @@ static void context_free(struct smq_invoke_ctx *ctx)
spin_lock(&ctx->fl->hlock);
hlist_del_init(&ctx->hn);
spin_unlock(&ctx->fl->hlock);
- for (i = 0; i < nbufs; ++i)
+ for (i = 0; i < nbufs; ++i) {
+ if (ctx->maps[i] && ctx->maps[i]->ctx_refs)
+ ctx->maps[i]->ctx_refs--;
fastrpc_mmap_free(ctx->maps[i]);
+ }
fastrpc_buf_free(ctx->buf, 1);
fastrpc_buf_free(ctx->lbuf, 1);
ctx->magic = 0;
@@ -1278,6 +1283,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
fastrpc_mmap_create(ctx->fl, ctx->fds[i],
ctx->attrs[i], buf, len,
mflags, &ctx->maps[i]);
+ if (ctx->maps[i])
+ ctx->maps[i]->ctx_refs++;
ipage += 1;
}
metalen = copylen = (size_t)&ipage[0];
@@ -1494,6 +1501,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
if (err)
goto bail;
} else {
+ if (ctx->maps[i]->ctx_refs)
+ ctx->maps[i]->ctx_refs--;
fastrpc_mmap_free(ctx->maps[i]);
ctx->maps[i] = NULL;
}