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

Commit 438948a5 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qseecom: Fix stack overflow issue"

parents b986e653 27d59676
Loading
Loading
Loading
Loading
+54 −28
Original line number Diff line number Diff line
/*
 * QTI Secure Execution Environment Communicator (QSEECOM) driver
 *
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2019, 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
@@ -2418,7 +2418,7 @@ 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;
@@ -2437,7 +2437,7 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req,
	spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
	list_for_each_entry(entry,
			&qseecom.registered_app_list_head, list) {
		if (!strcmp(entry->app_name, req.app_name)) {
		if (!strcmp(entry->app_name, req->app_name)) {
			found_app = true;
			break;
		}
@@ -2452,7 +2452,7 @@ static int __qseecom_check_app_exists(struct qseecom_check_app_ireq req,
	memset((void *)&resp, 0, sizeof(resp));

	/*  SCM_CALL  to check if app_id for the mentioned app exists */
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, req,
				sizeof(struct qseecom_check_app_ireq),
				&resp, sizeof(resp));
	if (ret) {
@@ -2493,19 +2493,24 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)

	size_t len;
	struct qseecom_command_scm_resp resp;
	struct qseecom_check_app_ireq req;
	struct qseecom_check_app_ireq *req = NULL;
	struct qseecom_load_app_ireq load_req;
	struct qseecom_load_app_64bit_ireq load_req_64bit;
	void *cmd_buf = NULL;
	size_t cmd_len;
	bool first_time = false;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	/* Copy the relevant information needed for loading the image */
	if (copy_from_user(&load_img_req,
				(void __user *)argp,
				sizeof(struct qseecom_load_img_req))) {
		pr_err("copy_from_user failed\n");
		return -EFAULT;
		ret = -EFAULT;
		goto req_free;
	}

	/* Check and load cmnlib */
@@ -2515,7 +2520,8 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
			ret = qseecom_load_commonlib_image(data, "cmnlib");
			if (ret) {
				pr_err("failed to load cmnlib\n");
				return -EIO;
				ret = -EIO;
				goto req_free;
			}
			qseecom.commonlib_loaded = true;
			pr_debug("cmnlib is loaded\n");
@@ -2526,7 +2532,8 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
			ret = qseecom_load_commonlib_image(data, "cmnlib64");
			if (ret) {
				pr_err("failed to load cmnlib64\n");
				return -EIO;
				ret = -EIO;
				goto req_free;
			}
			qseecom.commonlib64_loaded = true;
			pr_debug("cmnlib64 is loaded\n");
@@ -2538,7 +2545,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
		ret = __qseecom_register_bus_bandwidth_needs(data, MEDIUM);
		mutex_unlock(&qsee_bw_mutex);
		if (ret)
			return ret;
			goto req_free;
	}

	/* Vote for the SFPB clock */
@@ -2546,9 +2553,9 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
	if (ret)
		goto enable_clk_err;

	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
	req->qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
	load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
	strlcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
	strlcpy(req->app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);

	ret = __qseecom_check_app_exists(req, &app_id);
	if (ret < 0)
@@ -2556,14 +2563,14 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)

	if (app_id) {
		pr_debug("App id %d (%s) already exists\n", app_id,
			(char *)(req.app_name));
			(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 == app_id) {
				if (entry->ref_cnt == U32_MAX) {
					pr_err("App %d (%s) ref_cnt overflow\n",
						app_id, req.app_name);
						app_id, req->app_name);
					ret = -EINVAL;
					goto loadapp_err;
				}
@@ -2725,6 +2732,8 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
		qseecom_unregister_bus_bandwidth_needs(data);
		mutex_unlock(&qsee_bw_mutex);
	}
req_free:
	kfree(req);
	return ret;
}

@@ -4559,7 +4568,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
	int32_t ret = 0;
	unsigned long flags = 0;
	struct qseecom_dev_handle *data = NULL;
	struct qseecom_check_app_ireq app_ireq;
	struct qseecom_check_app_ireq *app_ireq = NULL;
	struct qseecom_registered_app_list *entry = NULL;
	struct qseecom_registered_kclient_list *kclient_entry = NULL;
	bool found_app = false;
