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

Commit 30b32197 authored by Suresh Vankadara's avatar Suresh Vankadara Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: crm: Fix use-after-free for link" into dev/msm-4.14-camx

parents d2c3c181 42492609
Loading
Loading
Loading
Loading
+47 −9
Original line number Diff line number Diff line
@@ -24,6 +24,32 @@
#include "cam_req_mgr_dev.h"

static struct cam_req_mgr_core_device *g_crm_core_dev;
static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];

void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
{
	link->link_hdl = 0;
	link->num_devs = 0;
	link->max_delay = CAM_PIPELINE_DELAY_0;
	link->workq = NULL;
	link->pd_mask = 0;
	link->l_dev = NULL;
	link->req.in_q = NULL;
	link->req.l_tbl = NULL;
	link->req.num_tbl = 0;
	link->watchdog = NULL;
	link->state = CAM_CRM_LINK_STATE_AVAILABLE;
	link->parent = NULL;
	link->subscribe_event = 0;
	link->trigger_mask = 0;
	link->sync_link = 0;
	link->sof_counter = 0;
	link->sync_self_ref = 0;
	link->frame_skip_flag = false;
	link->sync_link_sof_skip = false;
	link->open_req_cnt = 0;
	link->last_flush_id = 0;
}

void cam_req_mgr_handle_core_shutdown(void)
{
@@ -1344,13 +1370,17 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
			session->num_links, MAXIMUM_LINKS_PER_SESSION);
		return NULL;
	}

	link = (struct cam_req_mgr_core_link *)
		kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
	if (!link) {
		CAM_ERR(CAM_CRM, "failed to create link, no mem");
		return NULL;
	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
		if (!atomic_cmpxchg(&g_links[i].is_used, 0, 1)) {
			link = &g_links[i];
			CAM_DBG(CAM_CRM, "alloc link index %d", i);
			cam_req_mgr_core_link_reset(link);
			break;
		}
	}
	if (i == MAXIMUM_LINKS_PER_SESSION)
		return NULL;

	in_q = (struct cam_req_mgr_req_queue *)
		kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
	if (!in_q) {
@@ -1358,8 +1388,6 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
		kfree(link);
		return NULL;
	}
	mutex_init(&link->lock);
	spin_lock_init(&link->link_state_spin_lock);

	mutex_lock(&link->lock);
	link->state = CAM_CRM_LINK_STATE_AVAILABLE;
@@ -1414,9 +1442,12 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
 */
static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
{
	ptrdiff_t i;
	kfree(link->req.in_q);
	link->req.in_q = NULL;
	kfree(link);
	i = link - g_links;
	CAM_DBG(CAM_CRM, "free link index %d", i);
	atomic_set(&g_links[i].is_used, 0);
}

/**
@@ -2875,6 +2906,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)

int cam_req_mgr_core_device_init(void)
{
	int i;
	CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);

	if (g_crm_core_dev) {
@@ -2891,6 +2923,12 @@ int cam_req_mgr_core_device_init(void)
	mutex_init(&g_crm_core_dev->crm_lock);
	cam_req_mgr_debug_register(g_crm_core_dev);

	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
		mutex_init(&g_links[i].lock);
		spin_lock_init(&g_links[i].link_state_spin_lock);
		atomic_set(&g_links[i].is_used, 0);
		cam_req_mgr_core_link_reset(&g_links[i]);
	}
	return 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -318,6 +318,7 @@ struct cam_req_mgr_connected_device {
 * @open_req_cnt         : Counter to keep track of open requests that are yet
 *                         to be serviced in the kernel.
 * @last_flush_id        : Last request to flush
 * @is_used              : 1 if link is in use else 0
 *
 */
struct cam_req_mgr_core_link {
@@ -343,6 +344,7 @@ struct cam_req_mgr_core_link {
	bool                                 sync_link_sof_skip;
	int32_t                              open_req_cnt;
	uint32_t                             last_flush_id;
	atomic_t                             is_used;
};

/**