From c83a067a9a82010e5b1b7685ca9720e9c27a52a7 Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Tue, 7 Feb 2017 17:15:54 -0800 Subject: [PATCH] qseecom: return app_id correctly when looking up and loading app When __qseecom_check_app_exsits() and __qseecom_load_fw() get app_id from TZ, they save it to function's return value then return back. But "app_id" is of type uint32, "ret" is int32, this will return incorrect app_id to the caller if app_id is larger than 0x7FFFFFFF. Thus make change to return app_id correctly. Change-Id: I2ef98d64490c480d5416ee24ec6ca9aca9c8ca8a Signed-off-by: Zhen Kong --- drivers/misc/compat_qseecom.c | 6 ++-- drivers/misc/compat_qseecom.h | 4 +-- drivers/misc/qseecom.c | 67 +++++++++++++++++++++-------------- include/uapi/linux/qseecom.h | 4 +-- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/drivers/misc/compat_qseecom.c b/drivers/misc/compat_qseecom.c index 60bb86a08af7..2e9ffc71e452 100644 --- a/drivers/misc/compat_qseecom.c +++ b/drivers/misc/compat_qseecom.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -52,7 +52,7 @@ static int compat_get_qseecom_load_img_req( compat_ulong_t img_len; compat_long_t ifd_data_fd; compat_ulong_t app_arch; - compat_int_t app_id; + compat_uint_t app_id; err = get_user(mdt_len, &data32->mdt_len); err |= put_user(mdt_len, &data->mdt_len); @@ -164,7 +164,7 @@ static int compat_get_qseecom_qseos_app_load_query( { int err = 0; unsigned int i; - compat_int_t app_id; + compat_uint_t app_id; char app_name; compat_ulong_t app_arch; diff --git a/drivers/misc/compat_qseecom.h b/drivers/misc/compat_qseecom.h index 5167bf1cc6af..c934ef87e20a 100644 --- a/drivers/misc/compat_qseecom.h +++ b/drivers/misc/compat_qseecom.h @@ -93,7 +93,7 @@ struct compat_qseecom_load_img_req { compat_long_t ifd_data_fd; /* in */ char img_name[MAX_APP_NAME_SIZE]; /* in */ compat_ulong_t app_arch; /* in */ - compat_int_t app_id; /* out*/ + compat_uint_t app_id; /* out*/ }; struct compat_qseecom_set_sb_mem_param_req { @@ -117,7 +117,7 @@ struct compat_qseecom_qseos_version_req { */ struct compat_qseecom_qseos_app_load_query { char app_name[MAX_APP_NAME_SIZE]; /* in */ - compat_int_t app_id; /* out */ + compat_uint_t app_id; /* out */ compat_ulong_t app_arch; }; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 8d03c36858b3..78f03fc75761 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -2167,7 +2167,8 @@ static void __qseecom_reentrancy_check_if_this_app_blocked( } } -static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req) +static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req, + uint32_t *app_id) { int32_t ret; struct qseecom_command_scm_resp resp; @@ -2175,6 +2176,12 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req) struct qseecom_registered_app_list *entry = NULL; unsigned long flags = 0; + if (!app_id) { + pr_err("Null pointer to app_id\n"); + return -EINVAL; + } + *app_id = 0; + /* check if app exists and has been registered locally */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(entry, @@ -2187,7 +2194,8 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req) spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags); if (found_app) { pr_debug("Found app with id %d\n", entry->app_id); - return entry->app_id; + *app_id = entry->app_id; + return 0; } memset((void *)&resp, 0, sizeof(resp)); @@ -2210,7 +2218,8 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req) pr_err("resp type is of listener type instead of app"); return -EINVAL; case QSEOS_APP_ID: - return resp.data; + *app_id = resp.data; + return 0; default: pr_err("invalid resp type (%d) from qsee", resp.resp_type); @@ -2286,11 +2295,10 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0'; strlcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE); - ret = __qseecom_check_app_exists(req); + ret = __qseecom_check_app_exists(req, &app_id); if (ret < 0) goto loadapp_err; - app_id = ret; if (app_id) { pr_debug("App id %d (%s) already exists\n", app_id, (char *)(req.app_name)); @@ -4038,7 +4046,8 @@ static void __qseecom_free_img_data(struct ion_handle **ihandle) *ihandle = NULL; } -static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) +static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname, + uint32_t *app_id) { int ret = -1; uint32_t fw_size = 0; @@ -4052,6 +4061,11 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) size_t cmd_len; uint32_t app_arch = 0; + if (!data || !appname || !app_id) { + pr_err("Null pointer to data or appname or appid\n"); + return -EINVAL; + } + *app_id = 0; if (__qseecom_get_fw_size(appname, &fw_size, &app_arch)) return -EIO; data->client.app_arch = app_arch; @@ -4143,14 +4157,14 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) switch (resp.result) { case QSEOS_RESULT_SUCCESS: - ret = resp.data; + *app_id = resp.data; break; case QSEOS_RESULT_INCOMPLETE: ret = __qseecom_process_incomplete_cmd(data, &resp); if (ret) pr_err("process_incomplete_cmd FAILED\n"); else - ret = resp.data; + *app_id = resp.data; break; case QSEOS_RESULT_FAILURE: pr_err("scm call failed with response QSEOS_RESULT FAILURE\n"); @@ -4343,6 +4357,7 @@ int qseecom_start_app(struct qseecom_handle **handle, size_t len; ion_phys_addr_t pa; uint32_t fw_size, app_arch; + uint32_t app_id = 0; if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) { pr_err("Not allowed to be called in %d state\n", @@ -4397,18 +4412,18 @@ int qseecom_start_app(struct qseecom_handle **handle, app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND; strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE); - ret = __qseecom_check_app_exists(app_ireq); - if (ret < 0) + ret = __qseecom_check_app_exists(app_ireq, &app_id); + if (ret) goto err; strlcpy(data->client.app_name, app_name, MAX_APP_NAME_SIZE); - if (ret > 0) { - pr_warn("App id %d for [%s] app exists\n", ret, + if (app_id) { + pr_warn("App id %d for [%s] app exists\n", app_id, (char *)app_ireq.app_name); spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(entry, &qseecom.registered_app_list_head, list){ - if (entry->app_id == ret) { + if (entry->app_id == app_id) { entry->ref_cnt++; found_app = true; break; @@ -4423,11 +4438,11 @@ int qseecom_start_app(struct qseecom_handle **handle, /* load the app and get the app_id */ pr_debug("%s: Loading app for the first time'\n", qseecom.pdev->init_name); - ret = __qseecom_load_fw(data, app_name); + ret = __qseecom_load_fw(data, app_name, &app_id); if (ret < 0) goto err; } - data->client.app_id = ret; + data->client.app_id = app_id; if (!found_app) { entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { @@ -4435,7 +4450,7 @@ int qseecom_start_app(struct qseecom_handle **handle, ret = -ENOMEM; goto err; } - entry->app_id = ret; + entry->app_id = app_id; entry->ref_cnt = 1; strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE); if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) { @@ -5272,7 +5287,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, struct qseecom_check_app_ireq req; struct qseecom_registered_app_list *entry = NULL; unsigned long flags = 0; - uint32_t app_arch = 0; + uint32_t app_arch = 0, app_id = 0; bool found_app = false; /* Copy the relevant information needed for loading the image */ @@ -5287,18 +5302,18 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0'; strlcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE); - ret = __qseecom_check_app_exists(req); - - if ((ret == -EINVAL) || (ret == -ENODEV)) { + ret = __qseecom_check_app_exists(req, &app_id); + if (ret) { pr_err(" scm call to check if app is loaded failed"); return ret; /* scm call failed */ - } else if (ret > 0) { - pr_debug("App id %d (%s) already exists\n", ret, + } + if (app_id) { + pr_debug("App id %d (%s) already exists\n", app_id, (char *)(req.app_name)); spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(entry, &qseecom.registered_app_list_head, list){ - if (entry->app_id == ret) { + if (entry->app_id == app_id) { app_arch = entry->app_arch; entry->ref_cnt++; found_app = true; @@ -5307,8 +5322,8 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, } spin_unlock_irqrestore( &qseecom.registered_app_list_lock, flags); - data->client.app_id = ret; - query_req.app_id = ret; + data->client.app_id = app_id; + query_req.app_id = app_id; if (app_arch) { data->client.app_arch = app_arch; query_req.app_arch = app_arch; @@ -5330,7 +5345,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, pr_err("kmalloc for app entry failed\n"); return -ENOMEM; } - entry->app_id = ret; + entry->app_id = app_id; entry->ref_cnt = 1; entry->app_arch = data->client.app_arch; strlcpy(entry->app_name, data->client.app_name, diff --git a/include/uapi/linux/qseecom.h b/include/uapi/linux/qseecom.h index 5c5761d690dd..40c96eef3059 100644 --- a/include/uapi/linux/qseecom.h +++ b/include/uapi/linux/qseecom.h @@ -92,7 +92,7 @@ struct qseecom_load_img_req { int32_t ifd_data_fd; /* in */ char img_name[MAX_APP_NAME_SIZE]; /* in */ uint32_t app_arch; /* in */ - int app_id; /* out*/ + uint32_t app_id; /* out*/ }; struct qseecom_set_sb_mem_param_req { @@ -116,7 +116,7 @@ struct qseecom_qseos_version_req { */ struct qseecom_qseos_app_load_query { char app_name[MAX_APP_NAME_SIZE]; /* in */ - int app_id; /* out */ + uint32_t app_id; /* out */ uint32_t app_arch; };