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

Commit 5d02be98 authored by Zhen Kong's avatar Zhen Kong
Browse files

qseecom: fix a race condition when loading TA



Userspace and kernel clients may load a same TA at the same time.
To fix potential race condition, first kernel side need to release
mutex before sleep when failed to do ion allocation from QSEECOM_TA
heap. Besides, since kernel client may fail to load TA if this TA is
just being loaded by userspace client when mutex is released, it need
to recheck if this TA exists if TA loading error code is TA already
loaded.

Change-Id: Ie6af9c67b867dfae7b25e4ade6948dea67e476d6
Signed-off-by: default avatarZhen Kong <zkong@codeaurora.org>
parent 18be522e
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -4061,8 +4061,11 @@ static int __qseecom_allocate_img_data(struct ion_handle **pihandle,
	int retry = 0;

	do {
		if (retry++)
		if (retry++) {
			mutex_unlock(&app_access_lock);
			msleep(QSEECOM_TA_ION_ALLOCATE_DELAY);
			mutex_lock(&app_access_lock);
		}
		ihandle = ion_alloc(qseecom.ion_clnt, fw_size,
			SZ_4K, ION_HEAP(ION_QSECOM_TA_HEAP_ID), 0);
	} while (IS_ERR_OR_NULL(ihandle) &&
@@ -4212,7 +4215,11 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname,
	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len,
			&resp, sizeof(resp));
	if (ret) {
		pr_err("scm_call to load failed : ret %d\n", ret);
		pr_err("scm_call to load failed : ret %d, result %x\n",
			ret, resp.result);
		if (resp.result == QSEOS_RESULT_FAIL_APP_ALREADY_LOADED)
			ret = -EEXIST;
		else
			ret = -EIO;
		goto exit_disable_clk_vote;
	}
@@ -4465,6 +4472,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
	}
	mutex_lock(&app_access_lock);

recheck:
	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);
@@ -4494,7 +4502,10 @@ int qseecom_start_app(struct qseecom_handle **handle,
		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)
		if (ret == -EEXIST) {
			pr_err("recheck if TA %s is loaded\n", app_name);
			goto recheck;
		} else if (ret < 0)
			goto exit_ion_free;
	}
	data->client.app_id = app_id;
+2 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2018, 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
@@ -19,6 +19,7 @@
#define QSEECOM_KEY_ID_SIZE   32

#define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD  -19   /*0xFFFFFFED*/
#define QSEOS_RESULT_FAIL_APP_ALREADY_LOADED  -38   /*0xFFFFFFDA*/
#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
#define QSEOS_RESULT_FAIL_KS_OP               -64
#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65