From a1124defc680055e2f2a8c8e3da4a94ca2ec842e Mon Sep 17 00:00:00 2001 From: Mona Hossain Date: Tue, 1 Oct 2013 13:41:09 -0700 Subject: qseecom: Add checks for API called in IOCTL Validate the caller is the right type for the IOCTL being issued and inputs are valid. Change-Id: Iad71f0f5ed4d53c5d011bd55cdf74ec053d09af5 Signed-off-by: Mona Hossain Signed-off-by: Hariprasad Dhalinarasimha --- drivers/misc/qseecom.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 159 insertions(+), 6 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 7cc1c9f..51f0228 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -434,6 +434,12 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, if (copy_from_user(&req, (void __user *)argp, sizeof(req))) return -EFAULT; + if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == 0) || + (req.sb_len == 0)) { + pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%x)\n", + req.ifd_data_fd, req.sb_len, req.virt_sb_base); + return -EFAULT; + } /* Get the handle of the shared fd */ data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt, req.ifd_data_fd); @@ -2680,6 +2686,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, switch (cmd) { case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("reg lstnr req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } pr_debug("ioctl register_listener_req()\n"); atomic_inc(&data->ioctl_count); data->type = QSEECOM_LISTENER_SERVICE; @@ -2691,6 +2703,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: { + if ((data->listener.id == 0) || + (data->type != QSEECOM_LISTENER_SERVICE)) { + pr_err("unreg lstnr req: invalid handle (%d) lid(%d)\n", + data->type, data->listener.id); + ret = -EINVAL; + break; + } pr_debug("ioctl unregister_listener_req()\n"); atomic_inc(&data->ioctl_count); ret = qseecom_unregister_listener(data); @@ -2701,6 +2720,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SEND_CMD_REQ: { + if ((data->client.app_id == 0) || + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("send cmd req: invalid handle (%d) app_id(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } /* Only one client allowed here at a time */ mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2713,6 +2739,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: { + if ((data->client.app_id == 0) || + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } /* Only one client allowed here at a time */ mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2725,6 +2758,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_RECEIVE_REQ: { + if ((data->listener.id == 0) || + (data->type != QSEECOM_LISTENER_SERVICE)) { + pr_err("receive req: invalid handle (%d), lid(%d)\n", + data->type, data->listener.id); + ret = -EINVAL; + break; + } atomic_inc(&data->ioctl_count); ret = qseecom_receive_req(data); atomic_dec(&data->ioctl_count); @@ -2734,6 +2774,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SEND_RESP_REQ: { + if ((data->listener.id == 0) || + (data->type != QSEECOM_LISTENER_SERVICE)) { + pr_err("send resp req: invalid handle (%d), lid(%d)\n", + data->type, data->listener.id); + ret = -EINVAL; + break; + } atomic_inc(&data->ioctl_count); ret = qseecom_send_resp(); atomic_dec(&data->ioctl_count); @@ -2743,7 +2790,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: { - data->type = QSEECOM_CLIENT_APP; + if ((data->type != QSEECOM_CLIENT_APP) && + (data->type != QSEECOM_GENERIC) && + (data->type != QSEECOM_SECURE_SERVICE)) { + pr_err("set mem param req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } pr_debug("SET_MEM_PARAM: qseecom addr = 0x%x\n", (u32)data); ret = qseecom_set_client_mem_param(data, argp); if (ret) @@ -2752,6 +2806,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_LOAD_APP_REQ: { + if ((data->type != QSEECOM_GENERIC) && + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("load app req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->type = QSEECOM_CLIENT_APP; pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%x\n", (u32)data); mutex_lock(&app_access_lock); @@ -2772,6 +2833,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_UNLOAD_APP_REQ: { + if ((data->client.app_id == 0) || + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("unload app req:invalid handle(%d) app_id(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data); mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2791,6 +2859,20 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_PERF_ENABLE_REQ:{ + if ((data->type != QSEECOM_GENERIC) && + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("perf enable req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } + if ((data->type == QSEECOM_CLIENT_APP) && + (data->client.app_id == 0)) { + pr_err("perf enable req:invalid handle(%d) appid(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } atomic_inc(&data->ioctl_count); ret = qsee_vote_for_clock(data, CLK_DFAB); if (ret) @@ -2802,13 +2884,33 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_PERF_DISABLE_REQ:{ + if ((data->type != QSEECOM_SECURE_SERVICE) && + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("perf disable req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } + if ((data->type == QSEECOM_CLIENT_APP) && + (data->client.app_id == 0)) { + pr_err("perf disable: invalid handle (%d)app_id(%d)\n", + data->type, data->client.app_id); + ret = -EINVAL; + break; + } atomic_inc(&data->ioctl_count); - qsee_disable_clock_vote(data, CLK_DFAB); - qsee_disable_clock_vote(data, CLK_SFPB); + qsee_disable_clock_vote(data, CLK_DFAB); + qsee_disable_clock_vote(data, CLK_SFPB); atomic_dec(&data->ioctl_count); break; } case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("load ext elf req: invalid client handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->type = QSEECOM_UNAVAILABLE_CLIENT_APP; data->released = true; mutex_lock(&app_access_lock); @@ -2821,6 +2923,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: { + if (data->type != QSEECOM_UNAVAILABLE_CLIENT_APP) { + pr_err("unload ext elf req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->released = true; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2842,9 +2950,15 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("send cmd svc req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->type = QSEECOM_SECURE_SERVICE; if (qseecom.qsee_version < QSEE_VERSION_03) { - pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n", + pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee ver %u\n", qseecom.qsee_version); return -EINVAL; } @@ -2856,8 +2970,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_CREATE_KEY_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("create key req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } if (qseecom.qsee_version < QSEE_VERSION_05) { - pr_err("Create Key feature not supported in qsee version %u\n", + pr_err("Create Key feature unsupported: qsee ver %u\n", qseecom.qsee_version); return -EINVAL; } @@ -2873,8 +2993,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_WIPE_KEY_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("wipe key req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } if (qseecom.qsee_version < QSEE_VERSION_05) { - pr_err("Wipe Key feature not supported in qsee version %u\n", + pr_err("Wipe Key feature unsupported in qsee ver %u\n", qseecom.qsee_version); return -EINVAL; } @@ -2889,6 +3015,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("save part hash req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->released = true; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2898,6 +3030,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: { + if (data->type != QSEECOM_GENERIC) { + pr_err("ES activated req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->released = true; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); @@ -2907,6 +3045,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_SEND_MODFD_RESP: { + if ((data->listener.id == 0) || + (data->type != QSEECOM_LISTENER_SERVICE)) { + pr_err("receive req: invalid handle (%d), lid(%d)\n", + data->type, data->listener.id); + ret = -EINVAL; + break; + } /* Only one client allowed here at a time */ atomic_inc(&data->ioctl_count); ret = qseecom_send_modfd_resp(data, argp); @@ -2917,6 +3062,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } case QSEECOM_IOCTL_UNPROTECT_BUF: { + if ((data->listener.id == 0) || + (data->type != QSEECOM_LISTENER_SERVICE)) { + pr_err("receive req: invalid handle (%d), lid(%d)\n", + data->type, data->listener.id); + ret = -EINVAL; + break; + } /* Only one client allowed here at a time */ atomic_inc(&data->ioctl_count); ret = qseecom_unprotect_buffer(argp); @@ -2927,6 +3079,7 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, break; } default: + pr_err("Invalid IOCTL: %d\n", cmd); return -EINVAL; } return ret; -- cgit v1.1