Skip to content

Commit 81d9db8

Browse files
Vamsi Krishna GattupallimikeNG
authored andcommitted
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 Acked-by: DEEPAK SANNAPAREDDY <sdeeredd@qti.qualcomm.com> Signed-off-by: Vamsi Krishna Gattupalli <quic_vgattupa@quicinc.com>
1 parent 5ef4c30 commit 81d9db8

1 file changed

Lines changed: 24 additions & 9 deletions

File tree

drivers/char/adsprpc.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
3+
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
34
*
45
* This program is free software; you can redistribute it and/or modify
56
* it under the terms of the GNU General Public License version 2 and
@@ -356,7 +357,8 @@ struct fastrpc_mmap {
356357
int uncached;
357358
int secure;
358359
uintptr_t attr;
359-
bool is_filemap; /*flag to indicate map used in process init*/
360+
bool is_filemap; /* flag to indicate map used in process init */
361+
unsigned int ctx_refs; /* Indicates reference count for context map */
360362
};
361363

362364
enum fastrpc_perfkeys {
@@ -719,7 +721,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
719721
hlist_for_each_entry_safe(map, n, &me->maps, hn) {
720722
if (map->refs == 1 && map->raddr == va &&
721723
map->raddr + map->len == va + len &&
722-
/*Remove map if not used in process initialization*/
724+
/* Remove map if not used in process initialization */
723725
!map->is_filemap) {
724726
match = map;
725727
hlist_del_init(&map->hn);
@@ -732,9 +734,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
732734
return 0;
733735
}
734736
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
735-
if (map->refs == 1 && map->raddr == va &&
737+
/* Remove if only one reference map and no context map */
738+
if (map->refs == 1 && !map->ctx_refs && map->raddr == va &&
736739
map->raddr + map->len == va + len &&
737-
/*Remove map if not used in process initialization*/
740+
/* Remove map if not used in process initialization */
738741
!map->is_filemap) {
739742
match = map;
740743
hlist_del_init(&map->hn);
@@ -773,14 +776,14 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
773776
map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
774777
spin_lock(&me->hlock);
775778
map->refs--;
776-
if (!map->refs)
779+
if (!map->refs && !map->ctx_refs)
777780
hlist_del_init(&map->hn);
778781
spin_unlock(&me->hlock);
779782
if (map->refs > 0)
780783
return;
781784
} else {
782785
map->refs--;
783-
if (!map->refs)
786+
if (!map->refs && !map->ctx_refs)
784787
hlist_del_init(&map->hn);
785788
if (map->refs > 0 && !flags)
786789
return;
@@ -878,6 +881,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
878881
map->fd = fd;
879882
map->attr = attr;
880883
map->is_filemap = false;
884+
map->ctx_refs = 0;
881885
if (mflags == ADSP_MMAP_HEAP_ADDR ||
882886
mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
883887
unsigned long dma_attrs = DMA_ATTR_SKIP_ZEROING |
@@ -1336,9 +1340,11 @@ static void context_free(struct smq_invoke_ctx *ctx)
13361340
hlist_del_init(&ctx->hn);
13371341
spin_unlock(&ctx->fl->hlock);
13381342
mutex_lock(&ctx->fl->fl_map_mutex);
1339-
for (i = 0; i < nbufs; ++i)
1343+
for (i = 0; i < nbufs; ++i) {
1344+
if (ctx->maps[i] && ctx->maps[i]->ctx_refs)
1345+
ctx->maps[i]->ctx_refs--;
13401346
fastrpc_mmap_free(ctx->maps[i], 0);
1341-
1347+
}
13421348
mutex_unlock(&ctx->fl->fl_map_mutex);
13431349
fastrpc_buf_free(ctx->buf, 1);
13441350
fastrpc_buf_free(ctx->lbuf, 1);
@@ -1527,6 +1533,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
15271533
attrs, buf, len,
15281534
mflags, &ctx->maps[i]);
15291535
}
1536+
if (ctx->maps[i])
1537+
ctx->maps[i]->ctx_refs++;
15301538
mutex_unlock(&ctx->fl->fl_map_mutex);
15311539
ipage += 1;
15321540
}
@@ -1540,6 +1548,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
15401548
dmaflags = FASTRPC_DMAHANDLE_NOMAP;
15411549
VERIFY(err, !fastrpc_mmap_create(ctx->fl, ctx->fds[i],
15421550
FASTRPC_ATTR_NOVA, 0, 0, dmaflags, &ctx->maps[i]));
1551+
if (!err && ctx->maps[i])
1552+
ctx->maps[i]->ctx_refs++;
15431553
if (err) {
15441554
mutex_unlock(&ctx->fl->fl_map_mutex);
15451555
goto bail;
@@ -1786,6 +1796,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
17861796
goto bail;
17871797
} else {
17881798
mutex_lock(&ctx->fl->fl_map_mutex);
1799+
if (ctx->maps[i]->ctx_refs)
1800+
ctx->maps[i]->ctx_refs--;
17891801
fastrpc_mmap_free(ctx->maps[i], 0);
17901802
mutex_unlock(&ctx->fl->fl_map_mutex);
17911803
ctx->maps[i] = NULL;
@@ -1797,8 +1809,11 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
17971809
if (!fdlist[i])
17981810
break;
17991811
if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0,
1800-
0, 0, &mmap))
1812+
0, 0, &mmap)) {
1813+
if (mmap && mmap->ctx_refs)
1814+
mmap->ctx_refs--;
18011815
fastrpc_mmap_free(mmap, 0);
1816+
}
18021817
}
18031818
}
18041819
mutex_unlock(&ctx->fl->fl_map_mutex);

0 commit comments

Comments
 (0)