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

Commit 83f68ed0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: synx: Prevent accessing valid but released handles"

parents 631faf6b 0d292d11
Loading
Loading
Loading
Loading
+28 −16
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
 */
#define pr_fmt(fmt) "synx: " fmt

@@ -681,9 +681,9 @@ EXPORT_SYMBOL(synx_merge);
int synx_release(struct synx_session session_id, s32 h_synx)
{
	int rc = 0;
	u32 idx;
	struct synx_client *client;
	struct synx_handle_coredata *synx_data;
	struct synx_coredata *synx_obj;

	pr_debug("[sess: %u] Enter release from pid %d\n",
		session_id.client_id, current->pid);
@@ -692,21 +692,31 @@ int synx_release(struct synx_session session_id, s32 h_synx)
	if (!client)
		return -EINVAL;

	synx_data = synx_util_acquire_handle(client, h_synx);
	synx_obj = synx_util_obtain_object(synx_data);
	/* no need to check for fence here */
	if (!synx_obj) {
		pr_err("%s: [sess: %u] invalid handle access %d\n",
			__func__, client->id, h_synx);
		rc = -EINVAL;
		goto fail;
	}
	synx_data = NULL;
	idx = synx_util_handle_index(h_synx);

	mutex_lock(&client->synx_table_lock[idx]);
	synx_data = &client->synx_table[idx];
	if (!synx_data->synx_obj) {
		pr_err("[sess: %u] invalid object handle %d\n",
			client->id, h_synx);
	} else if (synx_data->handle != h_synx) {
		pr_err("[sess: %u] stale object handle %d\n",
			client->id, h_synx);
	} else if (synx_data->rel_count == 0) {
		pr_err("[sess: %u] released object handle %d\n",
			client->id, h_synx);
	} else if (!kref_read(&synx_data->internal_refcount)) {
		pr_err("[sess: %u] destroyed object handle %d\n",
			client->id, h_synx);
	} else {
		synx_data->rel_count--;
		/* release the reference obtained at synx creation */
	synx_util_release_handle(synx_data);
		kref_put(&synx_data->internal_refcount,
			synx_util_destroy_internal_handle);
	}
	mutex_unlock(&client->synx_table_lock[idx]);

fail:
	synx_util_release_handle(synx_data);
	synx_put_client(client);
	pr_debug("[sess: %u] exit release with status %d\n",
		session_id.client_id, rc);
@@ -953,8 +963,10 @@ int synx_addrefcount(struct synx_session session_id, s32 h_synx, s32 count)
	idx = synx_util_handle_index(h_synx);
	mutex_lock(&client->synx_table_lock[idx]);
	/* acquire additional references to handle */
	while (count--)
	while (count--) {
		synx_data->rel_count++;
		kref_get(&synx_data->internal_refcount);
	}
	mutex_unlock(&client->synx_table_lock[idx]);

fail:
+3 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
 */

#ifndef __SYNX_PRIVATE_H__
@@ -181,6 +181,7 @@ struct synx_device;
 * @import_refcount   : References for external clients for import
 * @id                : Synx object handle for the client
 * @key               : Key for import authentication
 * @rel_count         : No of allowed release counts
 */
struct synx_handle_coredata {
	struct synx_client *client;
@@ -189,6 +190,7 @@ struct synx_handle_coredata {
	struct kref import_refcount;
	u32 handle;
	u16 key;
	u32 rel_count;
};

/**
+4 −0
Original line number Diff line number Diff line
@@ -231,6 +231,7 @@ int synx_util_init_handle(struct synx_client *client,
	synx_data->handle = h_synx;
	synx_data->synx_obj = synx_obj;
	kref_init(&synx_data->internal_refcount);
	synx_data->rel_count = 1;
	mutex_unlock(&client->synx_table_lock[idx]);

	*new_synx = h_synx;
@@ -570,6 +571,9 @@ struct synx_handle_coredata *synx_util_acquire_handle(
	} else if (synx_data->handle != h_synx) {
		pr_err("[sess: %u] stale object handle %d\n",
			client->id, h_synx);
	} else if (synx_data->rel_count == 0) {
		pr_err("[sess: %u] released object handle %d\n",
			client->id, h_synx);
	} else if (!kref_read(&synx_data->internal_refcount)) {
		pr_err("[sess: %u] destroyed object handle %d\n",
			client->id, h_synx);