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

Commit 1c307a4d authored by Ravi Kumar Bokka's avatar Ravi Kumar Bokka Committed by Ravi Kuamr Bokka
Browse files

securemsm-kernel: Fix multiple listener registration on same fd



Currently, multiple listeners can register on same fd which
could lead to potential vulnerabilities of use after free
while unregistering the listener. Add check to prevent more
than one listener registration on a fd.

Change-Id: Ia2973853943b5619bcf2047629b9c193f6a8c5cf
Signed-off-by: default avatarPawan Rai <quic_pawarai@quicinc.com>
Signed-off-by: default avatarRavi Kumar Bokka <quic_c_rbokka@quicinc.com>
parent 80aaf7bb
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * QTI Secure Execution Environment Communicator (QSEECOM) driver
 *
 * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#define pr_fmt(fmt) "QSEECOM: %s: " fmt, __func__
@@ -375,7 +375,7 @@ struct qseecom_client_handle {

struct qseecom_listener_handle {
	u32               id;
	bool              unregister_pending;
	bool              register_pending;
	bool              release_called;
};

@@ -1525,6 +1525,11 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
	struct qseecom_registered_listener_list *new_entry;
	struct qseecom_registered_listener_list *ptr_svc;

	if (data->listener.register_pending) {
		pr_err("Already a listner registration is in process on this FD\n");
		return -EINVAL;
	}

	ret = copy_from_user(&rcvd_lstnr, argp, sizeof(rcvd_lstnr));
	if (ret) {
		pr_err("copy_from_user failed\n");
@@ -1534,6 +1539,13 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
			rcvd_lstnr.sb_size))
		return -EFAULT;

	ptr_svc = __qseecom_find_svc(data->listener.id);
	if (ptr_svc) {
		pr_err("Already a listener registered on this data: lid=%d\n",
			data->listener.id);
		return -EINVAL;
	}

	ptr_svc = __qseecom_find_svc(rcvd_lstnr.listener_id);
	if (ptr_svc) {
		if (!ptr_svc->unregister_pending) {
@@ -1577,13 +1589,16 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
	new_entry->svc.listener_id = rcvd_lstnr.listener_id;
	new_entry->sb_length = rcvd_lstnr.sb_size;
	new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base;
	data->listener.register_pending = true;
	if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
		pr_err("qseecom_set_sb_memory failed for listener %d, size %d\n",
				rcvd_lstnr.listener_id, rcvd_lstnr.sb_size);
		__qseecom_free_tzbuf(&new_entry->sglistinfo_shm);
		kzfree(new_entry);
		data->listener.register_pending = false;
		return -ENOMEM;
	}
	data->listener.register_pending = false;

	init_waitqueue_head(&new_entry->rcv_req_wq);
	init_waitqueue_head(&new_entry->listener_block_app_wq);