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

Commit 65963440 authored by Swathi K's avatar Swathi K
Browse files

msm: adsprpc: Handle out of bounds access



Add check for channel ID in fastrpc_buf_alloc to
fix out of bounds access.

Change-Id: I92f2717edcc91c19309589ce7c11c91c8129b71a
Signed-off-by: default avatarSwathi K <quic_c_kataka@quicinc.com>
parent b2e71fbd
Loading
Loading
Loading
Loading
+106 −36
Original line number Diff line number Diff line
@@ -997,7 +997,7 @@ static int fastrpc_minidump_remove_region(struct fastrpc_mmap *map)
static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
{
	struct fastrpc_file *fl = buf == NULL ? NULL : buf->fl;
	int vmid, err = 0;
	int vmid, err = 0, cid = -1;

	if (!fl)
		return;
@@ -1036,7 +1036,16 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
			goto bail;
		if (fl->sctx->smmu.cb)
			buf->phys &= ~((uint64_t)fl->sctx->smmu.cb << 32);
		vmid = fl->apps->channel[fl->cid].vmid;
		cid = fl->cid;
		VERIFY(err, VALID_FASTRPC_CID(cid));
		if (err) {
			err = -ECHRNG;
			ADSPRPC_ERR(
				"invalid channel 0x%zx set for session\n",
				cid);
			goto bail;
		}
		vmid = fl->apps->channel[cid].vmid;
		if (vmid) {
			int srcVM[2] = {VMID_HLOS, vmid};
			int hyp_err = 0;
@@ -1050,7 +1059,7 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache)
					hyp_err, buf->phys, buf->size);
			}
		}
		trace_fastrpc_dma_free(fl->cid, buf->phys, buf->size);
		trace_fastrpc_dma_free(cid, buf->phys, buf->size);
		dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt,
					buf->phys, buf->dma_attr);
	}
@@ -1304,7 +1313,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
			(dma_addr_t)map->phys, (unsigned long)map->attr);
		}
	} else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) {
		trace_fastrpc_dma_unmap(fl->cid, map->phys, map->size);
		trace_fastrpc_dma_unmap(cid, map->phys, map->size);
		if (!IS_ERR_OR_NULL(map->table))
			dma_buf_unmap_attachment(map->attach, map->table,
					DMA_BIDIRECTIONAL);
@@ -1321,7 +1330,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
		else
			sess = fl->sctx;

		vmid = fl->apps->channel[fl->cid].vmid;
		vmid = fl->apps->channel[cid].vmid;
		if (vmid && map->phys) {
			int hyp_err = 0;
			int srcVM[2] = {VMID_HLOS, vmid};
@@ -1335,7 +1344,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags)
					hyp_err, map->phys, map->size);
			}
		}
		trace_fastrpc_dma_unmap(fl->cid, map->phys, map->size);
		trace_fastrpc_dma_unmap(cid, map->phys, map->size);
		if (!IS_ERR_OR_NULL(map->table))
			dma_buf_unmap_attachment(map->attach, map->table,
					DMA_BIDIRECTIONAL);
