securemsm-kernel: Fixed multiple listener registration on same fd
Added check to prevent more than one listener registration
on a fd. This could lead to potential vulnerabilities of use
after free while unregistering the listener.
Issue: FP3SEC-1619
Change-Id: Ia2973853943b5619bcf2047629b9c193f6a8c5cf
Signed-off-by: Pawan Rai <quic_pawarai@quicinc.com>
Signed-off-by: Ravi Kumar Bokka <quic_c_rbokka@quicinc.com>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index e0386cbc..9a2b56d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -353,7 +353,7 @@ struct qseecom_client_handle {
struct qseecom_listener_handle {
u32 id;
- bool unregister_pending;
+ bool register_pending;
bool release_called;
};
@@ -1233,6 +1233,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");
@@ -1242,6 +1247,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 == false) {
@@ -1276,12 +1288,15 @@ 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);
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);