From b3ba6ffa2c3f27ce757647a5d5aa99074e900fba Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Fri, 2 Feb 2018 17:21:04 -0800 Subject: qseecom: block system signals when waiting for listener available Make change to block system signals when qseecom is waiting for a blocked listener becomes available. This will prevent qseecom being waken up by power collapse and returning to kernel, which may cause XPU violation as TA req/resp buffer is still XPU protected at this time Change-Id: Ie5ea16f11ad653937236de042afb1bb5710123e6 Signed-off-by: Zhen Kong --- drivers/misc/qseecom.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 98657d0a6822..3b5c3059a02d 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,6 +1,6 @@ /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -1856,6 +1856,8 @@ static int __qseecom_process_blocked_on_listener_legacy( struct qseecom_command_scm_resp continue_resp; bool found_app = false; unsigned long flags; + sigset_t new_sigset; + sigset_t old_sigset; if (!resp || !data) { pr_err("invalid resp or data pointer\n"); @@ -1897,23 +1899,23 @@ static int __qseecom_process_blocked_on_listener_legacy( ptr_app->blocked_on_listener_id = resp->data; /* sleep until listener is available */ + sigfillset(&new_sigset); + sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); + do { qseecom.app_block_ref_cnt++; ptr_app->app_blocked = true; mutex_unlock(&app_access_lock); - if (wait_event_freezable( + wait_event_freezable( list_ptr->listener_block_app_wq, - !list_ptr->listener_in_use)) { - pr_err("Interrupted: listener_id %d, app_id %d\n", - resp->data, ptr_app->app_id); - ret = -ERESTARTSYS; - goto exit; - } + !list_ptr->listener_in_use); mutex_lock(&app_access_lock); ptr_app->app_blocked = false; qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use); + sigprocmask(SIG_SETMASK, &old_sigset, NULL); + ptr_app->blocked_on_listener_id = 0; /* notify the blocked app that listener is available */ pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n", @@ -1947,6 +1949,8 @@ static int __qseecom_process_blocked_on_listener_smcinvoke( struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; unsigned int session_id; + sigset_t new_sigset; + sigset_t old_sigset; if (!resp) { pr_err("invalid resp pointer\n"); @@ -1962,22 +1966,23 @@ static int __qseecom_process_blocked_on_listener_smcinvoke( } pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); + /* sleep until listener is available */ + sigfillset(&new_sigset); + sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); + do { qseecom.app_block_ref_cnt++; mutex_unlock(&app_access_lock); - if (wait_event_freezable( + wait_event_freezable( list_ptr->listener_block_app_wq, - !list_ptr->listener_in_use)) { - pr_err("Interrupted: listener_id %d, session_id %d\n", - resp->data, session_id); - ret = -ERESTARTSYS; - goto exit; - } + !list_ptr->listener_in_use); mutex_lock(&app_access_lock); qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use); + sigprocmask(SIG_SETMASK, &old_sigset, NULL); + /* notify TZ that listener is available */ pr_warn("Lsntr %d is available, unblock session(%d) in TZ\n", resp->data, session_id); -- cgit v1.2.3