@@ -1389,6 +1398,11 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
	int err = 0, vmid, sgl_index = 0;
	struct scatterlist *sgl = NULL;

	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	cid = fl->cid;
	VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS);
	if (err) {
		err = -ECHRNG;
@@ -1485,7 +1499,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
		}
		map->phys = sg_dma_address(map->table->sgl);
		map->size = len;
		trace_fastrpc_dma_map(fl->cid, fd, map->phys, map->size,
		trace_fastrpc_dma_map(cid, fd, map->phys, map->size,
			len, mflags, map->attach->dma_map_attrs);
	} else {
		if (map->attr && (map->attr & FASTRPC_ATTR_KEEP_MAP)) {
@@ -1591,7 +1605,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
		} else {
			map->size = buf_page_size(len);
		}
		trace_fastrpc_dma_map(fl->cid, fd, map->phys, map->size,
		trace_fastrpc_dma_map(cid, fd, map->phys, map->size,
			len, mflags, map->attach->dma_map_attrs);

		VERIFY(err, map->size >= len && map->size < me->max_size_limit);
@@ -1602,7 +1616,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
			goto bail;
		}

		vmid = fl->apps->channel[fl->cid].vmid;
		vmid = fl->apps->channel[cid].vmid;
		if (vmid) {
			int srcVM[1] = {VMID_HLOS};
			int destVM[2] = {VMID_HLOS, vmid};
@@ -1702,7 +1716,7 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
			unsigned long dma_attr, uint32_t rflags,
			int buf_type, struct fastrpc_buf **obuf)
{
	int err = 0, vmid;
	int err = 0, vmid, cid = -1;
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_buf *buf = NULL;

@@ -1719,6 +1733,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
		err = -EBADR;
		goto bail;
	}
	cid = fl->cid;
	VERIFY(err, VALID_FASTRPC_CID(cid));
	if (err) {
		err = -ECHRNG;
		goto bail;
	}

	VERIFY(err, size > 0 && fl->sctx->smmu.dev);
	if (err) {
		err = (fl->sctx->smmu.dev == NULL) ? -ENODEV : err;
@@ -1766,10 +1787,10 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size,
	}
	if (fl->sctx->smmu.cb)
		buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32);
	trace_fastrpc_dma_alloc(fl->cid, buf->phys, size,
	trace_fastrpc_dma_alloc(cid, buf->phys, size,
		dma_attr, (int)rflags);

	vmid = fl->apps->channel[fl->cid].vmid;
	vmid = fl->apps->channel[cid].vmid;
	if (vmid) {
		int srcVM[1] = {VMID_HLOS};
		int destVM[2] = {VMID_HLOS, vmid};
@@ -2940,6 +2961,10 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
	uint32_t sc = ctx->sc;
	int64_t ns = 0;

	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	cid = fl->cid;
	VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS);
	if (err) {
@@ -2947,7 +2972,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
		goto bail;
	}

	channel_ctx = &fl->apps->channel[fl->cid];
	channel_ctx = &fl->apps->channel[cid];
	mutex_lock(&channel_ctx->smd_mutex);
	msg->pid = fl->tgid;
	msg->tid = current->pid;
@@ -2977,7 +3002,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
	}
	err = rpmsg_send(channel_ctx->rpdev->ept, (void *)msg, sizeof(*msg));
	mutex_unlock(&channel_ctx->rpmsg_mutex);
	trace_fastrpc_rpmsg_send(fl->cid, (uint64_t)ctx, msg->invoke.header.ctx,
	trace_fastrpc_rpmsg_send(cid, (uint64_t)ctx, msg->invoke.header.ctx,
		handle, sc, msg->invoke.page.addr, msg->invoke.page.size);
	ns = get_timestamp_in_ns();
	fastrpc_update_txmsg_buf(channel_ctx, msg, err, ns);
@@ -4116,21 +4141,29 @@ static int fastrpc_init_process(struct fastrpc_file *fl,

static int fastrpc_send_cpuinfo_to_dsp(struct fastrpc_file *fl)
{
	int err = 0;
	int err = 0, cid = -1;
	uint64_t cpuinfo = 0;
	struct fastrpc_apps *me = &gfa;
	struct fastrpc_ioctl_invoke_async ioctl;
	remote_arg_t ra[2];

	VERIFY(err, fl && fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS);
	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	cid = fl->cid;
	VERIFY(err, VALID_FASTRPC_CID(cid));
	if (err) {
		err = -ECHRNG;
		ADSPRPC_ERR(
			"invalid channel 0x%zx set for session\n",
			cid);
		goto bail;
	}

	cpuinfo = me->channel[fl->cid].cpuinfo_todsp;
	cpuinfo = me->channel[cid].cpuinfo_todsp;
	/* return success if already updated to remote processor */
	if (me->channel[fl->cid].cpuinfo_status)
	if (me->channel[cid].cpuinfo_status)
		return 0;

	ra[0].buf.pv = (void *)&cpuinfo;
@@ -4148,7 +4181,7 @@ static int fastrpc_send_cpuinfo_to_dsp(struct fastrpc_file *fl)

	err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, KERNEL_MSG_WITH_ZERO_PID, &ioctl);
	if (!err)
		me->channel[fl->cid].cpuinfo_status = true;
		me->channel[cid].cpuinfo_status = true;
bail:
	return err;
}
@@ -4263,12 +4296,17 @@ static int fastrpc_get_info_from_kernel(

static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
{
	int err = 0;
	int err = 0, cid = -1;
	struct fastrpc_ioctl_invoke_async ioctl;
	remote_arg_t ra[1];
	int tgid = 0;

	VERIFY(err, fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS);
	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	cid = fl->cid;
	VERIFY(err, VALID_FASTRPC_CID(cid));
	if (err) {
		err = -ECHRNG;
		goto bail;
@@ -4278,12 +4316,12 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
		err = -EBADR;
		goto bail;
	}
	VERIFY(err, fl->apps->channel[fl->cid].rpdev != NULL);
	VERIFY(err, fl->apps->channel[cid].rpdev != NULL);
	if (err) {
		err = -ENODEV;
		goto bail;
	}
	VERIFY(err, fl->apps->channel[fl->cid].issubsystemup == 1);
	VERIFY(err, fl->apps->channel[cid].issubsystemup == 1);
	if (err) {
		err = -ECONNRESET;
		goto bail;
@@ -4470,7 +4508,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
	struct fastrpc_ioctl_invoke_async ioctl;
	struct fastrpc_apps *me = &gfa;
	struct smq_phy_page page;
	int num = 1;
	int num = 1, cid = -1;
	remote_arg_t ra[3];
	int err = 0;
	struct {
@@ -4483,6 +4521,11 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
		uintptr_t vaddrout;
	} routargs;

	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	cid = fl->cid;
	inargs.pid = fl->tgid;
	inargs.vaddrin = (uintptr_t)va;
	inargs.flags = flags;
@@ -4514,12 +4557,22 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
	*raddr = (uintptr_t)routargs.vaddrout;
	if (err)
		goto bail;
	if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
		VERIFY(err, VALID_FASTRPC_CID(cid));
		if (err) {
			err = -ECHRNG;
			ADSPRPC_ERR(
				"invalid channel 0x%zx set for session\n",
				cid);
			goto bail;
		}
	}
	if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR
				&& me->channel[fl->cid].rhvm.vmid) {
				&& me->channel[cid].rhvm.vmid) {
		err = hyp_assign_phys(phys, (uint64_t)size,
				hlosvm, 1, me->channel[fl->cid].rhvm.vmid,
				me->channel[fl->cid].rhvm.vmperm,
				me->channel[fl->cid].rhvm.vmcount);
				hlosvm, 1, me->channel[cid].rhvm.vmid,
				me->channel[cid].rhvm.vmperm,
				me->channel[cid].rhvm.vmcount);
		if (err) {
			ADSPRPC_ERR(
				"rh hyp assign failed with %d for phys 0x%llx, size %zu\n",
@@ -4542,7 +4595,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
						size_t size, uint32_t flags)
{
	int err = 0;
	int err = 0, cid = -1;
	struct fastrpc_apps *me = &gfa;
	int tgid = 0;
	int destVM[1] = {VMID_HLOS};
@@ -4556,8 +4609,20 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
			uint8_t skey;
		} routargs;

		if (fl == NULL)
		if (!fl) {
			err = -EBADF;
			goto bail;
		}

		cid = fl->cid;
		VERIFY(err, VALID_FASTRPC_CID(cid));
		if (err) {
			err = -ECHRNG;
			ADSPRPC_ERR(
				"invalid channel 0x%zx set for session\n",
				cid);
			goto bail;
		}
		tgid = fl->tgid;
		ra[0].buf.pv = (void *)&tgid;
		ra[0].buf.len = sizeof(tgid);
@@ -4679,6 +4744,10 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl)
	struct fastrpc_apps *me = &gfa;
	int session = 0, err = 0, cid = -1;

	if (!fl) {
		err = -EBADF;
		goto bail;
	}
	err = fastrpc_get_spd_session(fl->servloc_name,
			&session, &cid);
	if (err)
@@ -4688,18 +4757,18 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl)
		err = -EBADR;
		goto bail;
	}
	if (!me->channel[fl->cid].spd[session].ispdup) {
	if (!me->channel[cid].spd[session].ispdup) {
		err = -ENOTCONN;
		goto bail;
	}
	if (me->channel[fl->cid].spd[session].pdrcount !=
		me->channel[fl->cid].spd[session].prevpdrcount) {
	if (me->channel[cid].spd[session].pdrcount !=
		me->channel[cid].spd[session].prevpdrcount) {
		err = fastrpc_mmap_remove_ssr(fl);
		if (err)
			ADSPRPC_WARN("failed to unmap remote heap (err %d)\n",
					err);
		me->channel[fl->cid].spd[session].prevpdrcount =
				me->channel[fl->cid].spd[session].pdrcount;
		me->channel[cid].spd[session].prevpdrcount =
				me->channel[cid].spd[session].pdrcount;
	}
bail:
	return err;
@@ -5246,7 +5315,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
	struct hlist_node *n = NULL;
	struct fastrpc_mmap *map = NULL, *lmap = NULL;
	unsigned long flags;
	int cid;
	int cid = -1, err = 0;

	if (!fl)
		return 0;
@@ -5305,6 +5374,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
	} while (lmap);
	mutex_unlock(&fl->map_mutex);

	VERIFY(err, VALID_FASTRPC_CID(cid));
	if (fl->sctx)
		fastrpc_session_free(&fl->apps->channel[cid], fl->sctx);
	if (fl->secsctx)