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

Commit d7257578 authored by Vamsi Krishna Gattupalli's avatar Vamsi Krishna Gattupalli
Browse files

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: default avatarDEEPAK SANNAPAREDDY <sdeeredd@qti.qualcomm.com>
Signed-off-by: default avatarVamsi Krishna Gattupalli <quic_vgattupa@quicinc.com>
parent fbca1995
Loading
Loading
Loading
Loading
+28 −11
Original line number Diff line number Diff line
@@ -415,8 +415,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 */
};

enum fastrpc_perfkeys {
@@ -862,8 +862,9 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, 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 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;
@@ -903,14 +904,14 @@ 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)
		if (!map->refs && !map->ctx_refs)
			hlist_del_init(&map->hn);
		spin_unlock(&me->hlock);
		if (map->refs > 0)
			return;
	} else {
		map->refs--;
		if (!map->refs)
		if (!map->refs && !map->ctx_refs)
			hlist_del_init(&map->hn);
		if (map->refs > 0 && !flags)
			return;
@@ -1008,6 +1009,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
	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) {
		map->apps = me;
@@ -1533,8 +1535,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);
@@ -1757,6 +1762,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;
@@ -1774,9 +1781,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;
		}
@@ -2059,6 +2071,8 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
				goto bail;
		} 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;
@@ -2070,10 +2084,13 @@ 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)
		K_COPY_TO_USER(err, kernel, ctx->crc,