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

Commit 6f133308 authored by Trishansh Bhardwaj's avatar Trishansh Bhardwaj Committed by Alok Chauhan
Browse files

msm: camera: crm: Fix use-after-free for link



CRM gets link pointer from device private data and accesses it.
There is a chance that pointer gets deallocated while CRM is accessing
it. Static allocated memory will prevent use-after-free.

Change-Id: Ic339f0e569d2294a5adce14c8218cd55172d1ff9
Signed-off-by: default avatarTrishansh Bhardwaj <tbhardwa@codeaurora.org>
Signed-off-by: default avatarAlok Chauhan <alokc@codeaurora.org>
parent c88445d6
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];

static 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 = NULL;
	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)
{
@@ -1330,13 +1356,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) {
@@ -1344,8 +1374,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;
@@ -1400,9 +1428,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);
}

/**
@@ -2849,6 +2880,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) {
@@ -2865,6 +2897,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;
}

+4 −0
Original line number Diff line number Diff line
@@ -310,6 +310,8 @@ struct cam_req_mgr_connected_device {
 *                         frame in sync link as well.
 * @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 {
@@ -334,6 +336,8 @@ struct cam_req_mgr_core_link {
	bool                                 frame_skip_flag;
	bool                                 sync_link_sof_skip;
	int32_t                              open_req_cnt;
	uint32_t                             last_flush_id;
	atomic_t                             is_used;
};

/**