From a064a44e03158dbf655a866ba21f5d1baa2dee9e Mon Sep 17 00:00:00 2001 From: Dennis Cagle Date: Fri, 6 Jan 2017 15:28:20 -0800 Subject: [PATCH] QBT1000: copy qseecom handle to user when loading/unloading app QBT1000 provides IOCTLs for loading and unloading a QSEE app. In the input structure for these IOCTLs there is a pointer to a qseecom handle which serves as an output parameter for the IOCTLs. That is, the given handle (in client address space) should be set to a valid handle value on load, and should be set to 0 on unload. The driver was missing a proper copy_to_user() call for this handle, which sometimes resulted in unload not setting the handle to 0. Bug: 32372915 Bug: 32370896 CRs-fixed: 1059327 Change-Id: I31f205afb1f9bf0b6243e3f20f54022525c93b28 Signed-off-by: Lior Barenboim Signed-off-by: Dennis Cagle --- drivers/soc/qcom/qbt1000.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c index 101fcedd1f2c0..961800e2f963f 100755 --- a/drivers/soc/qcom/qbt1000.c +++ b/drivers/soc/qcom/qbt1000.c @@ -772,6 +772,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) case QBT1000_LOAD_APP: { struct qbt1000_app app; + struct qseecom_handle *app_handle; if (copy_from_user(&app, priv_arg, sizeof(app)) != 0) { @@ -782,8 +783,15 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) goto end; } + if (!app.app_handle) { + dev_err(drvdata->dev, "%s: LOAD app_handle is null\n", + __func__); + rc = -EINVAL; + goto end; + } + /* start the TZ app */ - rc = qseecom_start_app(app.app_handle, app.name, app.size); + rc = qseecom_start_app(&app_handle, app.name, app.size); if (rc == 0) { g_app_buf_size = app.size; } else { @@ -792,36 +800,79 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) goto end; } + /* copy the app handle to user */ + rc = copy_to_user((void __user *)app.app_handle, &app_handle, + sizeof(*app.app_handle)); + + if (rc != 0) { + dev_err(drvdata->dev, + "%s: Failed copy 2us LOAD rc:%d\n", + __func__, rc); + rc = -ENOMEM; + goto end; + } + break; } case QBT1000_UNLOAD_APP: { struct qbt1000_app app; + struct qseecom_handle *app_handle; if (copy_from_user(&app, priv_arg, sizeof(app)) != 0) { rc = -ENOMEM; dev_err(drvdata->dev, - "%s: Failed copy from user space-LOAD\n", + "%s: Failed copy from user space-UNLOAD\n", __func__); goto end; } - /* if the app hasn't been loaded already, return err */ if (!app.app_handle) { + dev_err(drvdata->dev, "%s: UNLOAD app_handle is null\n", + __func__); + rc = -EINVAL; + goto end; + } + + rc = copy_from_user(&app_handle, app.app_handle, + sizeof(app_handle)); + + if (rc != 0) { + dev_err(drvdata->dev, + "%s: Failed copy from user space-UNLOAD handle rc:%d\n", + __func__, rc); + rc = -ENOMEM; + goto end; + } + + /* if the app hasn't been loaded already, return err */ + if (!app_handle) { dev_err(drvdata->dev, "%s: App not loaded\n", __func__); rc = -EINVAL; goto end; } - rc = qseecom_shutdown_app(app.app_handle); + rc = qseecom_shutdown_app(&app_handle); if (rc != 0) { dev_err(drvdata->dev, "%s: App failed to shutdown\n", __func__); goto end; } + /* copy the app handle (should be null) to user */ + rc = copy_to_user((void __user *)app.app_handle, &app_handle, + sizeof(*app.app_handle)); + + if (rc != 0) { + dev_err(drvdata->dev, + "%s: Failed copy 2us UNLOAD rc:%d\n", + __func__, rc); + rc = -ENOMEM; + goto end; + } + break; } case QBT1000_SEND_TZCMD: