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

Commit cc717b29 authored by Maheshwar Ajja's avatar Maheshwar Ajja
Browse files

msm: vidc: Fix corruption in bus vote



msm_comm_vote_bus() calculates and prepares core->vote_data
structure under core->lock for all instances and sets the
prepared vote_data to hfi layer after releasing core->lock.
There is a possibility that this prepared vote_data can be
corrupted while hfi layer accessesing it if msm_comm_vote_bus()
is called by another instance in parallel. Fix the issue
by allocating a new vote_data structure for every call to
msm_comm_vote_bus() function.

Change-Id: I502027054d994ee8144a8505c47954a1f1e06be4
Signed-off-by: default avatarMaheshwar Ajja <majja@codeaurora.org>
parent ad957023
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -364,13 +364,6 @@ static int msm_vidc_initialize_core(struct platform_device *pdev,
	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
	INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);

	mutex_lock(&core->lock);
	core->vote_data = kcalloc(MAX_SUPPORTED_INSTANCES,
		sizeof(*core->vote_data), GFP_KERNEL);
	if (!core->vote_data)
		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
	mutex_unlock(&core->lock);

	msm_vidc_init_core_clk_ops(core);
	return rc;
}
@@ -764,7 +757,6 @@ static int msm_vidc_remove(struct platform_device *pdev)
	v4l2_device_unregister(&core->v4l2_dev);

	msm_vidc_free_platform_resources(&core->resources);
	kfree(core->vote_data);
	sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
	dev_set_drvdata(&pdev->dev, NULL);
	mutex_destroy(&core->lock);
+13 −8
Original line number Diff line number Diff line
@@ -194,19 +194,23 @@ int msm_comm_vote_bus(struct msm_vidc_core *core)
		dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core);
		return -EINVAL;
	}

	hdev = core->device;

	mutex_lock(&core->lock);
	vote_data = core->vote_data;
	vote_data = kzalloc(sizeof(struct vidc_bus_vote_data) *
			MAX_SUPPORTED_INSTANCES, GFP_ATOMIC);
	if (!vote_data) {
		dprintk(VIDC_PROF,
			"Failed to get vote_data for inst %pK\n",
				inst);
		mutex_unlock(&core->lock);
		dprintk(VIDC_DBG,
			"vote_data allocation with GFP_ATOMIC failed\n");
		vote_data = kzalloc(sizeof(struct vidc_bus_vote_data) *
			MAX_SUPPORTED_INSTANCES, GFP_KERNEL);
		if (!vote_data) {
			dprintk(VIDC_DBG,
				"vote_data allocation failed\n");
			return -EINVAL;
		}
	}

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		int codec = 0;
		struct msm_vidc_buffer *temp, *next;
@@ -328,6 +332,7 @@ int msm_comm_vote_bus(struct msm_vidc_core *core)
		rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data,
			vote_data, vote_data_count);

	kfree(vote_data);
	return rc;
}

+0 −1
Original line number Diff line number Diff line
@@ -396,7 +396,6 @@ struct msm_vidc_core {
	bool trigger_ssr;
	unsigned long min_freq;
	unsigned long curr_freq;
	struct vidc_bus_vote_data *vote_data;
	struct msm_vidc_core_ops *core_ops;
};