mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
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: Santosh Sakore <ssakore@qti.qualcomm.com> Signed-off-by: Santosh Sakore <quic_ssakore@quicinc.com>
This commit is contained in:
parent
460f325dcb
commit
96507bd863
1 changed files with 30 additions and 12 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/* Uncomment this block to log an error on every VERIFY failure */
|
||||
|
|
@ -579,10 +579,11 @@ struct fastrpc_mmap {
|
|||
bool is_persistent; /* Indicates whether map is persistent */
|
||||
int frpc_md_index; /* Minidump unique index */
|
||||
uintptr_t attr;
|
||||
bool in_use; /* Indicates if persistent map is in use*/
|
||||
bool in_use; /* Indicates if persistent map is in use */
|
||||
struct timespec64 map_start_time;
|
||||
struct timespec64 map_end_time;
|
||||
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 */
|
||||
};
|
||||
|
||||
enum fastrpc_perfkeys {
|
||||
|
|
@ -1220,7 +1221,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va,
|
|||
hlist_for_each_entry_safe(map, n, &me->maps, hn) {
|
||||
if (map->refs == 1 && map->raddr == va &&
|
||||
map->raddr + map->len == va + len &&
|
||||
/*Remove map if not used in process initialization*/
|
||||
/* Remove map if not used in process initialization */
|
||||
!map->is_filemap) {
|
||||
match = map;
|
||||
hlist_del_init(&map->hn);
|
||||
|
|
@ -1233,9 +1234,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va,
|
|||
return 0;
|
||||
}
|
||||
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
|
||||
if (map->refs == 1 && map->raddr == va &&
|
||||
map->raddr + map->len == va + len &&
|
||||
/*Remove map if not used in process initialization*/
|
||||
/* 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) {
|
||||
match = map;
|
||||
hlist_del_init(&map->hn);
|
||||
|
|
@ -1274,7 +1276,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
|
|||
map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
|
||||
spin_lock(&me->hlock);
|
||||
map->refs--;
|
||||
if (!map->refs && !map->is_persistent)
|
||||
if (!map->refs && !map->is_persistent && !map->ctx_refs)
|
||||
hlist_del_init(&map->hn);
|
||||
spin_unlock(&me->hlock);
|
||||
if (map->refs > 0) {
|
||||
|
|
@ -1290,7 +1292,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
|
|||
}
|
||||
} else {
|
||||
map->refs--;
|
||||
if (!map->refs)
|
||||
if (!map->refs && !map->ctx_refs)
|
||||
hlist_del_init(&map->hn);
|
||||
if (map->refs > 0 && !flags)
|
||||
return;
|
||||
|
|
@ -1426,6 +1428,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
|
|||
map->attr = attr;
|
||||
map->frpc_md_index = -1;
|
||||
map->is_filemap = false;
|
||||
map->ctx_refs = 0;
|
||||
ktime_get_real_ts64(&map->map_start_time);
|
||||
if (mflags == ADSP_MMAP_HEAP_ADDR ||
|
||||
mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
|
||||
|
|
@ -2177,8 +2180,11 @@ static void context_free(struct smq_invoke_ctx *ctx)
|
|||
spin_unlock(&ctx->fl->hlock);
|
||||
|
||||
mutex_lock(&ctx->fl->map_mutex);
|
||||
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], 0);
|
||||
}
|
||||
mutex_unlock(&ctx->fl->map_mutex);
|
||||
|
||||
fastrpc_buf_free(ctx->buf, 1);
|
||||
|
|
@ -2485,6 +2491,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
|
|||
err = 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++;
|
||||
mutex_unlock(&ctx->fl->map_mutex);
|
||||
if (err)
|
||||
goto bail;
|
||||
|
|
@ -2502,9 +2510,14 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
|
|||
err = fastrpc_mmap_create(ctx->fl, ctx->fds[i],
|
||||
FASTRPC_ATTR_NOVA, 0, 0, dmaflags,
|
||||
&ctx->maps[i]);
|
||||
if (!err && ctx->maps[i])
|
||||
ctx->maps[i]->ctx_refs++;
|
||||
if (err) {
|
||||
for (j = bufs; j < i; j++)
|
||||
for (j = bufs; j < i; j++) {
|
||||
if (ctx->maps[j] && ctx->maps[j]->ctx_refs)
|
||||
ctx->maps[j]->ctx_refs--;
|
||||
fastrpc_mmap_free(ctx->maps[j], 0);
|
||||
}
|
||||
mutex_unlock(&ctx->fl->map_mutex);
|
||||
goto bail;
|
||||
}
|
||||
|
|
@ -2835,6 +2848,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
|
|||
}
|
||||
} else {
|
||||
mutex_lock(&ctx->fl->map_mutex);
|
||||
if (ctx->maps[i]->ctx_refs)
|
||||
ctx->maps[i]->ctx_refs--;
|
||||
fastrpc_mmap_free(ctx->maps[i], 0);
|
||||
mutex_unlock(&ctx->fl->map_mutex);
|
||||
ctx->maps[i] = NULL;
|
||||
|
|
@ -2845,8 +2860,11 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
|
|||
if (!fdlist[i])
|
||||
break;
|
||||
if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0,
|
||||
0, 0, &mmap))
|
||||
0, 0, &mmap)) {
|
||||
if (mmap && mmap->ctx_refs)
|
||||
mmap->ctx_refs--;
|
||||
fastrpc_mmap_free(mmap, 0);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ctx->fl->map_mutex);
|
||||
if (ctx->crc && crclist && rpra)
|
||||
|
|
|
|||
Loading…
Reference in a new issue