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

Commit 91ee18bf authored by Ayush Kumar's avatar Ayush Kumar
Browse files

msm: camera: core: Fix context release timing issue



When sync object is invalid and num_in_map > 1,
it will lead to context ref leak. Check sync
object first, then register sync call back.

Change-Id: I3418083c9f32ae0d7a9797d3e84dfda0a21385ee
Signed-off-by: default avatarAyush Kumar <ayushkr@codeaurora.org>
parent c4ff1eba
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -385,6 +385,17 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
				"[%s][%d] : Moving req[%llu] from free_list to pending_list",
				ctx->dev_name, ctx->ctx_id, req->request_id);

		for (j = 0; j < req->num_in_map_entries; j++) {
			rc = cam_sync_check_valid(
				req->in_map_entries[j].sync_id);
			if (rc) {
				CAM_ERR(CAM_CTXT,
					"invalid in map sync object %d",
					req->in_map_entries[j].sync_id);
				goto put_ref;
			}
		}

		for (j = 0; j < req->num_in_map_entries; j++) {
			cam_context_getref(ctx);
			rc = cam_sync_register_callback(
+36 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -279,6 +279,7 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
	int rc;
	long idx = 0;
	bool bit;
	int i = 0;

	if (!sync_obj || !merged_obj) {
		CAM_ERR(CAM_SYNC, "Invalid pointer(s)");
@@ -296,6 +297,15 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
		return -EINVAL;
	}

	for (i = 0; i < num_objs; i++) {
		rc = cam_sync_check_valid(sync_obj[i]);
		if (rc) {
			CAM_ERR(CAM_SYNC, "Sync_obj[%d] %d valid check fail",
				i, sync_obj[i]);
			return rc;
		}
	}

	do {
		idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
		if (idx >= CAM_SYNC_MAX_OBJS)
@@ -367,6 +377,31 @@ int cam_sync_destroy(int32_t sync_obj)
	return cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
}

int cam_sync_check_valid(int32_t sync_obj)
{
	struct sync_table_row *row = NULL;

	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
		return -EINVAL;

	row = sync_dev->sync_table + sync_obj;

	if (!test_bit(sync_obj, sync_dev->bitmap)) {
		CAM_ERR(CAM_SYNC, "Error: Released sync obj received %d",
			sync_obj);
		return -EINVAL;
	}

	if (row->state == CAM_SYNC_STATE_INVALID) {
		CAM_ERR(CAM_SYNC,
			"Error: accessing an uninitialized sync obj = %d",
			sync_obj);
		return -EINVAL;
	}

	return 0;
}

int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms)
{
	unsigned long timeleft;
+10 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -147,5 +147,14 @@ int cam_sync_destroy(int32_t sync_obj);
 */
int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms);

/**
 * @brief: Check if sync object is valid
 *
 * @param sync_obj: int referencing the sync object to be checked
 *
 * @return 0 upon success, -EINVAL if sync object is in bad state or arguments
 * are invalid
 */
int cam_sync_check_valid(int32_t sync_obj);

#endif /* __CAM_SYNC_API_H__ */