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

Commit e47d921a 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 58114830
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -378,7 +378,7 @@ struct qseecom_client_handle {

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

@@ -1550,6 +1550,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");
@@ -1559,6 +1564,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) {
@@ -1602,13 +1614,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);