@@ -4608,25 +4617,31 @@ int qseecom_start_app(struct qseecom_handle **handle,

	mutex_lock(&app_access_lock);

	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
	strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
	app_ireq = kzalloc(sizeof(*app_ireq), GFP_KERNEL);
	if (!app_ireq) {
		ret = -ENOMEM;
		goto err;
	}

	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, &app_id);
	if (ret)
		goto err;
		goto app_ireq_free;

	strlcpy(data->client.app_name, app_name, MAX_APP_NAME_SIZE);
	if (app_id) {
		pr_warn("App id %d for [%s] app exists\n", app_id,
			(char *)app_ireq.app_name);
			(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 == app_id) {
				if (entry->ref_cnt == U32_MAX) {
					pr_err("App %d (%s) ref_cnt overflow\n",
						app_id, app_ireq.app_name);
						app_id, app_ireq->app_name);
					ret = -EINVAL;
					goto err;
					goto app_ireq_free;
				}
				entry->ref_cnt++;
				found_app = true;
@@ -4637,15 +4652,16 @@ int qseecom_start_app(struct qseecom_handle **handle,
				&qseecom.registered_app_list_lock, flags);
		if (!found_app)
			pr_warn("App_id %d [%s] was loaded but not registered\n",
					ret, (char *)app_ireq.app_name);
					ret, (char *)app_ireq->app_name);
	} else {
		/* 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, &app_id);
		if (ret < 0)
			goto err;
			goto app_ireq_free;
	}
	kfree(app_ireq);
	data->client.app_id = app_id;
	if (!found_app) {
		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
@@ -4702,6 +4718,8 @@ int qseecom_start_app(struct qseecom_handle **handle,
	mutex_unlock(&app_access_lock);
	return 0;

app_ireq_free:
	kfree(app_ireq);
err:
	if (va)
		__qseecom_free_coherent_buf(size, va, pa);
@@ -5510,8 +5528,8 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
{

	int32_t ret = 0;
	struct qseecom_qseos_app_load_query *query_req;
	struct qseecom_check_app_ireq req;
	struct qseecom_qseos_app_load_query *query_req = NULL;
	struct qseecom_check_app_ireq *req = NULL;
	struct qseecom_registered_app_list *entry = NULL;
	unsigned long flags = 0;
	uint32_t app_arch = 0, app_id = 0;
@@ -5522,6 +5540,12 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
	if (!query_req)
		return -ENOMEM;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req) {
		ret = -ENOMEM;
		goto query_req_exit;
	}

	/* Copy the relevant information needed for loading the image */
	if (copy_from_user(query_req, (void __user *)argp,
				sizeof(struct qseecom_qseos_app_load_query))) {
@@ -5530,9 +5554,9 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
		goto exit_free;
	}

	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
	req->qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
	query_req->app_name[MAX_APP_NAME_SIZE-1] = '\0';
	strlcpy(req.app_name, query_req->app_name, MAX_APP_NAME_SIZE);
	strlcpy(req->app_name, query_req->app_name, MAX_APP_NAME_SIZE);

	ret = __qseecom_check_app_exists(req, &app_id);
	if (ret) {
@@ -5541,7 +5565,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
	}
	if (app_id) {
		pr_debug("App id %d (%s) already exists\n", app_id,
			(char *)(req.app_name));
			(char *)(req->app_name));
		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
		list_for_each_entry(entry,
				&qseecom.registered_app_list_head, list){
@@ -5549,7 +5573,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
				app_arch = entry->app_arch;
				if (entry->ref_cnt == U32_MAX) {
					pr_err("App %d (%s) ref_cnt overflow\n",
						app_id, req.app_name);
						app_id, req->app_name);
					ret = -EINVAL;
					goto exit_free;
				}
@@ -5609,6 +5633,8 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data,
	}

exit_free:
	kfree(req);
query_req_exit:
	kfree(query_req);

	return ret;	/* app not loaded */