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

Commit df065bdd authored by Tharun Kumar Merugu's avatar Tharun Kumar Merugu
Browse files

msm: adsprpc: protect the global remote heap buffer list



Protect global remote heap buffer list using spin locks. Validate
buffer before cache flush. Invoke remote process release only when
the context and subsystem status are valid and log the process
release error only if process init was successful. Fail I/O
requests during static PD restart. Log all hyp assign failures.

Change-Id: I20f12ba00ed33c2534faf107d7ca1cbb3695f50a
Acked-by: default avatarThyagarajan Venkatanarayanan <venkatan@qti.qualcomm.com>
Signed-off-by: default avatarTharun Kumar Merugu <mtharu@codeaurora.org>
parent 84606f73
Loading
Loading
Loading
Loading
+76 −13
Original line number Diff line number Diff line
@@ -379,6 +379,7 @@ struct fastrpc_file {
	int pd;
	char *servloc_name;
	int file_close;
	int dsp_process_init;
	struct fastrpc_apps *apps;
	struct hlist_head perf;
	struct dentry *debugfs_file;
@@ -581,7 +582,9 @@ static void fastrpc_mmap_add(struct fastrpc_mmap *map)
				map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
		struct fastrpc_apps *me = &gfa;

		spin_lock(&me->hlock);
		hlist_add_head(&map->hn, &me->maps);
		spin_unlock(&me->hlock);
	} else {
		struct fastrpc_file *fl = map->fl;

@@ -601,6 +604,7 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
		return -EOVERFLOW;
	if (mflags == ADSP_MMAP_HEAP_ADDR ||
				 mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
		spin_lock(&me->hlock);
		hlist_for_each_entry_safe(map, n, &me->maps, hn) {
			if (va >= map->va &&
				va + len <= map->va + map->len &&
@@ -611,6 +615,7 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
				break;
			}
		}
		spin_unlock(&me->hlock);
	} else {
		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
			if (va >= map->va &&
@@ -656,6 +661,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
	struct hlist_node *n;
	struct fastrpc_apps *me = &gfa;

	spin_lock(&me->hlock);
	hlist_for_each_entry_safe(map, n, &me->maps, hn) {
		if (map->raddr == va &&
			map->raddr + map->len == va + len &&
@@ -665,6 +671,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va,
			break;
		}
	}
	spin_unlock(&me->hlock);
	if (match) {
		*ppmap = match;
		return 0;
@@ -1609,7 +1616,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)

		if (rpra && lrpra && rpra[i].buf.len &&
			ctx->overps[oix]->mstart) {
			if (map && map->handle) {
			if (map && map->buf) {
				dma_buf_begin_cpu_access(map->buf,
					DMA_BIDIRECTIONAL);
				dma_buf_end_cpu_access(map->buf,
@@ -1715,7 +1722,7 @@ static void inv_args_pre(struct smq_invoke_ctx *ctx)
			continue;
		if (!IS_CACHE_ALIGNED((uintptr_t)
				uint64_to_ptr(rpra[i].buf.pv))) {
			if (map && map->handle) {
			if (map && map->buf) {
				dma_buf_begin_cpu_access(map->buf,
					DMA_BIDIRECTIONAL);
				dma_buf_end_cpu_access(map->buf,
@@ -1729,7 +1736,7 @@ static void inv_args_pre(struct smq_invoke_ctx *ctx)
		end = (uintptr_t)uint64_to_ptr(rpra[i].buf.pv +
							rpra[i].buf.len);
		if (!IS_CACHE_ALIGNED(end)) {
			if (map && map->handle) {
			if (map && map->buf) {
				dma_buf_begin_cpu_access(map->buf,
					DMA_BIDIRECTIONAL);
				dma_buf_end_cpu_access(map->buf,
@@ -2216,18 +2223,28 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
			goto bail;
	} else {
		err = -ENOTTY;
		goto bail;
	}
	fl->dsp_process_init = 1;
bail:
	kfree(proc_name);
	if (err && (init->flags == FASTRPC_INIT_CREATE_STATIC))
		me->staticpd_flags = 0;
	if (mem && err) {
		if (mem->flags == ADSP_MMAP_REMOTE_HEAP_ADDR
			&& me->channel[fl->cid].rhvm.vmid && rh_hyp_done)
			hyp_assign_phys(mem->phys, (uint64_t)mem->size,
			&& me->channel[fl->cid].rhvm.vmid && rh_hyp_done) {
			int hyp_err = 0;

			hyp_err = hyp_assign_phys(mem->phys,
					(uint64_t)mem->size,
					me->channel[fl->cid].rhvm.vmid,
					me->channel[fl->cid].rhvm.vmcount,
					hlosvm, hlosvmperm, 1);
			if (hyp_err)
				pr_warn("adsprpc: %s: %s: rh hyp unassign failed with %d for phys 0x%llx of size %zd\n",
						__func__, current->comm,
						hyp_err, mem->phys, mem->size);
		}
		mutex_lock(&fl->map_mutex);
		fastrpc_mmap_free(mem, 0);
		mutex_unlock(&fl->map_mutex);
@@ -2378,9 +2395,15 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
	int tgid = 0;

	VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS);
	if (err)
		goto bail;
	VERIFY(err, fl->sctx != NULL);
	if (err)
		goto bail;
	VERIFY(err, fl->apps->channel[fl->cid].rpdev != NULL);
	if (err)
		goto bail;
	VERIFY(err, fl->apps->channel[fl->cid].issubsystemup == 1);
	if (err)
		goto bail;
	tgid = fl->tgid;
@@ -2394,6 +2417,9 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
	ioctl.crc = NULL;
	VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
		FASTRPC_MODE_PARALLEL, 1, &ioctl)));
	if (err && fl->dsp_process_init)
		pr_err("adsprpc: %s: releasing DSP process failed with %d (0x%x) for %s\n",
				__func__, err, err, current->comm);
bail:
	return err;
}
@@ -2452,9 +2478,13 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
				hlosvm, 1, me->channel[fl->cid].rhvm.vmid,
				me->channel[fl->cid].rhvm.vmperm,
				me->channel[fl->cid].rhvm.vmcount);
		if (err)
		if (err) {
			pr_err("adsprpc: %s: %s: rh hyp assign failed with %d for phys 0x%llx, size %zd\n",
					__func__, current->comm,
					err, phys, size);
			goto bail;
		}
	}
bail:
	return err;
}
@@ -2503,10 +2533,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
					me->channel[fl->cid].rhvm.vmid,
					me->channel[fl->cid].rhvm.vmcount,
					destVM, destVMperm, 1);
			if (err)
			if (err) {
				pr_err("adsprpc: %s: %s: rh hyp unassign failed with %d for phys 0x%llx, size %zd\n",
					__func__, current->comm,
					err, phys, size);
				goto bail;
			}
		}
	}

bail:
	return err;
@@ -2620,8 +2654,8 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl)
		me->channel[fl->cid].spd[session].prevpdrcount) {
		err = fastrpc_mmap_remove_ssr(fl);
		if (err)
			pr_err("adsprpc: %s: SSR: failed to unmap remote heap (err %d)\n",
					__func__, err);
			pr_warn("adsprpc: %s: %s: failed to unmap remote heap (err %d)\n",
					__func__, current->comm, err);
		me->channel[fl->cid].spd[session].prevpdrcount =
				me->channel[fl->cid].spd[session].pdrcount;
	}
@@ -3284,7 +3318,6 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
	struct fastrpc_apps *me = &gfa;
	int cid, err = 0;


	VERIFY(err, fl && fl->sctx);
	if (err)
		goto bail;
@@ -3316,9 +3349,11 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
	if (cid == ADSP_DOMAIN_ID && me->channel[cid].ssrcount !=
			 me->channel[cid].prevssrcount) {
		mutex_lock(&fl->map_mutex);
		if (fastrpc_mmap_remove_ssr(fl))
			pr_err("adsprpc: %s: SSR: Failed to unmap remote heap for %s\n",
				__func__, me->channel[cid].name);
		err = fastrpc_mmap_remove_ssr(fl);
		if (err)
			pr_warn("adsprpc: %s: %s: failed to unmap remote heap for %s (err %d)\n",
					__func__, current->comm,
					me->channel[cid].subsys, err);
		mutex_unlock(&fl->map_mutex);
		me->channel[cid].prevssrcount =
					me->channel[cid].ssrcount;
@@ -3385,6 +3420,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
		fl->debugfs_file = debugfs_file;
	memset(&fl->perf, 0, sizeof(fl->perf));
	fl->qos_request = 0;
	fl->dsp_process_init = 0;
	filp->private_data = fl;
	mutex_init(&fl->internal_map_mutex);
	mutex_init(&fl->map_mutex);
@@ -3477,6 +3513,25 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
	return err;
}

static int fastrpc_check_pd_status(struct fastrpc_file *fl, char *sloc_name)
{
	int err = 0, session = -1, cid = -1;
	struct fastrpc_apps *me = &gfa;

	if (fl->servloc_name && sloc_name
		&& !strcmp(fl->servloc_name, sloc_name)) {
		err = fastrpc_get_spd_session(sloc_name, &session, &cid);
		if (err || cid != fl->cid)
			goto bail;
		if (!me->channel[cid].spd[session].ispdup) {
			err = -ENOTCONN;
			goto bail;
		}
	}
bail:
	return err;
}

static int fastrpc_setmode(unsigned long ioctl_param,
				struct fastrpc_file *fl)
{
@@ -3612,6 +3667,14 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
	p.inv.fds = NULL;
	p.inv.attrs = NULL;
	p.inv.crc = NULL;

	err = fastrpc_check_pd_status(fl,
			AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME);
	err |= fastrpc_check_pd_status(fl,
			SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME);
	if (err)
		goto bail;

	spin_lock(&fl->hlock);
	if (fl->file_close == 1) {
		err = EBADF;