diff --git a/CMakeLists.txt b/CMakeLists.txt index cd588797e3d6b2eb30f70c7c36d7c4fb88773dfc..9ef9ef8fbf67f0530758dad9fc8fb3284d50ce8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,9 @@ set(TARGET_NAME tzdriver) # Add source files set(depend-objs "core/smc_smp.o core/tc_client_driver.o core/session_manager.o core/mailbox_mempool.o core/teek_app_load.o") set(depend-objs "${depend-objs} core/agent.o core/gp_ops.o core/mem.o core/cmdmonitor.o core/tz_spi_notify.o core/tz_pm.o core/tee_compat_check.o") -set(depend-objs "${depend-objs} auth/auth_base_impl.o core/teec_daemon_auth.o tlogger/tlogger.o tlogger/log_pages_cfg.o ko_adapt.o auth/security_auth_enhance.o") +set(depend-objs "${depend-objs} auth/auth_base_impl.o auth/client_hash_auth.o tlogger/tlogger.o tlogger/log_pages_cfg.o ko_adapt.o") +set(depend-objs "${depend-objs} core/reserved_mempool.o tzdriver_internal/tee_trace_event/tee_trace_event.o tzdriver_internal/tee_trace_event/tee_trace_interrupt.o") +set(depend-objs "${depend-objs} core/shared_mem.o") # Check libboundscheck.so execute_process(COMMAND cat /proc/kallsyms COMMAND grep vsnprintf_s OUTPUT_VARIABLE RESULT) @@ -27,12 +29,15 @@ string(STRIP ${KDIR} KDIR) set(KERNEL_DIR ${KPATH}/${KDIR}) # Set extra options -set(CMAKE_EXTRA_FLAGS "-fstack-protector-strong -DCONFIG_TEELOG -DCONFIG_TZDRIVER_MODULE -DCONFIG_TEECD_AUTH -DCONFIG_PAGES_MEM=y -DCONFIG_AUTH_ENHANCE -DCONFIG_CLOUDSERVER_TEECD_AUTH") -set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM") +set(CMAKE_EXTRA_FLAGS "-fstack-protector-strong -DCONFIG_TEELOG -DCONFIG_TZDRIVER_MODULE -DCONFIG_TEECD_AUTH -DCONFIG_PAGES_MEM=y -DCONFIG_CLOUDSERVER_TEECD_AUTH") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM -DCONFIG_TEE_TRACE") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_TEE_LOG_ACHIVE_PATH=\\\\\\\"/var/log/tee/last_teemsg\\\\\\\"") -set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DTEECD_PATH_UID_AUTH_CTX=\\\\\\\"/usr/bin/teecd:0\\\\\\\"") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_AUTH_SUPPORT_UNAME -DCONFIG_AUTH_HASH -std=gnu99") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/libboundscheck/include/ -I${PROJECT_SOURCE_DIR} -I${PROJECT_SOURCE_DIR}/auth -I${PROJECT_SOURCE_DIR}/core") -set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/tlogger -I${PROJECT_SOURCE_DIR}/kthread_affinity") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/tlogger -I${PROJECT_SOURCE_DIR}/tzdriver_internal/kthread_affinity -I${PROJECT_SOURCE_DIR}/tzdriver_internal/include") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/tzdriver_internal/tee_trace_event") # Compile .ko file add_custom_target(${TARGET_NAME} ALL COMMAND @echo "Compiling module ${TARGET_NAME}.ko...") @@ -52,4 +57,5 @@ add_custom_target(clean COMMAND cd ${PROJECT_SOURCE_DIR} && rm -vrf *.o *.ko auth/*.o core/*.o tlogger/*.o COMMAND cd ${PROJECT_SOURCE_DIR} && rm -vrf *.order *.symvers *.mod.c .tmp_versions .*o.cmd auth/.*o.cmd core/.*o.cmd tlogger/.*o.cmd COMMAND cd ${PROJECT_SOURCE_DIR} && rm -vrf auth/.*.o.d core/.*.o.d tlogger/.*.o.d + COMMAND cd ${PROJECT_SOURCE_DIR} && rm -vrf tzdriver_internal/tee_trace_event/.*.o.d ) diff --git a/Makefile b/Makefile index 8bfcc449cb079aa76a2467504f83415017dff090..a5eb6198e7d6350c1a9e251b3c6ad0abff3efb3b 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,9 @@ obj-m := tzdriver.o tzdriver-objs := core/smc_smp.o core/tc_client_driver.o core/session_manager.o core/mailbox_mempool.o core/teek_app_load.o tzdriver-objs += core/agent.o core/gp_ops.o core/mem.o core/cmdmonitor.o core/tz_spi_notify.o core/tz_pm.o core/tee_compat_check.o -tzdriver-objs += core/reserved_mempool.o core/tee_trace_event.o -tzdriver-objs += auth/auth_base_impl.o tlogger/tlogger.o tlogger/log_pages_cfg.o ko_adapt.o +tzdriver-objs += auth/auth_base_impl.o auth/client_hash_auth.o tlogger/tlogger.o tlogger/log_pages_cfg.o ko_adapt.o +tzdriver-objs += core/reserved_mempool.o tzdriver_internal/tee_trace_event/tee_trace_event.o tzdriver_internal/tee_trace_event/tee_trace_interrupt.o +tzdriver-objs += core/shared_mem.o RESULT := $(shell cat /proc/kallsyms | grep vsnprintf_s) @@ -21,14 +22,17 @@ KPATH := /usr/src/kernels KDIR := $(KPATH)/$(shell ls $(KPATH)) EXTRA_CFLAGS += -fstack-protector-strong -DCONFIG_TEELOG -DCONFIG_TZDRIVER_MODULE -DCONFIG_TEECD_AUTH -DCONFIG_PAGES_MEM=y -DCONFIG_CLOUDSERVER_TEECD_AUTH -EXTRA_CFLAGS += -I$(PWD)/libboundscheck/include/ -I$(PWD) -I$(PWD)/auth -I$(PWD)/core -EXTRA_CFLAGS += -I$(PWD)/tlogger -I$(PWD)/kthread_affinity +EXTRA_CFLAGS += -I$(PWD)/libboundscheck/include/ -I$(PWD) -I$(PWD)/auth -I$(PWD)/core -I$(PWD)/tzdriver_internal/tee_trace_event +EXTRA_CFLAGS += -I$(PWD)/tlogger -I$(PWD)/tzdriver_internal/kthread_affinity -I$(PWD)/tzdriver_internal/include EXTRA_CFLAGS += -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM -DCONFIG_TEE_TRACE EXTRA_CFLAGS += -DCONFIG_TEE_LOG_ACHIVE_PATH=\"/var/log/tee/last_teemsg\" EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM +EXTRA_CFLAGS += -DTEECD_PATH_UID_AUTH_CTX=\"/usr/bin/teecd:0\" +EXTRA_CFLAGS += -DCONFIG_AUTH_SUPPORT_UNAME -DCONFIG_AUTH_HASH -std=gnu99 all: make -C $(KDIR) M=$(PWD) modules clean: -rm -vrf *.o *.ko auth/*.o core/*.o tlogger/*.o -rm -vrf *.order *.symvers *.mod.c .tmp_versions .*o.cmd auth/.*o.cmd core/.*o.cmd tlogger/.*o.cmd -rm -vrf auth/.*.o.d core/.*.o.d tlogger/.*.o.d + -rm -vrf tzdriver_internal/tee_trace_event/.*.o.d diff --git a/auth/auth_base_impl.c b/auth/auth_base_impl.c index 9890be0bdc4a84b59a3b685b9aebe3ff57668a1d..9c93851687d143dc7ea9b8b490c72fe3391f4b65 100644 --- a/auth/auth_base_impl.c +++ b/auth/auth_base_impl.c @@ -42,7 +42,7 @@ /* for crypto */ struct crypto_shash *g_shash_handle; -bool g_shash_handle_state; +bool g_shash_handle_state = false; struct mutex g_shash_handle_lock; void init_crypto_hash_lock(void) @@ -66,7 +66,7 @@ struct crypto_shash *get_shash_handle(void) return g_shash_handle; } -void tee_exit_shash_handle(void) +void free_shash_handle(void) { if (g_shash_handle) { crypto_free_shash(g_shash_handle); @@ -128,21 +128,21 @@ static int prepare_desc(struct sdesc **desc) #define PINED_PAGE_NUMBER 1 static int get_proc_user_pages(struct mm_struct *mm, unsigned long start_code, - struct page **ptr_page, struct task_struct *cur_struct) + struct page **ptr_page, struct task_struct *cur_struct) { #if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) - (void)cur_struct; - return get_user_pages_remote(mm, start_code, (unsigned long)PINED_PAGE_NUMBER, - FOLL_FORCE, ptr_page, NULL, NULL); + (void)cur_struct; + return get_user_pages_remote(mm, start_code, + (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL, NULL); #elif (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE) - return get_user_pages_remote(cur_struct, mm, start_code, (unsigned long)PINED_PAGE_NUMBER, - FOLL_FORCE, ptr_page, NULL, NULL); + return get_user_pages_remote(cur_struct, mm, start_code, + (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL, NULL); #elif (KERNEL_VERSION(4, 4, 197) <= LINUX_VERSION_CODE) - return get_user_pages_locked(cur_struct, mm, start_code, (unsigned long)PINED_PAGE_NUMBER, - FOLL_FORCE, ptr_page, NULL); + return get_user_pages_locked(cur_struct, mm, start_code, + (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL); #else - return get_user_pages_locked(cur_struct, mm, start_code, (unsigned long)PINED_PAGE_NUMBER, - 0, 1, ptr_page, NULL); + return get_user_pages_locked(cur_struct, mm, start_code, + (unsigned long)PINED_PAGE_NUMBER, 0, 1, ptr_page, NULL); #endif } @@ -164,7 +164,7 @@ static int update_task_hash(struct mm_struct *mm, while (start_code < end_code) { /* Get a handle of the page we want to read */ - rc = get_proc_user_pages(mm, start_code, &ptr_page, cur_struct); + rc = get_proc_user_pages(mm, start_code, &ptr_page, cur_struct); if (rc != PINED_PAGE_NUMBER) { tloge("get user pages error[0x%x]\n", rc); rc = -EFAULT; @@ -213,18 +213,17 @@ int calc_task_hash(unsigned char *digest, uint32_t dig_len, if (!mm) { if (memset_s(digest, dig_len, 0, MAX_SHA_256_SZ)) return -EFAULT; - tloge("kernel proc need not check\n"); return EOK; } - if(pub_key_len != sizeof(uint32_t)){ - tloge("apk need not check!\n"); - mmput(mm); - return EOK; - } + if (pub_key_len != sizeof(uint32_t)) { + mmput(mm); + return EOK; + } if (prepare_desc(&desc) != EOK) { mmput(mm); + tloge("prepare desc failed\n"); return -ENOMEM; } @@ -250,3 +249,80 @@ free_res: return rc; } /* end: Calculate the SHA256 file digest */ + +static int check_proc_uid_path(const char *auth_ctx) +{ + int ret = 0; + char str_path_uid[MAX_PATH_SIZE] = { 0 }; + const struct cred *cred = NULL; + char *pro_dpath = NULL; + char *k_path = NULL; + u32 auth_ctx_len; + + if (auth_ctx == NULL) { + tloge("bad params\n"); + return CHECK_ACCESS_FAIL; + } + + auth_ctx_len = (u32)strnlen(auth_ctx, MAX_PATH_SIZE); + if (auth_ctx_len == 0 || auth_ctx_len >= MAX_PATH_SIZE) { + tloge("invalid uid path\n"); + return CHECK_ACCESS_FAIL; + } + + k_path = kmalloc(MAX_PATH_SIZE, GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)k_path)) { + tloge("path kmalloc fail\n"); + return CHECK_ACCESS_FAIL; + } + + pro_dpath = get_proc_dpath(k_path, MAX_PATH_SIZE); + if (IS_ERR_OR_NULL(pro_dpath)) { + kfree(k_path); + return CHECK_ACCESS_FAIL; + } + + get_task_struct(current); + cred = koadpt_get_task_cred(current); + if (cred == NULL) { + tloge("cred is NULL\n"); + kfree(k_path); + put_task_struct(current); + return CHECK_ACCESS_FAIL; + } + + if (snprintf_s(str_path_uid, MAX_PATH_SIZE, MAX_PATH_SIZE - 1, "%s:%u", pro_dpath, cred->uid.val) < 0) { + tloge("snprintf_s path uid failed, ret %d\n", ret); + ret = CHECK_ACCESS_FAIL; + goto clean; + } + + if (strncmp(str_path_uid, auth_ctx, auth_ctx_len) != 0) + ret = ENTER_BYPASS_CHANNEL; + else + ret = CHECK_ACCESS_SUCC; + +clean: + put_cred(cred); + put_task_struct(current); + kfree(k_path); + return ret; +} + +#ifdef CONFIG_TEECD_AUTH +int check_teecd_auth(void) +{ + int ret = check_proc_uid_path(TEECD_PATH_UID_AUTH_CTX); + if (ret != 0) { + tloge("check teecd path failed, ret %d\n", ret); + return ret; + } + + return CHECK_ACCESS_SUCC; +} +#else +int check_teecd_auth(void) +{ + return 0; +} +#endif diff --git a/auth/auth_base_impl.h b/auth/auth_base_impl.h index 40390c6e807e9a302a4ccc3ef14f0faf8cac52c6..3d8d8aed235c5ecae8f3b947234c3d8722cbc597 100644 --- a/auth/auth_base_impl.h +++ b/auth/auth_base_impl.h @@ -18,6 +18,10 @@ #ifndef AUTH_BASE_IMPL_H #define AUTH_BASE_IMPL_H +#ifndef TEECD_PATH_UID_AUTH_CTX +#define TEECD_PATH_UID_AUTH_CTX "" +#endif + #if ((defined CONFIG_CLIENT_AUTH) || (defined CONFIG_TEECD_AUTH)) #include #if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) @@ -36,6 +40,7 @@ #define BUF_MAX_SIZE 1024 #define MAX_PATH_SIZE 512 #define SHA256_DIGEST_LENTH 32 +#define MAX_SCTX_LEN 128 struct sdesc { struct shash_desc shash; @@ -47,16 +52,16 @@ int calc_task_hash(unsigned char *digest, uint32_t dig_len, struct task_struct *cur_struct, uint32_t pub_key_len); int tee_init_shash_handle(char *hash_type); -void tee_exit_shash_handle(void); +void free_shash_handle(void); struct crypto_shash *get_shash_handle(void); void init_crypto_hash_lock(void); void mutex_crypto_hash_lock(void); void mutex_crypto_hash_unlock(void); - +int check_teecd_auth(void); #else -static inline void tee_exit_shash_handle(void) +static inline void free_shash_handle(void) { return; } @@ -66,6 +71,11 @@ static void init_crypto_hash_lock(void) return; } +int check_teecd_auth(void) +{ + return 0; +} + #endif /* CLIENT_AUTH || TEECD_AUTH */ #endif diff --git a/auth/client_hash_auth.c b/auth/client_hash_auth.c index 85ed1b68b30a2beb54e5ff75d02c2a803af69414..a407eb49bb975c964663ce76ef989fe4015ff3ff 100644 --- a/auth/client_hash_auth.c +++ b/auth/client_hash_auth.c @@ -1,246 +1,505 @@ -/* - * client_hash_auth.c - * - * function for CA code hash auth - * - * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "client_hash_auth.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "tc_ns_log.h" -#include "auth_base_impl.h" - -#define LIBTEEC_CODE_PAGE_SIZE 8 -#define DEFAULT_TEXT_OFF 0 -#define LIBTEEC_NAME_MAX_LEN 50 - -const char g_libso[KIND_OF_SO][LIBTEEC_NAME_MAX_LEN] = {"libteec_vendor.so"}; - -static int find_lib_code_area(struct mm_struct *mm, struct vm_area_struct **lib_code_area, int so_index) -{ - struct vm_area_struct *vma = NULL; - bool is_valid_vma = false; - bool is_so_exists = false; - bool param_check = (!mm || !mm->mmap || !lib_code_area || so_index >= KIND_OF_SO); - - if (param_check){ - tloge("illegal input params\n"); - return -EFAULT; - } - - for (vma = mm->mmap; vma ; vma = vma->vm->next) { - is_valid_vma = (vma->vm_file && vma->vm_file->f_path.dentry && - vma->vm_file->f_path.dentry->d_name.name); - if (is_valid_vma) { - is_so_exists = !strcmp(g_libso[so_index], vma->vm_file->f_path.dentry->d_name.name); - if (is_so_exists && (vma->vm_flags & VM_EXEC)) { - *lib_code_area = vma; - tlogd("so name is %s\n", - vma->vm_file->f_path.dentry->d_name.name); - return EOK; - } - } - } - return -EFAULT; -} - -struct get_code_info { - unsigned long code_start; - unsigned long code_end; - unsigned long code_size; -}; - -static int update_so_hash(struct mm_struct *mm, - struct task_struct *cur_struct, struct shash_desc *shash, int so_index) -{ - struct vm_area_struct *vma = NULL; - int rc = -EFAULT; - struct get_code_info code_info; - unsigned long in_size; - struct page *ptr_page = NULL; - void *ptr_base = NULL; - - if (find_lib_code_area(mm, &vma, so_index)) { - tlogd("get lib code vma area failed\n"); - return -EFAULT; - } - - code_info.code_start = vma->vm_start; - code_info.code_end = vma->vm_end; - code_info.code_size = code_info.code_end - code_info.code_start; - - while (code_info.code_start < code_info.code_end) { - // get a handle of the page we want to read -#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) - rc = get_user_pages_remote(mm, code_info.code_start, 1, FOLL_FORCE, &ptr_page, NULL, NULL); -#else - rc = get_user_pages_remote(cur_struct, mm, code_info.code_start, 1, - FOLL_FORCE, &ptr_page, NULL, NULL); -#endif - if (rc != 1) { - tloge("get user pages locked error[0x%x]\n", rc); - rc = -EFAULT; - break; - } - - ptr_base = kmap_atomic(ptr_page); - if (!ptr_base) { - rc = -EFAULT; - put_page(ptr_page); - break; - } - in_size = (code_info.code_size > PAGE_SIZE) ? PAGE_SIZE : code_info.code_size; - - rc = crypto_shash_update(shash, ptr_base, in_size); - if (rc) { - kunmap_atomic(ptr_base); - put_page(ptr_page); - break; - } - kunmap_atomic(ptr_base); - put_page(ptr_page); - code_info.code_start += in_size; - code_info.code_size = code_info.code_end - code_info.code_start; - } - return rc; -} - -/* Calculate the SHA256 library digest */ -static int calc_task_so_hash(unsigned char *digest, uint32_t dig_len, - struct task_struct *cur_struct, int so_index) -{ - struct mm_struct *mm = NULL; - int rc; - size_t size; - size_t shash_size; - struct sdesc *desc = NULL; - - if(!digest || dig_len != SHA256_DIGEST_LENTH) { - tloge("tee hash: digest is NULL\n"); - return -EFAULT; - } - - shash_size = crypto_shash_descsize(get_shash_handle()); - size = sizeof(desc->shash) + shash_size; - if (size < sizeof(desc->shash) || size < shash_size) { - tloge("size overflow\n"); - return -ENOMEM; - } - - desc = kzalloc(size, GFP_KERNEL); - if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)desc)) { - tloge("alloc desc failed\n"); - return -ENOMEM; - } - - desc->shash.tfm = get_shash_handle(); - if (crypto_shash_init(&desc->shash)) { - kfree(desc); - return -EFAULT; - } - - mm = get_task_mm(cur_struct); - if (!mm) { - tloge("so does not have mm struct\n"); - if (memset_s(digest, MAX_SHA_256_SZ, 0, dig_len)) - tloge("memset digest failed\n"); - kfree(desc); - return -EFAULT; - } - - down_read(&mm_sem_lock(mm)); - rc = update_so_hash(mm, cur_struct, &desc->shash, so_index); - up_read(&mm_sem_lock(mm)); - mmput(mm); - if (!rc) - rc = crypto_shash_final(&desc->shash, digest); - kfree(desc); - return rc; -} - -static int proc_calc_hash(uint8_t kernel_api, struct tc_ns_session *session, - struct task_struct *cur_struct, uint32_t pub_key_len) -{ - int rc, i; - int so_found = 0; - - mutex_crypto_hash_lock(); - if (kernel_api == TEE_REQ_FROM_USER_MODE) { - for (i = 0; so_found < NUM_OF_SO && i < KIND_OF_SO; i++) { - rc = calc_task_so_hash(session->auth_hash_buf + MAX_SHA_256_SZ * so_found, - (uint32_t)SHA256_DIGEST_LENTH, cur_struct, i); - if (!rc) - so_found++; - } - if (so_found != NUM_OF_SO) - tlogd("so library found: %d\n", so_found); - }else { - tlogd("request from kernel\n"); - } - -#ifdef CONFIG_ASAN_DEBUG - tloge("so auth disabled for ASAN debug\n"); - uint32_t so_hash_len = MAX_SHA_256_SZ * NUM_OF_SO; - errno_t sret = memset_s(session->auth_hash_buf, so_hash_len, 0, so_hash_len); - if (sret) { - mutex_crypto_hash_unlock(); - tloge("memset so hash failed\n"); - return -EFAULT; - } -#endif - - rc = calc_task_hash(session->auth_hash_buf + MAX_SHA_256_SZ * NUM_OF_SO, - (uint32_t)SHA256_DIGEST_LENTH, cur_struct, pub_key_len); - if (rc) { - mutex_crypto_hash_unlock(); - tloge("tee calc ca hash failed\n"); - return -EFAULT; - } - mutex_crypto_hash_unlock(); - return EOK; -} - -int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, - struct tc_ns_client_context *context, struct tc_ns_session *session) -{ - int ret; - struct task_struct *cur_struct = NULL; - bool check = false; - check = (!dev_file || !context || !session); - if (check) { - tloge("bad parameters\n"); - return -EFAULT; - } - - if (tee_init_shash_handle("sha256")) { - tloge("init code hash error\n"); - return -EFAULT; - } - - cur_struct = current; - ret = proc_calc_hash(dev_file->kernel_api, session, cur_struct, dev_file->pub_key_len); - return ret; -} \ No newline at end of file +/* + * client_hash_auth.c + * + * function for CA code hash auth + * + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include "client_hash_auth.h" +#include +#include +#include +#include +#ifdef CONFIG_AUTH_SUPPORT_UNAME +#include +#endif +#ifdef CONFIG_CLIENT_AUTH +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef CONFIG_AUTH_HASH +#include +#endif +#include + +#include "tc_ns_log.h" +#include "auth_base_impl.h" + +#ifdef CONFIG_AUTH_HASH +#define SHA256_DIGEST_LENGTH 32 +#define FIXED_PKG_NAME_LENGTH 256 +struct sdesc_hash { + struct shash_desc shash; + char ctx[]; +}; +#endif + +#ifdef CONFIG_CLIENT_AUTH +#define LIBTEEC_CODE_PAGE_SIZE 8 +#define DEFAULT_TEXT_OFF 0 +#define LIBTEEC_NAME_MAX_LEN 50 + +const char g_libso[KIND_OF_SO][LIBTEEC_NAME_MAX_LEN] = {"libteec_vendor.so"}; + +static int find_lib_code_area(struct mm_struct *mm, + struct vm_area_struct **lib_code_area, int so_index) +{ + struct vm_area_struct *vma = NULL; + bool is_valid_vma = false; + bool is_so_exists = false; + bool param_check = (!mm || !mm->mmap || + !lib_code_area || so_index >= KIND_OF_SO); + + if (param_check) { + tloge("illegal input params\n"); + return -EFAULT; + } + for (vma = mm->mmap; vma; vma = vma->vm_next) { + is_valid_vma = (vma->vm_file && + vma->vm_file->f_path.dentry && + vma->vm_file->f_path.dentry->d_name.name); + if (is_valid_vma) { + is_so_exists = !strcmp(g_libso[so_index], + vma->vm_file->f_path.dentry->d_name.name); + if (is_so_exists && (vma->vm_flags & VM_EXEC)) { + *lib_code_area = vma; + tlogd("so name is %s\n", + vma->vm_file->f_path.dentry->d_name.name); + return EOK; + } + } + } + return -EFAULT; +} + +struct get_code_info { + unsigned long code_start; + unsigned long code_end; + unsigned long code_size; +}; +static int update_so_hash(struct mm_struct *mm, + struct task_struct *cur_struct, struct shash_desc *shash, int so_index) +{ + struct vm_area_struct *vma = NULL; + int rc = -EFAULT; + struct get_code_info code_info; + unsigned long in_size; + struct page *ptr_page = NULL; + void *ptr_base = NULL; + + if (find_lib_code_area(mm, &vma, so_index)) { + tlogd("get lib code vma area failed\n"); + return -EFAULT; + } + + code_info.code_start = vma->vm_start; + code_info.code_end = vma->vm_end; + code_info.code_size = code_info.code_end - code_info.code_start; + + while (code_info.code_start < code_info.code_end) { + // Get a handle of the page we want to read +#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) + rc = get_user_pages_remote(mm, code_info.code_start, 1, FOLL_FORCE, &ptr_page, NULL, NULL); +#else + rc = get_user_pages_remote(cur_struct, mm, code_info.code_start, + 1, FOLL_FORCE, &ptr_page, NULL, NULL); +#endif + if (rc != 1) { + tloge("get user pages locked error[0x%x]\n", rc); + rc = -EFAULT; + break; + } + + ptr_base = kmap_atomic(ptr_page); + if (!ptr_base) { + rc = -EFAULT; + put_page(ptr_page); + break; + } + in_size = (code_info.code_size > PAGE_SIZE) ? PAGE_SIZE : code_info.code_size; + + rc = crypto_shash_update(shash, ptr_base, in_size); + if (rc) { + kunmap_atomic(ptr_base); + put_page(ptr_page); + break; + } + kunmap_atomic(ptr_base); + put_page(ptr_page); + code_info.code_start += in_size; + code_info.code_size = code_info.code_end - code_info.code_start; + } + return rc; +} + +/* Calculate the SHA256 library digest */ +static int calc_task_so_hash(unsigned char *digest, uint32_t dig_len, + struct task_struct *cur_struct, int so_index) +{ + struct mm_struct *mm = NULL; + int rc; + size_t size; + size_t shash_size; + struct sdesc *desc = NULL; + + if (!digest || dig_len != SHA256_DIGEST_LENTH) { + tloge("tee hash: digest is NULL\n"); + return -EFAULT; + } + + shash_size = crypto_shash_descsize(get_shash_handle()); + size = sizeof(desc->shash) + shash_size; + if (size < sizeof(desc->shash) || size < shash_size) { + tloge("size overflow\n"); + return -ENOMEM; + } + + desc = kzalloc(size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)desc)) { + tloge("alloc desc failed\n"); + return -ENOMEM; + } + + desc->shash.tfm = get_shash_handle(); + if (crypto_shash_init(&desc->shash)) { + kfree(desc); + return -EFAULT; + } + + mm = get_task_mm(cur_struct); + if (!mm) { + tloge("so does not have mm struct\n"); + if (memset_s(digest, MAX_SHA_256_SZ, 0, dig_len)) + tloge("memset digest failed\n"); + kfree(desc); + return -EFAULT; + } + + down_read(&mm_sem_lock(mm)); + rc = update_so_hash(mm, cur_struct, &desc->shash, so_index); + up_read(&mm_sem_lock(mm)); + mmput(mm); + if (!rc) + rc = crypto_shash_final(&desc->shash, digest); + kfree(desc); + return rc; +} + +static int proc_calc_hash(uint8_t kernel_api, struct tc_ns_session *session, + struct task_struct *cur_struct, uint32_t pub_key_len) +{ + int rc, i; + int so_found = 0; + + mutex_crypto_hash_lock(); + if (kernel_api == TEE_REQ_FROM_USER_MODE) { + for (i = 0; so_found < NUM_OF_SO && i < KIND_OF_SO; i++) { + rc = calc_task_so_hash(session->auth_hash_buf + MAX_SHA_256_SZ * so_found, + (uint32_t)SHA256_DIGEST_LENTH, cur_struct, i); + if (!rc) + so_found++; + } + if (so_found != NUM_OF_SO) + tlogd("so library found: %d\n", so_found); + } else { + tlogd("request from kernel\n"); + } + +#ifdef CONFIG_ASAN_DEBUG + tloge("so auth disabled for ASAN debug\n"); + uint32_t so_hash_len = MAX_SHA_256_SZ * NUM_OF_SO; + errno_t sret = memset_s(session->auth_hash_buf, so_hash_len, 0, so_hash_len); + if (sret) { + mutex_crypto_hash_unlock(); + tloge("memset so hash failed\n"); + return -EFAULT; + } +#endif + + rc = calc_task_hash(session->auth_hash_buf + MAX_SHA_256_SZ * NUM_OF_SO, + (uint32_t)SHA256_DIGEST_LENTH, cur_struct, pub_key_len); + if (rc) { + mutex_crypto_hash_unlock(); + tloge("tee calc ca hash failed\n"); + return -EFAULT; + } + mutex_crypto_hash_unlock(); + return EOK; +} + +int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, + struct tc_ns_client_context *context, struct tc_ns_session *session) +{ + int ret; + struct task_struct *cur_struct = NULL; + bool check = false; + check = (!dev_file || !context || !session); + if (check) { + tloge("bad params\n"); + return -EFAULT; + } + + if (tee_init_shash_handle("sha256")) { + tloge("init code hash error\n"); + return -EFAULT; + } + + cur_struct = current; + ret = proc_calc_hash(dev_file->kernel_api, session, cur_struct, dev_file->pub_key_len); + return ret; +} +#endif + +#ifdef CONFIG_AUTH_HASH +#define UID_LEN 16 +static int construct_hashdata(struct tc_ns_dev_file *dev_file, + uint8_t *buf, uint32_t buf_len) +{ + int ret; + ret = memcpy_s(buf, buf_len, dev_file->pkg_name, dev_file->pkg_name_len); + if (ret) { + tloge("memcpy_s failed\n"); + goto error; + } + buf += dev_file->pkg_name_len; + buf_len -= dev_file->pkg_name_len; + ret = memcpy_s(buf, buf_len, dev_file->pub_key, dev_file->pub_key_len); + if (ret) { + tloge("memcpy_s failed\n"); + goto error; + } + return 0; +error: + return -EFAULT; +} + +static struct sdesc_hash *init_sdesc(struct crypto_shash *alg) +{ + struct sdesc_hash *sdesc; + size_t size; + + size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); + sdesc = kmalloc(size, GFP_KERNEL); + if (sdesc == NULL) + return ERR_PTR(-ENOMEM); + sdesc->shash.tfm = alg; + return sdesc; +} + +static int calc_hash(struct crypto_shash *alg, + const unsigned char *data, unsigned int datalen, unsigned char *digest) +{ + struct sdesc_hash *sdesc; + int ret; + + sdesc = init_sdesc(alg); + if (IS_ERR(sdesc)) { + pr_info("can't alloc sdesc\n"); + return PTR_ERR(sdesc); + } + + ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); + kfree(sdesc); + return ret; +} + +static int do_sha256(const unsigned char *data, uint32_t datalen, + unsigned char *out_digest, uint8_t digest_len) +{ + int ret; + struct crypto_shash *alg; + const char *hash_alg_name = "sha256"; + if (digest_len != SHA256_DIGEST_LENGTH) { + tloge("error digest_len\n"); + return -1; + } + + alg = crypto_alloc_shash(hash_alg_name, 0, 0); + if(IS_ERR_OR_NULL(alg)) { + tloge("can't alloc alg %s, PTR_ERR alg is %ld\n", hash_alg_name, PTR_ERR(alg)); + return PTR_ERR(alg); + } + ret = calc_hash(alg, data, datalen, out_digest); + if (ret != 0) { + tloge("calc hash failed\n"); + crypto_free_shash(alg); + alg = NULL; + return -1; + } + crypto_free_shash(alg); + alg = NULL; + return 0; +} + +int set_login_information_hash(struct tc_ns_dev_file *hash_dev_file) +{ + int ret = 0; + uint8_t *indata = NULL; + if (hash_dev_file == NULL) { + tloge("wrong caller info, cal hash stopped\n"); + return -1; + } + mutex_lock(&hash_dev_file->cainfo_hash_setup_lock); + + if (!(hash_dev_file->cainfo_hash_setup)) { + unsigned char digest[SHA256_DIGEST_LENGTH] = {0}; + uint8_t digest_len = sizeof(digest); + + uint32_t indata_len; +#ifdef CONFIG_AUTH_SUPPORT_UNAME + /* username using fixed length to cal hash */ + if (hash_dev_file->pub_key_len >= FIXED_PKG_NAME_LENGTH) { + tloge("username is too loog\n"); + ret = -1; + goto error; + } + indata_len = hash_dev_file->pkg_name_len + FIXED_PKG_NAME_LENGTH; +#else + indata_len = hash_dev_file->pkg_name_len + hash_dev_file->pub_key_len; +#endif + indata = kzalloc(indata_len, GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)indata)) { + tloge("indata kmalloc fail\n"); + ret = -1; + goto error; + } + + ret = construct_hashdata(hash_dev_file, indata, indata_len); + if (ret != 0) { + tloge("construct hashdata failed\n"); + goto error; + } + + ret = do_sha256((unsigned char *)indata, indata_len, digest, digest_len); + if (ret != 0) { + tloge("do sha256 failed\n"); + goto error; + } + + ret = memcpy_s(hash_dev_file->pkg_name, MAX_PACKAGE_NAME_LEN, digest, digest_len); + if (ret != 0) { + tloge("memcpy_s failed\n"); + goto error; + } + hash_dev_file->pkg_name_len = SHA256_DIGEST_LENGTH; + hash_dev_file->cainfo_hash_setup = true; + } + +error: + if (!ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)indata)) + kfree(indata); + + mutex_unlock(&hash_dev_file->cainfo_hash_setup_lock); + return ret; +} +#endif + +#ifdef CONFIG_AUTH_SUPPORT_UNAME +#define PASSWD_FILE "/etc/passwd" +#define UID_POS 2U +#define DECIMAL 10 +static int uid_compare(uint32_t uid, const char* uid_str, uint32_t uid_len) +{ + uint32_t uid_num = 0; + for (uint32_t i = 0; i < uid_len; i++) { + bool is_number = uid_str[i] >= '0' && uid_str[i] <= '9'; + if (!is_number) { + tloge("passwd info wrong format: uid missing\n"); + return -1; + } + uid_num = DECIMAL * uid_num + (uid_str[i] - '0'); + } + return (uid_num == uid) ? 0 : -1; +} + +/* "username:[encrypted password]:uid:gid:[comments]:home directory:login shell" */ +static uint32_t parse_uname(uint32_t uid, char *username, int buffer_len) +{ + char *str = username; + char *token = strsep(&str, ":"); + char *temp_name = token; // first tokon is username, need to check uid + int index = 0; + while(token != NULL && index < UID_POS) { + token = strsep(&str, ":"); + index++; + } + if (token == NULL) + return -1; + if (uid_compare(uid, token, strlen(token)) != 0) + return -1; + if (strcpy_s(username, buffer_len, temp_name) != EOK) + return -1; + return strlen(temp_name); +} +static int read_line(char *buf, int buf_len, struct file *fp, loff_t *offset) +{ + ssize_t ret; + ssize_t i; + if (offset == NULL) { + tloge("offset is null while read file\n"); + return -1; + } + ret = kernel_read(fp, buf, buf_len, offset); + if (ret < 0) + return -1; + i = 0; + /* read buf_len, need to find first '\n' */ + while(i < ret) { + if (i >= buf_len) + break; + if (buf[i] == '\n') + break; + i++; + } + if (i < ret) + *offset -= (loff_t)(ret - i); + if (i < buf_len) + buf[i] = '\0'; + return 0; +} + +/* get username by uid, +* on linux, user info is stored in system file "/etc/passwd", +* each line represents a user, fields are separated by ':', +* formatted as such: "username:[encrypted password]:uid:gid:[comments]:home directory:login shell" +*/ +int tc_ns_get_uname(uint32_t uid, char *username, int buffer_len, uint32_t *out_len) +{ + struct file *f = NULL; + loff_t offset = 0; + if (username == NULL || out_len == NULL || buffer_len != FIXED_PKG_NAME_LENGTH) { + tloge("params is null\n"); + return -1; + } + f = filp_open(PASSWD_FILE, O_RDONLY, 0); + if (IS_ERR(f)) { + tloge("kernel open passwd file failed\n"); + return -1; + } + while (read_line(username, buffer_len, f, &offset) == 0) { + uint32_t ret = parse_uname(uid, username, buffer_len); + if (ret >= 0) { + *out_len = ret; + filp_close(f, NULL); + return 0; + } + } + filp_close(f, NULL); + return -1; +} +#endif diff --git a/auth/client_hash_auth.h b/auth/client_hash_auth.h index e7785f6e29ea2c1d3eb7a20c575a486c27f38b7c..2f610d40c15f986239c8390f5925210e2efae1f0 100644 --- a/auth/client_hash_auth.h +++ b/auth/client_hash_auth.h @@ -1,40 +1,54 @@ -/* - * client_hash_auth.h - * - * function definition for CA code hash auth - * - * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef CLIENT_HASH_CALC_H -#define CLIENT_HASH_CALC_H - -#include "tc_ns_client.h" -#include "teek_ns_client.h" - -#ifdef CONFIG_CLIENT_AUTH -#include "auth_base_impl.h" - -int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, - struct tc_ns_client_context *context, struct tc_ns_session *session); - -#else -static inline int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, - struct tc_ns_client_context *context, struct tc_ns_session *session) -{ - return 0; -} - -#endif - -#endif \ No newline at end of file +/* + * client_hash_auth.h + * + * function definition for CA code hash auth + * + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef CLIENT_HASH_CALC_H +#define CLIENT_HASH_CALC_H + +#include "tc_ns_client.h" +#include "teek_ns_client.h" + +#ifdef CONFIG_CLIENT_AUTH +#include "auth_base_impl.h" + +int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, + struct tc_ns_client_context *context, struct tc_ns_session *session); + +#else + +static inline int calc_client_auth_hash(struct tc_ns_dev_file *dev_file, + struct tc_ns_client_context *context, struct tc_ns_session *session) +{ + (void)dev_file; + (void)context; + (void)session; + return 0; +} + +#endif + +#ifdef CONFIG_AUTH_SUPPORT_UNAME +#define MAX_NAME_LENGTH 256 + +int tc_ns_get_uname(uint32_t uid, char *username, int buffer_len, uint32_t *out_len); +#endif + +#ifdef CONFIG_AUTH_HASH +int set_login_information_hash(struct tc_ns_dev_file *hash_dev_file); +#endif + +#endif diff --git a/core/agent.c b/core/agent.c index ec749e6d6310d2bee167f2689513a9ea14a9c804..7a1bee9f6ac30498413c1d231e92c29120b3dc8c 100644 --- a/core/agent.c +++ b/core/agent.c @@ -50,7 +50,8 @@ #include "tc_client_driver.h" #include "cmdmonitor.h" #include "ko_adapt.h" -#include "tz_kthread_affinity.h" +#include "internal_functions.h" +#include "auth_base_impl.h" #ifdef CONFIG_CMS_CAHASH_AUTH #define HASH_FILE_MAX_SIZE CONFIG_HASH_FILE_SIZE @@ -75,6 +76,7 @@ int __attribute__((weak)) is_allowed_agent_ca(const struct ca_info *ca, { (void)ca; (void)check_agent_id; + return -EFAULT; } @@ -106,13 +108,13 @@ char *get_proc_dpath(char *path, int path_len) return NULL; } - if (memset_s(path, path_len, '\0', MAX_PATH_SIZE)) { + if (memset_s(path, path_len, '\0', MAX_PATH_SIZE) != 0) { tloge("memset error\n"); return NULL; } mm = get_task_mm(current); - if (check_mm_struct(mm)) { + if (check_mm_struct(mm) != 0) { tloge("check mm_struct failed\n"); return NULL; } @@ -186,7 +188,7 @@ int check_ext_agent_access(uint32_t agent_id) struct ca_info agent_ca = { {0}, 0, 0 }; ret = get_ca_path_and_uid(&agent_ca); - if (ret) { + if (ret != 0) { tloge("get cp path or uid failed\n"); return ret; } @@ -219,16 +221,16 @@ static int send_set_smc_cmd(struct mb_cmd_pack *mb_pack, mb_pack->operation.paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); mb_pack->operation.params[0].value.a = - (unsigned int)virt_to_phys(buf_to_tee); + (unsigned int)mailbox_virt_to_phys((uintptr_t)buf_to_tee); mb_pack->operation.params[0].value.b = - (uint64_t)virt_to_phys(buf_to_tee) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)buf_to_tee) >> ADDR_TRANS_NUM; mb_pack->operation.params[1].value.a = buf_len; smc_cmd->cmd_type = CMD_TYPE_GLOBAL; smc_cmd->cmd_id = cmd_id; - smc_cmd->operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd->operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd->operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; - if (tc_ns_smc(smc_cmd)) { + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; + if (tc_ns_smc(smc_cmd) != 0) { ret = -EPERM; tloge("set native hash failed\n"); } @@ -245,15 +247,16 @@ int tc_ns_set_native_hash(unsigned long arg, unsigned int cmd_id) uint8_t *buf_to_tee = NULL; struct mb_cmd_pack *mb_pack = NULL; - if (!inbuf) - return -EINVAL; - - if (tc_ns_get_uid()) { - tloge("It is a fake tee agent\n"); + ret = check_teecd_auth(); + if (ret != 0) { + tloge("teecd auth failed, ret %d\n", ret); return -EACCES; } - if (get_buf_len(inbuf, &buf_len)) + if (!inbuf) + return -EINVAL; + + if (get_buf_len(inbuf, &buf_len) != 0) return -EFAULT; buf_to_tee = mailbox_alloc(buf_len, 0); @@ -289,11 +292,6 @@ int tc_ns_late_init(unsigned long arg) uint32_t index = (uint32_t)arg; /* index is uint32, no truncate risk */ struct mb_cmd_pack *mb_pack = NULL; - if (tc_ns_get_uid()) { - tloge("It is a fake tee agent\n"); - return -EACCES; - } - mb_pack = mailbox_alloc_cmd_pack(); if (!mb_pack) { tloge("alloc cmd pack failed\n"); @@ -305,9 +303,9 @@ int tc_ns_late_init(unsigned long arg) smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = GLOBAL_CMD_ID_LATE_INIT; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; if (tc_ns_smc(&smc_cmd)) { ret = -EPERM; @@ -371,7 +369,7 @@ static void unmap_agent_buffer(struct smc_event_data *event_data) return; if (vm_munmap((unsigned long)(uintptr_t)event_data->agent_buff_user, - event_data->agent_buff_size)) + event_data->agent_buff_size) != 0) tloge("unmap failed\n"); event_data->agent_buff_user = NULL; @@ -539,10 +537,6 @@ int tc_ns_wait_event(unsigned int agent_id) int ret = -EINVAL; struct smc_event_data *event_data = NULL; - if (tc_ns_get_uid() && check_ext_agent_access(agent_id)) { - tloge("It is a fake tee agent\n"); - return -EPERM; - } tlogd("agent %u waits for command\n", agent_id); event_data = find_event_control(agent_id); @@ -561,7 +555,6 @@ int tc_ns_sync_sys_time(const struct tc_ns_client_time *tc_ns_time) { struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; int ret = 0; - struct tc_ns_client_time tmp_tc_ns_time = {0}; struct mb_cmd_pack *mb_pack = NULL; if (!tc_ns_time) { @@ -569,17 +562,6 @@ int tc_ns_sync_sys_time(const struct tc_ns_client_time *tc_ns_time) return -EINVAL; } - if (tc_ns_get_uid()) { - tloge("It is a fake tee agent\n"); - return -EINVAL; - } - - if (copy_from_user(&tmp_tc_ns_time, tc_ns_time, - sizeof(tmp_tc_ns_time))) { - tloge("copy from user failed\n"); - return -EFAULT; - } - mb_pack = mailbox_alloc_cmd_pack(); if (!mb_pack) { tloge("alloc mb pack failed\n"); @@ -587,15 +569,14 @@ int tc_ns_sync_sys_time(const struct tc_ns_client_time *tc_ns_time) } mb_pack->operation.paramtypes = TEE_PARAM_TYPE_VALUE_INPUT; - mb_pack->operation.params[0].value.a = tmp_tc_ns_time.seconds; - mb_pack->operation.params[0].value.b = tmp_tc_ns_time.millis; + mb_pack->operation.params[0].value.a = tc_ns_time->seconds; + mb_pack->operation.params[0].value.b = tc_ns_time->millis; smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = GLOBAL_CMD_ID_ADJUST_TIME; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); - smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; - + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); + smc_cmd.operation_h_phys = + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; if (tc_ns_smc(&smc_cmd)) { tloge("tee adjust time failed, return error\n"); ret = -EPERM; @@ -605,6 +586,46 @@ int tc_ns_sync_sys_time(const struct tc_ns_client_time *tc_ns_time) return ret; } +int sync_system_time_from_user(const struct tc_ns_client_time *user_time) +{ + int ret = 0; + struct tc_ns_client_time time = { 0 }; + + if (!user_time) { + tloge("user time is NULL input buffer\n"); + return -EINVAL; + } + + if (copy_from_user(&time, user_time, sizeof(time))) { + tloge("copy from user failed\n"); + return -EFAULT; + } + + ret = tc_ns_sync_sys_time(&time); + if (ret != 0) + tloge("sync system time from user failed, ret = 0x%x\n", ret); + + return ret; +} + +void sync_system_time_from_kernel(void) +{ + int ret = 0; + struct tc_ns_client_time time = { 0 }; + + struct time_spec kernel_time = {0}; + get_time_spec(&kernel_time); + + time.seconds = (uint32_t)kernel_time.ts.tv_sec; + time.millis = (uint32_t)(kernel_time.ts.tv_nsec / MS_TO_NS); + + ret = tc_ns_sync_sys_time(&time); + if (ret != 0) + tloge("sync system time from kernel failed, ret = 0x%x\n", ret); + + return; +} + static struct smc_event_data *check_response_access(unsigned int agent_id) { struct smc_event_data *event_data = find_event_control(agent_id); @@ -613,20 +634,12 @@ static struct smc_event_data *check_response_access(unsigned int agent_id) tloge("Can't get event_data\n"); return NULL; } - - if (tc_ns_get_uid() && - check_ext_agent_access(agent_id)) { - tloge("It is a fake tee agent\n"); - put_agent_event(event_data); - return NULL; - } - return event_data; } static void process_send_event_response(struct smc_event_data *event_data) { - if (!event_data->ret_flag) + if (event_data->ret_flag == 0) return; event_data->ret_flag = 0; @@ -663,7 +676,7 @@ void send_event_response(unsigned int agent_id) return; } - tloge("agent 0x%x sends answer back\n", agent_id); + tlogi("agent 0x%x sends answer back\n", agent_id); atomic_set(&event_data->agent_ready, AGENT_CRASHED); process_send_event_response(event_data); put_agent_event(event_data); @@ -672,7 +685,7 @@ void send_event_response(unsigned int agent_id) static void init_restart_agent_node(struct tc_ns_dev_file *dev_file, struct smc_event_data *event_data) { - tloge("agent: 0x%x restarting\n", event_data->agent_id); + tlogi("agent: 0x%x restarting\n", event_data->agent_id); event_data->ret_flag = 0; event_data->owner = dev_file; atomic_set(&event_data->agent_ready, AGENT_REGISTERED); @@ -714,17 +727,6 @@ static int create_new_agent_node(struct tc_ns_dev_file *dev_file, return 0; } -static bool is_built_in_agent(unsigned int agent_id) -{ - if (agent_id == AGENT_FS_ID || - agent_id == AGENT_MISC_ID || - agent_id == AGENT_SOCKET_ID || - agent_id == SECFILE_LOAD_AGENT_ID) - return true; - - return false; -} - static unsigned long agent_buffer_map(unsigned long buffer, uint32_t size) { struct vm_area_struct *vma = NULL; @@ -747,7 +749,7 @@ static unsigned long agent_buffer_map(unsigned long buffer, uint32_t size) ret = remap_pfn_range(vma, user_addr, buffer >> PAGE_SHIFT, size, vma->vm_page_prot); - if (ret) { + if (ret != 0) { tloge("remap agent buffer failed, err=%d", ret); goto err_out; } @@ -764,12 +766,7 @@ err_out: static bool is_valid_agent(unsigned int agent_id, unsigned int buffer_size, bool user_agent) { - if (tc_ns_get_uid() && - check_ext_agent_access(agent_id)) { - tloge("It is a fake tee agent\n"); - return false; - } - + (void)agent_id; if (user_agent && (buffer_size > SZ_4K)) { tloge("size: %u of user agent's shared mem is invalid\n", buffer_size); @@ -797,9 +794,9 @@ static int is_agent_already_exist(unsigned int agent_id, flag = true; get_agent_event(agent_node); /* - * We find the agent event_data aready in agent_list, it indicate agent - * didn't unregister normally, so the event_data will be reused. - */ + * We find the agent event_data aready in agent_list, it indicate agent + * didn't unregister normally, so the event_data will be reused. + */ init_restart_agent_node(dev_file, agent_node); break; } @@ -837,15 +834,15 @@ static int register_agent_to_tee(unsigned int agent_id, const void *agent_buff, mb_pack->operation.paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); mb_pack->operation.params[0].value.a = - virt_to_phys(agent_buff); + mailbox_virt_to_phys((uintptr_t)agent_buff); mb_pack->operation.params[0].value.b = - (uint64_t)virt_to_phys(agent_buff) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)agent_buff) >> ADDR_TRANS_NUM; mb_pack->operation.params[1].value.a = agent_buff_size; smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = GLOBAL_CMD_ID_REGISTER_AGENT; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; smc_cmd.agent_id = agent_id; if (tc_ns_smc(&smc_cmd)) { @@ -864,7 +861,7 @@ static int get_agent_buffer(struct smc_event_data *event_data, if (user_agent) { event_data->agent_buff_user = (void *)(uintptr_t)agent_buffer_map( - virt_to_phys(event_data->agent_buff_kernel), + mailbox_virt_to_phys((uintptr_t)event_data->agent_buff_kernel), event_data->agent_buff_size); if (IS_ERR(event_data->agent_buff_user)) { tloge("vm map agent buffer failed\n"); @@ -899,11 +896,10 @@ int tc_ns_register_agent(struct tc_ns_dev_file *dev_file, if (is_agent_already_exist(agent_id, &event_data, dev_file, &find_flag)) return ret; - if (!find_flag) { ret = create_new_agent_node(dev_file, &event_data, agent_id, &agent_buff, size_align); - if (ret) + if (ret != 0) return ret; } @@ -917,7 +913,7 @@ int tc_ns_register_agent(struct tc_ns_dev_file *dev_file, * in tc_ns_unregister_agent */ ret = register_agent_to_tee(agent_id, agent_buff, size_align); - if (ret) { + if (ret != 0) { unmap_agent_buffer(event_data); goto release_rsrc; } @@ -938,30 +934,6 @@ release_rsrc: return ret; } -static int check_for_unregister_agent(unsigned int agent_id) -{ - bool check_value = false; - - if (tc_ns_get_uid() && tc_ns_get_uid() != SYSTEM_UID) { - tloge("It is a fake tee agent\n"); - return -EINVAL; - } - - check_value = is_built_in_agent(agent_id); - if (check_value) { - tloge("agent: 0x%x is not allowed to unregister\n", agent_id); - return -EINVAL; - } - - return 0; -} - -bool __attribute__((weak)) is_third_party_agent(unsigned int agent_id) -{ - (void)agent_id; - return false; -} - int tc_ns_unregister_agent(unsigned int agent_id) { struct smc_event_data *event_data = NULL; @@ -969,17 +941,6 @@ int tc_ns_unregister_agent(unsigned int agent_id) struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; struct mb_cmd_pack *mb_pack = NULL; - if (check_for_unregister_agent(agent_id)) - return -EINVAL; - /* - * if third party itself trigger unregister agent - * we allow them to unregister. - */ - if (!is_third_party_agent(agent_id)) { - tloge("invalid agent id: 0x%x\n", agent_id); - return -EACCES; - } - event_data = find_event_control(agent_id); if (!event_data || !event_data->agent_buff_kernel) { tloge("agent is not found or kaddr is not allocated\n"); @@ -995,19 +956,19 @@ int tc_ns_unregister_agent(unsigned int agent_id) mb_pack->operation.paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); mb_pack->operation.params[0].value.a = - virt_to_phys(event_data->agent_buff_kernel); + mailbox_virt_to_phys((uintptr_t)event_data->agent_buff_kernel); mb_pack->operation.params[0].value.b = - (uint64_t)virt_to_phys(event_data->agent_buff_kernel) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)event_data->agent_buff_kernel) >> ADDR_TRANS_NUM; mb_pack->operation.params[1].value.a = SZ_4K; smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = GLOBAL_CMD_ID_UNREGISTER_AGENT; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; smc_cmd.agent_id = agent_id; tlogd("unregistering agent 0x%x\n", agent_id); - if (!tc_ns_smc(&smc_cmd)) { + if (tc_ns_smc(&smc_cmd) == 0) { free_event_control(agent_id); } else { ret = -EPERM; @@ -1061,7 +1022,7 @@ void send_crashed_event_response_all(const struct tc_ns_dev_file *dev_file) spin_unlock_irqrestore(&g_agent_control.lock, flags); for (i = 0; i < AGENT_MAX; i++) { - if (agent_id[i]) + if (agent_id[i] != 0) send_event_response(agent_id[i]); } @@ -1095,19 +1056,19 @@ static int def_tee_agent_work(void *instance) while (!kthread_should_stop()) { tlogd("%s agent loop++++\n", agent_instance->agent_name); ret = tc_ns_wait_event(agent_instance->agent_id); - if (ret) { + if (ret != 0) { tloge("%s wait event fail\n", agent_instance->agent_name); break; } if (agent_instance->tee_agent_work) { ret = agent_instance->tee_agent_work(agent_instance); - if (ret) + if (ret != 0) tloge("%s agent work fail\n", agent_instance->agent_name); } ret = tc_ns_send_event_response(agent_instance->agent_id); - if (ret) { + if (ret != 0) { tloge("%s send event response fail\n", agent_instance->agent_name); break; @@ -1127,7 +1088,7 @@ static int def_tee_agent_run(struct tee_agent_kernel_ops *agent_instance) ret = tc_ns_register_agent(&dev, agent_instance->agent_id, agent_instance->agent_buff_size, &agent_instance->agent_buff, false); - if (ret) { + if (ret != 0) { tloge("register agent buffer fail,ret =0x%x\n", ret); ret = -EINVAL; goto out; @@ -1138,7 +1099,7 @@ static int def_tee_agent_run(struct tee_agent_kernel_ops *agent_instance) kthread_create(def_tee_agent_work, agent_instance, "agent_%s", agent_instance->agent_name); if (IS_ERR_OR_NULL(agent_instance->agent_thread)) { - tloge("kthread creat fail\n"); + tloge("kthread create fail\n"); ret = PTR_ERR(agent_instance->agent_thread); agent_instance->agent_thread = NULL; goto out; @@ -1155,11 +1116,11 @@ static int def_tee_agent_stop(struct tee_agent_kernel_ops *agent_instance) { int ret; - if (tc_ns_send_event_response(agent_instance->agent_id)) + if (tc_ns_send_event_response(agent_instance->agent_id) != 0) tloge("failed to send response for agent %u\n", agent_instance->agent_id); ret = tc_ns_unregister_agent(agent_instance->agent_id); - if (ret) + if (ret != 0) tloge("failed to unregister agent %u\n", agent_instance->agent_id); if (!IS_ERR_OR_NULL(agent_instance->agent_thread)) @@ -1210,7 +1171,7 @@ static int tee_agent_kernel_init(void) else tlogw("agent id %u has no init function\n", agent_ops->agent_id); - if (ret) { + if (ret != 0) { tloge("tee_agent_init %s failed\n", agent_ops->agent_name); continue; @@ -1225,7 +1186,7 @@ static int tee_agent_kernel_init(void) tlogw("agent id %u has no run function\n", agent_ops->agent_id); - if (ret) { + if (ret != 0) { tloge("tee_agent_run %s failed\n", agent_ops->agent_name); if (agent_ops->tee_agent_exit) @@ -1292,12 +1253,26 @@ void agent_init(void) INIT_LIST_HEAD(&g_agent_control.agent_list); INIT_LIST_HEAD(&g_tee_agent_list); - if (tee_agent_kernel_init()) + if (tee_agent_kernel_init() != 0) tloge("tee agent kernel init failed\n"); return; } -void agent_exit(void) +void free_agent(void) { + struct smc_event_data *event_data = NULL; + struct smc_event_data *temp = NULL; + unsigned long flags; + tee_agent_kernel_exit(); + + spin_lock_irqsave(&g_agent_control.lock, flags); + list_for_each_entry_safe(event_data, temp, &g_agent_control.agent_list, head) { + list_del(&event_data->head); + unmap_agent_buffer(event_data); + mailbox_free(event_data->agent_buff_kernel); + event_data->agent_buff_kernel = NULL; + kfree(event_data); + } + spin_unlock_irqrestore(&g_agent_control.lock, flags); } diff --git a/core/agent.h b/core/agent.h index 7e2a793f38dd895f93ff4da6405486c9750eebb0..190209700d3c85ae726ff55a3a359e9587223cdb 100644 --- a/core/agent.h +++ b/core/agent.h @@ -31,6 +31,7 @@ #define TEE_FACE_AGENT2_ID 0x46616345 /* face agent id */ #define TEE_VLTMM_AGENT_ID 0x564c544d /* vltmm agent id */ #define SYSTEM_UID 1000 +#define MS_TO_NS 1000000 enum agent_state_type { AGENT_CRASHED = 0, @@ -101,10 +102,10 @@ static inline void put_agent_event(struct smc_event_data *event_data) } } -int is_allowed_agent_ca(const struct ca_info *ca, bool check_agent_id); -bool is_third_party_agent(unsigned int agent_id); +int is_allowed_agent_ca(const struct ca_info *ca, + bool check_agent_id); void agent_init(void); -void agent_exit(void); +void free_agent(void); struct smc_event_data *find_event_control(unsigned int agent_id); void send_event_response(unsigned int agent_id); int agent_process_work(const struct tc_ns_smc_cmd *smc_cmd, unsigned int agent_id); @@ -118,12 +119,13 @@ void send_crashed_event_response_all(const struct tc_ns_dev_file *dev_file); int tc_ns_wait_event(unsigned int agent_id); int tc_ns_send_event_response(unsigned int agent_id); void send_event_response_single(const struct tc_ns_dev_file *dev_file); -int tc_ns_sync_sys_time(const struct tc_ns_client_time *tc_ns_time); +int sync_system_time_from_user(const struct tc_ns_client_time *user_time); +void sync_system_time_from_kernel(void); int tee_agent_clear_work(struct tc_ns_client_context *context, unsigned int dev_file_id); int tee_agent_kernel_register(struct tee_agent_kernel_ops *new_agent); bool is_system_agent(const struct tc_ns_dev_file *dev_file); void tee_agent_clear_dev_owner(const struct tc_ns_dev_file *dev_file); char *get_proc_dpath(char *path, int path_len); - +int check_ext_agent_access(uint32_t agent_id); #endif diff --git a/core/cmdmonitor.c b/core/cmdmonitor.c index 7b36c379c3f7fa0eb056b1805637f11cda529d31..aeb158fc21ae00cac31bad7a800da87e356a164c 100644 --- a/core/cmdmonitor.c +++ b/core/cmdmonitor.c @@ -33,16 +33,15 @@ #include "tc_ns_log.h" #include "smc_smp.h" +#include "internal_functions.h" #include "mailbox_mempool.h" #include "tlogger.h" #include "log_cfg_api.h" -#include "tz_kthread_affinity.h" static int g_cmd_need_archivelog; static LIST_HEAD(g_cmd_monitor_list); static int g_cmd_monitor_list_size; -/* report 2 hours */ -static const long long g_memstat_report_freq = 2 * 60 * 60 * 1000; + #define MAX_CMD_MONITOR_LIST 200 #define MAX_AGENT_CALL_COUNT 250 static DEFINE_MUTEX(g_cmd_monitor_lock); @@ -51,11 +50,12 @@ static DEFINE_MUTEX(g_cmd_monitor_lock); static struct workqueue_struct *g_cmd_monitor_wq; static struct delayed_work g_cmd_monitor_work; static struct delayed_work g_cmd_monitor_work_archive; -static struct delayed_work g_mem_stat; static int g_tee_detect_ta_crash; -static void get_time_spec(struct time_spec *time) +void get_time_spec(struct time_spec *time) { + if (!time) + return; #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) time->ts = current_kernel_time(); #else @@ -63,11 +63,6 @@ static void get_time_spec(struct time_spec *time) #endif } -static void schedule_memstat_work(struct delayed_work *work, unsigned long delay) -{ - schedule_delayed_work(work, delay); -} - static void schedule_cmd_monitor_work(struct delayed_work *work, unsigned long delay) { @@ -77,12 +72,7 @@ static void schedule_cmd_monitor_work(struct delayed_work *work, schedule_delayed_work(work, delay); } -void tzdebug_memstat(void) -{ - schedule_memstat_work(&g_mem_stat, usecs_to_jiffies(S_TO_MS)); -} - -void tzdebug_archivelog(void) +static void tz_archivelog(void) { schedule_cmd_monitor_work(&g_cmd_monitor_work_archive, usecs_to_jiffies(0)); @@ -92,7 +82,8 @@ void cmd_monitor_ta_crash(int32_t type) { g_tee_detect_ta_crash = ((type == TYPE_CRASH_TEE) ? TYPE_CRASH_TEE : TYPE_CRASH_TA); - tzdebug_archivelog(); + tz_archivelog(); + fault_monitor_start(type); } static int get_pid_name(pid_t pid, char *comm, size_t size) @@ -119,14 +110,14 @@ static int get_pid_name(pid_t pid, char *comm, size_t size) } sret = strncpy_s(comm, size, task->comm, strlen(task->comm)); - if (sret) - tloge("strncpy faild: errno = %d\n", sret); + if (sret != 0) + tloge("strncpy failed: errno = %d\n", sret); put_task_struct(task); return sret; } -bool is_thread_reported(unsigned int tid) +bool is_thread_reported(pid_t tid) { bool ret = false; struct cmd_monitor *monitor = NULL; @@ -165,12 +156,11 @@ void cmd_monitor_reset_context(void) } /* -* if one session timeout, monitor will print timedifs every step[N] in seconds, -* if lasted more than 360s, monitor will print timedifs every 360 seconds -*/ + * if one session timeout, monitor will print timedifs every step[n] in seconds, + * if lasted more then 360s, monitor will print timedifs every 360s. + */ const int32_t g_timer_step[] = {1, 1, 1, 2, 5, 10, 40, 120, 180, 360}; const int32_t g_timer_nums = sizeof(g_timer_step) / sizeof(int32_t); - static void show_timeout_cmd_info(struct cmd_monitor *monitor) { long long timedif, timedif2; @@ -194,24 +184,29 @@ static void show_timeout_cmd_info(struct cmd_monitor *monitor) monitor->pid, monitor->pname, monitor->tid, monitor->tname, monitor->lastcmdid, monitor->agent_call_count, timedif); + /* threads out of white table need info dump */ + tlogw("monitor: pid-%d", monitor->pid); + if (!is_tui_in_use(monitor->tid)) { + show_cmd_bitmap(); + g_cmd_need_archivelog = 1; + wakeup_tc_siq(SIQ_DUMP_TIMEOUT); + } } - timedif2 = S_TO_MS * (nowtime.ts.tv_sec - monitor->lasttime.ts.tv_sec) + + timedif2 = S_TO_MS * (nowtime.ts.tv_sec - monitor->lasttime.ts.tv_sec) + (nowtime.ts.tv_nsec - monitor->lasttime.ts.tv_nsec) / S_TO_US; time_in_sec = monitor->timer_index >= g_timer_nums ? g_timer_step[g_timer_nums - 1] : g_timer_step[monitor->timer_index]; - if (timedif2 > time_in_sec * S_TO_MS) { monitor->lasttime = nowtime; - monitor->timer_index = monitor->timer_index >= sizeof(g_timer_step) ? - sizeof(g_timer_step) : (monitor->timer_index + 1); + monitor->timer_index = monitor->timer_index >= (int32_t)sizeof(g_timer_step) ? + (int32_t)sizeof(g_timer_step) : (monitor->timer_index + 1); tlogw("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, " "lastcmdid=%u,agent call count:%d,timedif=%lld ms\n", monitor->pid, monitor->pname, monitor->tid, monitor->lastcmdid, monitor->agent_call_count, timedif); } - } static void cmd_monitor_tick(void) @@ -223,7 +218,7 @@ static void cmd_monitor_tick(void) list_for_each_entry_safe(monitor, tmp, &g_cmd_monitor_list, list) { if (monitor->returned) { g_cmd_monitor_list_size--; - tlogi("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, " + tlogd("[cmd_monitor_tick] pid=%d,pname=%s,tid=%d, " "tname=%s,lastcmdid=%u,count=%d,agent call count=%d, " "timetotal=%lld us returned, remained command(s)=%d\n", monitor->pid, monitor->pname, monitor->tid, monitor->tname, @@ -271,7 +266,7 @@ static struct cmd_monitor *init_monitor_locked(void) newitem = kzalloc(sizeof(*newitem), GFP_KERNEL); if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)newitem)) { - tloge("[cmd_monitor_tick]kzalloc faild\n"); + tloge("[cmd_monitor_tick]kzalloc failed\n"); return NULL; } @@ -285,10 +280,10 @@ static struct cmd_monitor *init_monitor_locked(void) newitem->pid = current->tgid; newitem->tid = current->pid; if (get_pid_name(newitem->pid, newitem->pname, - sizeof(newitem->pname))) + sizeof(newitem->pname)) != 0) newitem->pname[0] = '\0'; if (get_pid_name(newitem->tid, newitem->tname, - sizeof(newitem->tname))) + sizeof(newitem->tname)) != 0) newitem->tname[0] = '\0'; INIT_LIST_HEAD(&newitem->list); list_add_tail(&newitem->list, &g_cmd_monitor_list); @@ -329,8 +324,7 @@ struct cmd_monitor *cmd_monitor_log(const struct tc_ns_smc_cmd *cmd) if (!found_flag) { #ifndef CONFIG_BIG_SESSION - if (g_cmd_monitor_list_size > - MAX_CMD_MONITOR_LIST - 1) { + if (g_cmd_monitor_list_size > MAX_CMD_MONITOR_LIST - 1) { tloge("monitor reach max node num\n"); monitor = NULL; break; @@ -397,3 +391,24 @@ void init_cmd_monitor(void) INIT_DEFERRABLE_WORK((struct delayed_work *) (uintptr_t)&g_cmd_monitor_work_archive, cmd_monitor_archivefn); } + +void free_cmd_monitor(void) +{ + struct cmd_monitor *monitor = NULL; + struct cmd_monitor *tmp = NULL; + + mutex_lock(&g_cmd_monitor_lock); + list_for_each_entry_safe(monitor, tmp, &g_cmd_monitor_list, list) { + list_del(&monitor->list); + kfree(monitor); + } + mutex_unlock(&g_cmd_monitor_lock); + + flush_delayed_work(&g_cmd_monitor_work); + flush_delayed_work(&g_cmd_monitor_work_archive); + if (g_cmd_monitor_wq) { + flush_workqueue(g_cmd_monitor_wq); + destroy_workqueue(g_cmd_monitor_wq); + g_cmd_monitor_wq = NULL; + } +} diff --git a/core/cmdmonitor.h b/core/cmdmonitor.h index d43eeae53cdc1edc195cb69ef5a39634c7648979..a04a0f5e545e9ad0e9d04151e54c114c01eda5a0 100644 --- a/core/cmdmonitor.h +++ b/core/cmdmonitor.h @@ -19,6 +19,7 @@ #define CMD_MONITOR_H #include "teek_ns_client.h" +#include "smc_smp.h" #include #if (KERNEL_VERSION(4, 14, 0) > LINUX_VERSION_CODE) @@ -67,11 +68,11 @@ struct cmd_monitor *cmd_monitor_log(const struct tc_ns_smc_cmd *cmd); void cmd_monitor_reset_context(void); void cmd_monitor_logend(struct cmd_monitor *item); void init_cmd_monitor(void); +void free_cmd_monitor(void); void do_cmd_need_archivelog(void); -bool is_thread_reported(unsigned int tid); +bool is_thread_reported(pid_t tid); void tzdebug_archivelog(void); void cmd_monitor_ta_crash(int32_t type); -void memstat_report(void); -void tzdebug_memstat(void); +void get_time_spec(struct time_spec *time); #endif diff --git a/core/gp_ops.c b/core/gp_ops.c index 80cd76720410ca59e903dee4e8f1ee1e67c934d5..74848110a70d00ffb6efc647e9bd2d65b6b4c3cf 100644 --- a/core/gp_ops.c +++ b/core/gp_ops.c @@ -43,6 +43,7 @@ #include "mem.h" #include "mailbox_mempool.h" #include "tc_client_driver.h" +#include "internal_functions.h" #include "reserved_mempool.h" #include "tlogger.h" @@ -140,15 +141,6 @@ bool is_val_param(uint32_t param_type) return false; } -bool is_ion_param(uint32_t param_type) -{ - if (param_type == TEEC_ION_INPUT || - param_type == TEEC_ION_SGLIST_INPUT) - return true; - - return false; -} - static bool is_mem_param(uint32_t param_type) { if (is_tmp_mem(param_type) || is_ref_mem(param_type)) @@ -158,59 +150,55 @@ static bool is_mem_param(uint32_t param_type) } /* Check the size and buffer addresses have valid userspace addresses */ -static bool is_usr_refmem_valid(union tc_ns_client_param *client_param) +static bool is_usr_refmem_valid(const union tc_ns_client_param *client_param) { uint32_t size = 0; + uint64_t size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); + uint64_t buffer_addr = client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM); #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 18) || \ LINUX_VERSION_CODE == KERNEL_VERSION(4, 19, 71)) - if (!access_ok(VERIFY_READ, - (void *)(uintptr_t)client_param->memref.size_addr, - sizeof(uint32_t))) + if (access_ok(VERIFY_READ, (void *)(uintptr_t)size_addr, sizeof(uint32_t)) == 0) #else - if (!access_ok( - (void *)(uintptr_t)client_param->memref.size_addr, - sizeof(uint32_t))) + if (access_ok((void *)(uintptr_t)size_addr, sizeof(uint32_t)) == 0) #endif return false; - get_user(size, (uint32_t *)(uintptr_t)client_param->memref.size_addr); + get_user(size, (uint32_t *)(uintptr_t)size_addr); #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 18) || \ LINUX_VERSION_CODE == KERNEL_VERSION(4, 19, 71)) - if (!access_ok(VERIFY_READ, - (void *)(uintptr_t)client_param->memref.buffer, size)) + if (access_ok(VERIFY_READ, (void *)(uintptr_t)buffer_addr, size) == 0) #else - if (!access_ok((void *)(uintptr_t)client_param->memref.buffer, size)) + if (access_ok((void *)(uintptr_t)buffer_addr, size) == 0) #endif return false; return true; } -static bool is_usr_valmem_valid(union tc_ns_client_param *client_param) +static bool is_usr_valmem_valid(const union tc_ns_client_param *client_param) { + uint64_t a_addr = client_param->value.a_addr | + ((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM); + uint64_t b_addr = client_param->value.b_addr | + ((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 18) || \ LINUX_VERSION_CODE == KERNEL_VERSION(4, 19, 71)) - if (!access_ok(VERIFY_READ, - (void *)(uintptr_t)client_param->value.a_addr, - sizeof(uint32_t))) + if (access_ok(VERIFY_READ, (void *)(uintptr_t)a_addr, sizeof(uint32_t)) == 0) #else - if (!access_ok( - (void *)(uintptr_t)client_param->value.a_addr, - sizeof(uint32_t))) + if (access_ok((void *)(uintptr_t)a_addr, sizeof(uint32_t)) == 0) #endif return false; #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 18) || \ LINUX_VERSION_CODE == KERNEL_VERSION(4, 19, 71)) - if (!access_ok(VERIFY_READ, - (void *)(uintptr_t)client_param->value.b_addr, - sizeof(uint32_t))) + if (access_ok(VERIFY_READ, (void *)(uintptr_t)b_addr, sizeof(uint32_t)) == 0) #else - if (!access_ok( - (void *)(uintptr_t)client_param->value.b_addr, - sizeof(uint32_t))) + if (access_ok((void *)(uintptr_t)b_addr, sizeof(uint32_t)) == 0) #endif return false; @@ -223,7 +211,7 @@ bool tc_user_param_valid(struct tc_ns_client_context *client_context, union tc_ns_client_param *client_param = NULL; unsigned int param_type; - if (check_user_param(client_context, index)) + if (check_user_param(client_context, index) != 0) return false; client_param = &(client_context->params[index]); @@ -266,10 +254,10 @@ int read_from_client(void *dest, size_t dest_size, tloge("size is larger than dest_size or size is 0\n"); return -EINVAL; } - if (!size) + if (size == 0) return 0; - if (kernel_api) { + if (kernel_api != 0) { ret = memcpy_s(dest, dest_size, src, size); if (ret != EOK) { tloge("memcpy fail. line=%d, s_ret=%d\n", @@ -279,7 +267,7 @@ int read_from_client(void *dest, size_t dest_size, return ret; } /* buffer is in user space(CA call TEE API) */ - if (copy_from_user(dest, src, size)) { + if (copy_from_user(dest, src, size) != 0) { tloge("copy from user failed\n"); return -EFAULT; } @@ -302,10 +290,10 @@ int write_to_client(void __user *dest, size_t dest_size, return -EINVAL; } - if (!size) + if (size == 0) return 0; - if (kernel_api) { + if (kernel_api != 0) { ret = memcpy_s(dest, dest_size, src, size); if (ret != EOK) { tloge("write to client fail. line=%d, ret=%d\n", @@ -316,7 +304,7 @@ int write_to_client(void __user *dest, size_t dest_size, } /* buffer is in user space(CA call TEE API) */ - if (copy_to_user(dest, src, size)) { + if (copy_to_user(dest, src, size) != 0) { tloge("copy to user failed\n"); return -EFAULT; } @@ -336,12 +324,15 @@ static int update_input_data(const union tc_ns_client_param *client_param, uint32_t buffer_size, void *temp_buf, unsigned int param_type, uint8_t kernel_params) { + uint64_t buffer_addr; if (!is_input_tempmem(param_type)) return 0; + buffer_addr = client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM); if (read_from_client(temp_buf, buffer_size, - (void *)(uintptr_t)client_param->memref.buffer, - buffer_size, kernel_params)) { + (void *)(uintptr_t)buffer_addr, + buffer_size, kernel_params) != 0) { tloge("copy memref buffer failed\n"); return -EFAULT; } @@ -359,6 +350,7 @@ static int alloc_for_tmp_mem(const struct tc_call_params *call_params, union tc_ns_client_param *client_param = NULL; void *temp_buf = NULL; uint32_t buffer_size = 0; + uint64_t size_addr; /* this never happens */ if (index >= TEE_PARAM_NUM) @@ -366,9 +358,11 @@ static int alloc_for_tmp_mem(const struct tc_call_params *call_params, /* For compatibility sake we assume buffer size to be 32bits */ client_param = &(call_params->context->params[index]); + size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); if (read_from_client(&buffer_size, sizeof(buffer_size), - (uint32_t __user *)(uintptr_t)client_param->memref.size_addr, - sizeof(uint32_t), kernel_params)) { + (uint32_t __user *)(uintptr_t)size_addr, + sizeof(uint32_t), kernel_params) != 0) { tloge("copy memref.size_addr failed\n"); return -EFAULT; } @@ -378,6 +372,18 @@ static int alloc_for_tmp_mem(const struct tc_call_params *call_params, return -EFAULT; } + op_params->mb_pack->operation.params[index].memref.size = buffer_size; + /* TEEC_MEMREF_TEMP_INPUT equal to TEE_PARAM_TYPE_MEMREF_INPUT */ + op_params->trans_paramtype[index] = param_type; + + if (buffer_size == 0) { + op_params->local_tmpbuf[index].temp_buffer = NULL; + op_params->local_tmpbuf[index].size = 0; + op_params->mb_pack->operation.params[index].memref.buffer = 0; + op_params->mb_pack->operation.buffer_h_addr[index] = 0; + return 0; + } + temp_buf = mailbox_alloc(buffer_size, MB_FLAG_ZERO); if (!temp_buf) { tloge("temp buf malloc failed, i = %u\n", index); @@ -387,16 +393,13 @@ static int alloc_for_tmp_mem(const struct tc_call_params *call_params, op_params->local_tmpbuf[index].size = buffer_size; if (update_input_data(client_param, buffer_size, temp_buf, - param_type, kernel_params)) + param_type, kernel_params) != 0) return -EFAULT; op_params->mb_pack->operation.params[index].memref.buffer = - virt_to_phys(temp_buf); + mailbox_virt_to_phys((uintptr_t)temp_buf); op_params->mb_pack->operation.buffer_h_addr[index] = - (uint64_t)virt_to_phys(temp_buf) >> ADDR_TRANS_NUM; - op_params->mb_pack->operation.params[index].memref.size = buffer_size; - /* TEEC_MEMREF_TEMP_INPUT equal to TEE_PARAM_TYPE_MEMREF_INPUT */ - op_params->trans_paramtype[index] = param_type; + (unsigned int)(mailbox_virt_to_phys((uintptr_t)temp_buf) >> ADDR_TRANS_NUM); return 0; } @@ -404,9 +407,11 @@ static int alloc_for_tmp_mem(const struct tc_call_params *call_params, static int check_buffer_for_ref(uint32_t *buffer_size, const union tc_ns_client_param *client_param, uint8_t kernel_params) { + uint64_t size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); if (read_from_client(buffer_size, sizeof(*buffer_size), - (uint32_t __user *)(uintptr_t)client_param->memref.size_addr, - sizeof(uint32_t), kernel_params)) { + (uint32_t __user *)(uintptr_t)size_addr, + sizeof(uint32_t), kernel_params) != 0) { tloge("copy memref.size_addr failed\n"); return -EFAULT; } @@ -417,8 +422,8 @@ static int check_buffer_for_ref(uint32_t *buffer_size, return 0; } -static bool is_refmem_offset_valid(struct tc_ns_shared_mem *shared_mem, - union tc_ns_client_param *client_param, uint32_t buffer_size) +static bool is_refmem_offset_valid(const struct tc_ns_shared_mem *shared_mem, + const union tc_ns_client_param *client_param, uint32_t buffer_size) { /* * arbitrary CA can control offset by ioctl, so in here @@ -431,15 +436,15 @@ static bool is_refmem_offset_valid(struct tc_ns_shared_mem *shared_mem, return false; } -static bool is_phyaddr_valid(struct tc_ns_operation *operation, int index) +static bool is_phyaddr_valid(const struct tc_ns_operation *operation, int index) { /* * for 8G physical memory device, there is a chance that * operation->params[i].memref.buffer could be all 0, * buffer_h_addr cannot be 0 in the same time. */ - if ((!operation->params[index].memref.buffer) && - (!operation->buffer_h_addr[index])) { + if ((operation->params[index].memref.buffer == 0) && + (operation->buffer_h_addr[index]) == 0) { tloge("can not find shared buffer, exit\n"); return false; } @@ -447,26 +452,26 @@ static bool is_phyaddr_valid(struct tc_ns_operation *operation, int index) return true; } -static int set_operation_buffer(struct tc_ns_shared_mem *shared_mem, void *buffer_addr, +static int set_operation_buffer(const struct tc_ns_shared_mem *shared_mem, void *buffer_addr, uint32_t buffer_size, unsigned int index, struct tc_op_params *op_params) { if (shared_mem->mem_type == RESERVED_TYPE) { /* no copy to mailbox */ op_params->mb_pack->operation.mb_buffer[index] = buffer_addr; - op_params->mb_pack->operation.params[index].memref.buffer = + op_params->mb_pack->operation.params[index].memref.buffer = res_mem_virt_to_phys((uintptr_t)buffer_addr); - op_params->mb_pack->operation.buffer_h_addr[index] = + op_params->mb_pack->operation.buffer_h_addr[index] = res_mem_virt_to_phys((uintptr_t)buffer_addr) >> ADDR_TRANS_NUM; } else { - buffer_addr = mailbox_copy_alloc(buffer_addr, buffer_size); - if (buffer_addr == NULL) + void *tmp_buffer_addr = mailbox_copy_alloc(buffer_addr, buffer_size); + if (tmp_buffer_addr == NULL) return -ENOMEM; - op_params->mb_pack->operation.mb_buffer[index] = buffer_addr; + op_params->mb_pack->operation.mb_buffer[index] = tmp_buffer_addr; op_params->mb_pack->operation.params[index].memref.buffer = - virt_to_phys(buffer_addr); - op_params->mb_pack->operation.buffer_h_addr[index] = - (uint64_t)virt_to_phys(buffer_addr) >> ADDR_TRANS_NUM; + (unsigned int)mailbox_virt_to_phys((uintptr_t)tmp_buffer_addr); + op_params->mb_pack->operation.buffer_h_addr[index] = + (unsigned int)((uint64_t)mailbox_virt_to_phys((uintptr_t)tmp_buffer_addr) >> ADDR_TRANS_NUM); } return 0; } @@ -491,7 +496,7 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, return -EINVAL; client_param = &(call_params->context->params[index]); - if (check_buffer_for_ref(&buffer_size, client_param, kernel_params)) + if (check_buffer_for_ref(&buffer_size, client_param, kernel_params) != 0) return -EINVAL; op_params->mb_pack->operation.params[index].memref.buffer = 0; @@ -499,8 +504,9 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, mutex_lock(&call_params->dev->shared_mem_lock); list_for_each_entry(shared_mem, &call_params->dev->shared_mem_list, head) { - if (shared_mem->user_addr != - (void *)(uintptr_t)client_param->memref.buffer) + buffer_addr = (void *)(uintptr_t)(client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM)); + if (shared_mem->user_addr != buffer_addr) continue; if (!is_refmem_offset_valid(shared_mem, client_param, buffer_size)) { @@ -509,13 +515,12 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, buffer_addr = (void *)(uintptr_t)( (uintptr_t)shared_mem->kernel_addr + client_param->memref.offset); - + ret = set_operation_buffer(shared_mem, buffer_addr, buffer_size, index, op_params); - if (ret) { + if (ret != 0) { tloge("set operation buffer failed\n"); break; } - op_params->mb_pack->operation.sharemem[index] = shared_mem; get_sharemem_struct(shared_mem); break; @@ -532,8 +537,8 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, op_params->trans_paramtype[index] = param_type - (TEEC_MEMREF_PARTIAL_INPUT - TEE_PARAM_TYPE_MEMREF_INPUT); - if (shared_mem->mem_type == RESERVED_TYPE) - op_params->trans_paramtype[index] += + if (shared_mem->mem_type == RESERVED_TYPE) + op_params->trans_paramtype[index] += (TEE_PARAM_TYPE_RESMEM_INPUT - TEE_PARAM_TYPE_MEMREF_INPUT); return ret; } @@ -550,11 +555,11 @@ static int fill_shared_mem_info(void *start_vaddr, uint32_t pages_no, if (pages_no == 0) return -EFAULT; - + pages = (struct page **)vmalloc(pages_no * sizeof(uint64_t)); if (pages == NULL) return -EFAULT; - + down_read(&mm_sem_lock(current->mm)); page_num = get_user_pages((uintptr_t)start_vaddr, pages_no, FOLL_WRITE, pages, NULL); up_read(&mm_sem_lock(current->mm)); @@ -572,7 +577,7 @@ static int fill_shared_mem_info(void *start_vaddr, uint32_t pages_no, page_info->sharedmem_offset = offset; page_info->sharedmem_size = buffer_size; - phys_addr = (uint64_t*)buff + (sizeof(*page_info) / sizeof(uint64_t)); + phys_addr = (uint64_t *)buff + (sizeof(*page_info) / sizeof(uint64_t)); for (i = 0; i < pages_no; i++) { struct page *page = pages[i]; if (page == NULL) { @@ -587,14 +592,18 @@ static int fill_shared_mem_info(void *start_vaddr, uint32_t pages_no, return 0; } -static int check_buffer_for_sharedmem(uint32_t* buffer_size, +static int check_buffer_for_sharedmem(uint32_t *buffer_size, const union tc_ns_client_param *client_param, uint8_t kernel_params) { + uint64_t size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); + uint64_t buffer_addr = client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM); if (read_from_client(buffer_size, sizeof(*buffer_size), - (uint32_t __user *)(uintptr_t)client_param->memref.size_addr, + (uint32_t __user *)(uintptr_t)size_addr, sizeof(uint32_t), kernel_params)) { - tloge("copy size_addr failed\n"); - return -EFAULT; + tloge("copy size_addr failed\n"); + return -EFAULT; } if (*buffer_size == 0 || *buffer_size > SZ_256M) { @@ -602,18 +611,17 @@ static int check_buffer_for_sharedmem(uint32_t* buffer_size, return -ENOMEM; } - if ((client_param->memref.offset >= SZ_256M) || - (UINT64_MAX - client_param->memref.buffer <= client_param->memref.offset)) { - tloge("invalid buff or offset\n"); - return -EFAULT; - } - + if ((client_param->memref.offset >= SZ_256M) || + (UINT64_MAX - buffer_addr <= client_param->memref.offset)) { + tloge("invalid buff or offset\n"); + return -EFAULT; + } return 0; } -static int transfer_shared_mem(const struct tc_call_params *call_params, +static int transfer_shared_mem(const struct tc_call_params *call_params, struct tc_op_params *op_params, uint8_t kernel_params, - uint32_t param_type, unsigned int index) + uint32_t param_type, unsigned int index) { void *buff = NULL; void *start_vaddr = NULL; @@ -622,15 +630,18 @@ static int transfer_shared_mem(const struct tc_call_params *call_params, uint32_t pages_no; uint32_t offset; uint32_t buff_len; + uint64_t buffer_addr; - if (index >= TEE_PARAM_NUM) + if (index >= TEE_PARAM_NUM) return -EINVAL; - + client_param = &(call_params->context->params[index]); if (check_buffer_for_sharedmem(&buffer_size, client_param, kernel_params)) return -EINVAL; - - buff = (void *)(uint64_t)(client_param->memref.buffer + client_param->memref.offset); + + buffer_addr = client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM); + buff = (void *)(uint64_t)(buffer_addr + client_param->memref.offset); start_vaddr = (void *)(((uint64_t)buff) & PAGE_MASK); offset = ((uint32_t)(uintptr_t)buff) & (~PAGE_MASK); pages_no = PAGE_ALIGN(offset + buffer_size) / PAGE_SIZE; @@ -639,7 +650,7 @@ static int transfer_shared_mem(const struct tc_call_params *call_params, buff = mailbox_alloc(buff_len, MB_FLAG_ZERO); if (buff == NULL) return -EFAULT; - + if (fill_shared_mem_info(start_vaddr, pages_no, offset, buffer_size, buff)) { mailbox_free(buff); return -EFAULT; @@ -648,17 +659,22 @@ static int transfer_shared_mem(const struct tc_call_params *call_params, op_params->local_tmpbuf[index].temp_buffer = buff; op_params->local_tmpbuf[index].size = buff_len; - op_params->mb_pack->operation.params[index].memref.buffer = virt_to_phys(buff); - op_params->mb_pack->operation.buffer_h_addr[index] = (uint64_t)virt_to_phys(buff) >> ADDR_TRANS_NUM; + op_params->mb_pack->operation.params[index].memref.buffer = mailbox_virt_to_phys((uintptr_t)buff); + op_params->mb_pack->operation.buffer_h_addr[index] = (uint64_t)mailbox_virt_to_phys((uintptr_t)buff) >> ADDR_TRANS_NUM; op_params->mb_pack->operation.params[index].memref.size = buff_len; op_params->trans_paramtype[index] = param_type; return 0; } #else -static int transfer_shared_mem(const struct tc_call_params *call_params, - struct tc_op_params *op_params, uint8_t kernel_params, - uint32_t param_type, unsigned int index) +static int transfer_shared_mem(const struct tc_call_params *call_params, + const struct tc_op_params *op_params, uint8_t kernel_params, + uint32_t param_type, unsigned int index) { + (void)call_params; + (void)op_params; + (void)kernel_params; + (void)param_type; + (void)index; tloge("invalid shared mem type\n"); return -1; } @@ -670,25 +686,31 @@ static int transfer_client_value(const struct tc_call_params *call_params, { struct tc_ns_operation *operation = &op_params->mb_pack->operation; union tc_ns_client_param *client_param = NULL; + uint64_t a_addr, b_addr; /* this never happens */ if (index >= TEE_PARAM_NUM) return -EINVAL; client_param = &(call_params->context->params[index]); + a_addr = client_param->value.a_addr | + ((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM); + b_addr = client_param->value.b_addr | + ((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM); + if (read_from_client(&operation->params[index].value.a, sizeof(operation->params[index].value.a), - (void *)(uintptr_t)client_param->value.a_addr, + (void *)(uintptr_t)a_addr, sizeof(operation->params[index].value.a), - kernel_params)) { + kernel_params) != 0) { tloge("copy valuea failed\n"); return -EFAULT; } if (read_from_client(&operation->params[index].value.b, sizeof(operation->params[index].value.b), - (void *)(uintptr_t)client_param->value.b_addr, + (void *)(uintptr_t)b_addr, sizeof(operation->params[index].value.b), - kernel_params)) { + kernel_params) != 0) { tloge("copy valueb failed\n"); return -EFAULT; } @@ -698,22 +720,6 @@ static int transfer_client_value(const struct tc_call_params *call_params, return 0; } -static int alloc_for_ion_sglist(const struct tc_call_params *call_params, - struct tc_op_params *op_params, uint8_t kernel_params, - uint32_t param_type, unsigned int index) -{ - tloge("not support seg and releated feature!\n"); - return -1; -} - -static inline int alloc_for_ion(const struct tc_call_params *call_params, - struct tc_op_params *op_params, uint8_t kernel_params, - uint32_t param_type, unsigned int index) -{ - tloge("not support ion and releated feature!\n"); - return -1; -} - static int alloc_operation(const struct tc_call_params *call_params, struct tc_op_params *op_params) { @@ -758,10 +764,10 @@ static int alloc_operation(const struct tc_call_params *call_params, else tlogd("param type = TEEC_NONE\n"); - if (ret) + if (ret != 0) break; } - if (ret) { + if (ret != 0) { free_operation(call_params, op_params); return ret; } @@ -776,11 +782,12 @@ static int alloc_operation(const struct tc_call_params *call_params, } static int update_tmp_mem(const struct tc_call_params *call_params, - struct tc_op_params *op_params, unsigned int index, bool is_complete) + const struct tc_op_params *op_params, unsigned int index, bool is_complete) { union tc_ns_client_param *client_param = NULL; uint32_t buffer_size; struct tc_ns_operation *operation = &op_params->mb_pack->operation; + uint64_t size_addr, buffer_addr; if (index >= TEE_PARAM_NUM) { tloge("tmp buf size or index is invalid\n"); @@ -789,11 +796,15 @@ static int update_tmp_mem(const struct tc_call_params *call_params, buffer_size = operation->params[index].memref.size; client_param = &(call_params->context->params[index]); + size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); + buffer_addr = client_param->memref.buffer | + ((uint64_t)client_param->memref.buffer_h_addr << ADDR_TRANS_NUM); /* Size is updated all the time */ - if (write_to_client((void *)(uintptr_t)client_param->memref.size_addr, + if (write_to_client((void *)(uintptr_t)size_addr, sizeof(buffer_size), &buffer_size, sizeof(buffer_size), - call_params->dev->kernel_api)) { + call_params->dev->kernel_api) != 0) { tloge("copy tempbuf size failed\n"); return -EFAULT; } @@ -808,12 +819,14 @@ static int update_tmp_mem(const struct tc_call_params *call_params, tloge("memref.size has been changed larger than the initial\n"); return -EFAULT; } + if (buffer_size == 0) + return 0; /* Only update the buffer when the buffer size is valid in complete case */ - if (write_to_client((void *)(uintptr_t)client_param->memref.buffer, + if (write_to_client((void *)(uintptr_t)buffer_addr, operation->params[index].memref.size, op_params->local_tmpbuf[index].temp_buffer, operation->params[index].memref.size, - call_params->dev->kernel_api)) { + call_params->dev->kernel_api) != 0) { tloge("copy tempbuf failed\n"); return -ENOMEM; } @@ -821,12 +834,13 @@ static int update_tmp_mem(const struct tc_call_params *call_params, } static int update_for_ref_mem(const struct tc_call_params *call_params, - struct tc_op_params *op_params, unsigned int index) + const struct tc_op_params *op_params, unsigned int index) { union tc_ns_client_param *client_param = NULL; uint32_t buffer_size; unsigned int orig_size = 0; struct tc_ns_operation *operation = &op_params->mb_pack->operation; + uint64_t size_addr; if (index >= TEE_PARAM_NUM) { tloge("index is invalid\n"); @@ -836,19 +850,21 @@ static int update_for_ref_mem(const struct tc_call_params *call_params, /* update size */ buffer_size = operation->params[index].memref.size; client_param = &(call_params->context->params[index]); + size_addr = client_param->memref.size_addr | + ((uint64_t)client_param->memref.size_h_addr << ADDR_TRANS_NUM); if (read_from_client(&orig_size, sizeof(orig_size), - (uint32_t __user *)(uintptr_t)client_param->memref.size_addr, - sizeof(orig_size), call_params->dev->kernel_api)) { + (uint32_t __user *)(uintptr_t)size_addr, + sizeof(orig_size), call_params->dev->kernel_api) != 0) { tloge("copy orig memref.size_addr failed\n"); return -EFAULT; } - if (write_to_client((void *)(uintptr_t)client_param->memref.size_addr, + if (write_to_client((void *)(uintptr_t)size_addr, sizeof(buffer_size), &buffer_size, sizeof(buffer_size), - call_params->dev->kernel_api)) { + call_params->dev->kernel_api) != 0) { tloge("copy buf size failed\n"); return -EFAULT; } @@ -856,7 +872,6 @@ static int update_for_ref_mem(const struct tc_call_params *call_params, /* reserved memory no need to copy */ if (operation->sharemem[index]->mem_type == RESERVED_TYPE) return 0; - /* copy from mb_buffer to sharemem */ if (operation->mb_buffer[index] && orig_size >= buffer_size) { void *buffer_addr = @@ -866,7 +881,7 @@ static int update_for_ref_mem(const struct tc_call_params *call_params, if (memcpy_s(buffer_addr, operation->sharemem[index]->len - client_param->memref.offset, - operation->mb_buffer[index], buffer_size)) { + operation->mb_buffer[index], buffer_size) != 0) { tloge("copy to sharemem failed\n"); return -EFAULT; } @@ -875,29 +890,35 @@ static int update_for_ref_mem(const struct tc_call_params *call_params, } static int update_for_value(const struct tc_call_params *call_params, - struct tc_op_params *op_params, unsigned int index) + const struct tc_op_params *op_params, unsigned int index) { union tc_ns_client_param *client_param = NULL; struct tc_ns_operation *operation = &op_params->mb_pack->operation; + uint64_t a_addr, b_addr; if (index >= TEE_PARAM_NUM) { tloge("index is invalid\n"); return -EFAULT; } client_param = &(call_params->context->params[index]); - if (write_to_client((void *)(uintptr_t)client_param->value.a_addr, + a_addr = client_param->value.a_addr | + ((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM); + b_addr = client_param->value.b_addr | + ((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM); + + if (write_to_client((void *)(uintptr_t)a_addr, sizeof(operation->params[index].value.a), &operation->params[index].value.a, sizeof(operation->params[index].value.a), - call_params->dev->kernel_api)) { + call_params->dev->kernel_api) != 0) { tloge("inc copy value.a_addr failed\n"); return -EFAULT; } - if (write_to_client((void *)(uintptr_t)client_param->value.b_addr, + if (write_to_client((void *)(uintptr_t)b_addr, sizeof(operation->params[index].value.b), &operation->params[index].value.b, sizeof(operation->params[index].value.b), - call_params->dev->kernel_api)) { + call_params->dev->kernel_api) != 0) { tloge("inc copy value.b_addr failed\n"); return -EFAULT; } @@ -905,7 +926,7 @@ static int update_for_value(const struct tc_call_params *call_params, } static int update_client_operation(const struct tc_call_params *call_params, - struct tc_op_params *op_params, bool is_complete) + const struct tc_op_params *op_params, bool is_complete) { int ret = 0; uint32_t param_type; @@ -915,7 +936,7 @@ static int update_client_operation(const struct tc_call_params *call_params, return 0; /* if paramTypes is NULL, no need to update */ - if (!call_params->context->param_types) + if (call_params->context->param_types == 0) return 0; for (index = 0; index < TEE_PARAM_NUM; index++) { @@ -931,7 +952,7 @@ static int update_client_operation(const struct tc_call_params *call_params, ret = update_for_value(call_params, op_params, index); else tlogd("param_type:%u don't need to update\n", param_type); - if (ret) + if (ret != 0) break; } return ret; @@ -951,14 +972,13 @@ static void release_page(void *buf) page = (struct page *)(uintptr_t)phys_to_page(phys_addr[i]); if (page == NULL) continue; - set_bit(PG_dirty, &page->flags); + set_bit(PG_dirty, &page->flags); put_page(page); } } #endif -static void free_operation(const struct tc_call_params *call_params, - struct tc_op_params *op_params) +static void free_operation(const struct tc_call_params *call_params, struct tc_op_params *op_params) { uint32_t param_type; uint32_t index; @@ -967,16 +987,17 @@ static void free_operation(const struct tc_call_params *call_params, struct tc_ns_operation *operation = &op_params->mb_pack->operation; for (index = 0; index < TEE_PARAM_NUM; index++) { - param_type = teec_param_type_get( - call_params->context->param_types, index); + param_type = teec_param_type_get(call_params->context->param_types, index); if (is_tmp_mem(param_type)) { /* free temp buffer */ temp_buf = local_tmpbuf[index].temp_buffer; tlogd("free temp buf, i = %u\n", index); - if (virt_addr_valid( - (unsigned long)(uintptr_t)temp_buf) && - !ZERO_OR_NULL_PTR( - (unsigned long)(uintptr_t)temp_buf)) { +#ifndef CONFIG_SHARED_MEM_RESERVED + /* if temp_buf from iomap instead of page_alloc, virt_addr_valid will return false */ + if (!virt_addr_valid((unsigned long)(uintptr_t)temp_buf)) + continue; +#endif + if (!ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)temp_buf)) { mailbox_free(temp_buf); temp_buf = NULL; } @@ -992,9 +1013,12 @@ static void free_operation(const struct tc_call_params *call_params, } else if (param_type == TEEC_ION_SGLIST_INPUT) { temp_buf = local_tmpbuf[index].temp_buffer; tlogd("free ion sglist buf, i = %u\n", index); - if (virt_addr_valid((uint64_t)(uintptr_t)temp_buf) && - !ZERO_OR_NULL_PTR( - (unsigned long)(uintptr_t)temp_buf)) { +#ifndef CONFIG_SHARED_MEM_RESERVED + /* if temp_buf from iomap instead of page_alloc, virt_addr_valid will return false */ + if (!virt_addr_valid((uint64_t)(uintptr_t)temp_buf)) + continue; +#endif + if (!ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)temp_buf)) { mailbox_free(temp_buf); temp_buf = NULL; } @@ -1010,7 +1034,7 @@ static void free_operation(const struct tc_call_params *call_params, } } -static int is_clicall_params_vaild(const struct tc_call_params *call_params) +static bool is_clicall_params_vaild(const struct tc_call_params *call_params) { if (!call_params) { tloge("call param is null"); @@ -1059,7 +1083,7 @@ static int init_smc_cmd(const struct tc_call_params *call_params, smc_cmd->cmd_type = global ? CMD_TYPE_GLOBAL : CMD_TYPE_TA; if (memcpy_s(smc_cmd->uuid, sizeof(smc_cmd->uuid), - context->uuid, UUID_LEN)) { + context->uuid, UUID_LEN) != 0) { tloge("memcpy uuid error\n"); return -EFAULT; } @@ -1072,18 +1096,18 @@ static int init_smc_cmd(const struct tc_call_params *call_params, smc_cmd->pid = current->tgid; tlogv("current uid is %u\n", smc_cmd->uid); - if (context->param_types) { + if (context->param_types != 0) { smc_cmd->operation_phys = - virt_to_phys(operation); + mailbox_virt_to_phys((uintptr_t)operation); smc_cmd->operation_h_phys = - (uint64_t)virt_to_phys(operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)operation) >> ADDR_TRANS_NUM; } else { smc_cmd->operation_phys = 0; smc_cmd->operation_h_phys = 0; } smc_cmd->login_method = context->login.method; - /* if smc from kernel CA, set login method to TEEK_LOGIN_IDENTIFY */ + /* if smc from kernel CA, set login_method to TEEK_LOGIN_IDENTIFY */ if (call_params->dev->kernel_api == TEE_REQ_FROM_KERNEL_MODE) smc_cmd->login_method = TEEK_LOGIN_IDENTIFY; @@ -1091,11 +1115,11 @@ static int init_smc_cmd(const struct tc_call_params *call_params, } static bool need_check_login(const struct tc_call_params *call_params, - struct tc_op_params *op_params) + const struct tc_op_params *op_params) { if (call_params->dev->pub_key_len == sizeof(uint32_t) && op_params->smc_cmd->cmd_id == GLOBAL_CMD_ID_OPEN_SESSION && - current->mm && (call_params->flags & TC_CALL_GLOBAL)) + current->mm && ((call_params->flags & TC_CALL_GLOBAL) != 0)) return true; return false; @@ -1111,13 +1135,13 @@ static int check_login_for_encrypt(const struct tc_call_params *call_params, if (need_check_login(call_params, op_params) && sess) { if (memcpy_s(mb_pack->login_data, sizeof(mb_pack->login_data), sess->auth_hash_buf, - sizeof(sess->auth_hash_buf))) { + sizeof(sess->auth_hash_buf)) != 0) { tloge("copy login data failed\n"); return -EFAULT; } - smc_cmd->login_data_phy = virt_to_phys(mb_pack->login_data); + smc_cmd->login_data_phy = mailbox_virt_to_phys((uintptr_t)mb_pack->login_data); smc_cmd->login_data_h_addr = - (uint64_t)virt_to_phys(mb_pack->login_data) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)mb_pack->login_data) >> ADDR_TRANS_NUM; smc_cmd->login_data_len = MAX_SHA_256_SZ * (NUM_OF_SO + 1); } else { smc_cmd->login_data_phy = 0; @@ -1136,7 +1160,7 @@ static uint32_t get_uid_for_cmd(void) } static void reset_session_id(const struct tc_call_params *call_params, - struct tc_op_params *op_params, int tee_ret) + const struct tc_op_params *op_params, int tee_ret) { bool need_reset = false; @@ -1147,7 +1171,7 @@ static void reset_session_id(const struct tc_call_params *call_params, */ need_reset = ((call_params->flags & TC_CALL_GLOBAL) && call_params->context->cmd_id == GLOBAL_CMD_ID_OPEN_SESSION && - tee_ret && tee_ret != TEEC_PENDING); + tee_ret && tee_ret != (int)TEEC_PENDING); if (need_reset) call_params->context->session_id = 0; return; @@ -1167,7 +1191,7 @@ static void pend_ca_thread(struct tc_ns_session *session, * use wait_event instead of wait_event_interruptible so * that ap suspend will not wake up the TEE wait call */ - wait_event(wq->send_cmd_wq, wq->send_wait_flag); + wait_event(wq->send_cmd_wq, wq->send_wait_flag != 0); wq->send_wait_flag = 0; } tlogv("operation start is :%d\n", smc_cmd->started); @@ -1183,10 +1207,12 @@ static void release_tc_call_resource(const struct tc_call_params *call_params, call_params->context->returns.origin = op_params->smc_cmd->err_origin; /* - * 1. when CA invoke command and crash, Gtask release service node - * then del ion won't be triggered, so here tzdriver need to kill ion; - *2. when ta crash, tzdriver also need to kill ion - */ + * 1. when CA invoke command and crash, Gtask release service node + * then del ion won't be triggered, so here tzdriver need to kill ion; + * 2. when ta crash, tzdriver also need to kill ion; + */ + if (tee_ret == (int)TEE_ERROR_TAGET_DEAD || tee_ret == (int)TEEC_ERROR_GENERIC) + kill_ion_by_uuid((struct tc_uuid *)op_params->smc_cmd->uuid); if (op_params->op_inited) free_operation(call_params, op_params); @@ -1201,12 +1227,10 @@ static int config_smc_cmd_context(const struct tc_call_params *call_params, int ret; ret = init_smc_cmd(call_params, op_params); - if (ret) + if (ret != 0) return ret; ret = check_login_for_encrypt(call_params, op_params); - if (ret) - return ret; return ret; } @@ -1214,10 +1238,10 @@ static int config_smc_cmd_context(const struct tc_call_params *call_params, static int handle_ta_pending(const struct tc_call_params *call_params, struct tc_op_params *op_params, int *tee_ret) { - if (*tee_ret != TEEC_PENDING) + if (*tee_ret != (int)TEEC_PENDING) return 0; - while (*tee_ret == TEEC_PENDING) { + while (*tee_ret == (int)TEEC_PENDING) { pend_ca_thread(call_params->sess, op_params->smc_cmd); *tee_ret = tc_ns_smc_with_no_nr(op_params->smc_cmd); } @@ -1230,15 +1254,15 @@ static int post_proc_smc_return(const struct tc_call_params *call_params, { int ret; - if (tee_ret) { + if (tee_ret != 0) { tloge("smc call ret 0x%x, cmd ret val 0x%x, origin %u\n", tee_ret, op_params->smc_cmd->ret_val, op_params->smc_cmd->err_origin); /* same as libteec_vendor, err from TEE, set ret positive */ ret = EFAULT; - if (tee_ret == TEEC_CLIENT_INTR) + if (tee_ret == (int)TEEC_CLIENT_INTR) ret = -ERESTARTSYS; - if (tee_ret == TEEC_ERROR_SHORT_BUFFER) + if (tee_ret == (int)TEEC_ERROR_SHORT_BUFFER) (void)update_client_operation(call_params, op_params, false); } else { tz_log_write(); @@ -1257,19 +1281,19 @@ int tc_client_call(const struct tc_call_params *call_params) if (!is_clicall_params_vaild(call_params)) return -EINVAL; - if (alloc_for_client_call(&op_params)) + if (alloc_for_client_call(&op_params) != 0) return -ENOMEM; op_params.smc_cmd->err_origin = TEEC_ORIGIN_COMMS; op_params.smc_cmd->uid = get_uid_for_cmd(); - if (call_params->context->param_types) { + if (call_params->context->param_types != 0) { ret = alloc_operation(call_params, &op_params); - if (ret) + if (ret != 0) goto free_src; } ret = config_smc_cmd_context(call_params, &op_params); - if (ret) + if (ret != 0) goto free_src; tee_ret = tc_ns_smc(op_params.smc_cmd); @@ -1277,7 +1301,7 @@ int tc_client_call(const struct tc_call_params *call_params) reset_session_id(call_params, &op_params, tee_ret); ret = handle_ta_pending(call_params, &op_params, &tee_ret); - if (ret) + if (ret != 0) goto free_src; ret = post_proc_smc_return(call_params, &op_params, tee_ret); diff --git a/core/gp_ops.h b/core/gp_ops.h index 4f00a8a80cc0d2c4ce3fccd1d0b07fb4ea15c21e..7144a0b0f95944f23390a3134accb526e4b8a128 100644 --- a/core/gp_ops.h +++ b/core/gp_ops.h @@ -20,21 +20,6 @@ #include "tc_ns_client.h" #include "teek_ns_client.h" -struct tc_call_params { - struct tc_ns_dev_file *dev; - struct tc_ns_client_context *context; - struct tc_ns_session *sess; - uint8_t flags; -}; - -struct tc_op_params { - struct mb_cmd_pack *mb_pack; - struct tc_ns_smc_cmd *smc_cmd; - struct tc_ns_temp_buf local_tmpbuf[TEE_PARAM_NUM]; - uint32_t trans_paramtype[TEE_PARAM_NUM]; - bool op_inited; -}; - struct pagelist_info { uint64_t page_num; uint64_t page_size; @@ -52,6 +37,5 @@ int tc_client_call(const struct tc_call_params *call_params); bool is_tmp_mem(uint32_t param_type); bool is_ref_mem(uint32_t param_type); bool is_val_param(uint32_t param_type); -bool is_ion_param(uint32_t param_type); #endif diff --git a/core/mailbox_mempool.c b/core/mailbox_mempool.c index afe81177e6e638a4096a40d8b9319312dc98bd58..e088e59149cd9c9907c44b491e1a668af54ba5de 100644 --- a/core/mailbox_mempool.c +++ b/core/mailbox_mempool.c @@ -16,6 +16,7 @@ * GNU General Public License for more details. */ #include "mailbox_mempool.h" +#include "shared_mem.h" #include #include #include @@ -34,6 +35,7 @@ #include "tc_ns_log.h" #include "smc_smp.h" #include "ko_adapt.h" +#include "internal_functions.h" #define MAILBOX_PAGE_MAX (MAILBOX_POOL_SIZE >> PAGE_SHIFT) static int g_max_oder; @@ -43,7 +45,7 @@ static int g_max_oder; struct mb_page_t { struct list_head node; - struct page *page; + mailbox_page_t *page; int order; unsigned int count; /* whether be used */ }; @@ -54,7 +56,7 @@ struct mb_free_area_t { }; struct mb_zone_t { - struct page *all_pages; + mailbox_page_t *all_pages; struct mb_page_t pages[MAILBOX_PAGE_MAX]; struct mb_free_area_t free_areas[0]; }; @@ -77,7 +79,7 @@ static void mailbox_show_status(void) tloge("########################################\n"); mutex_lock(&g_mb_lock); for (i = 0; i < MAILBOX_PAGE_MAX; i++) { - if (g_m_zone->pages[i].count) { + if (g_m_zone->pages[i].count != 0) { tloge("page[%02d], order=%02d, count=%d\n", i, g_m_zone->pages[i].order, g_m_zone->pages[i].count); @@ -89,7 +91,7 @@ static void mailbox_show_status(void) for (i = 0; i < (unsigned int)g_max_oder; i++) { head = &g_m_zone->free_areas[i].page_list; - if (list_empty(head)) { + if (list_empty(head) != 0) { tloge("order[%02d] is empty\n", i); } else { list_for_each_entry(pos, head, node) @@ -123,13 +125,13 @@ static void mailbox_show_details(void) tloge("%04d-%04d:", i, i + MB_SHOW_LINE); } - if (g_m_zone->pages[i].count) { + if (g_m_zone->pages[i].count != 0) { left = 1 << (uint32_t)g_m_zone->pages[i].order; - order = g_m_zone->pages[i].order; + order = (uint32_t)g_m_zone->pages[i].order; used += (1 << (uint32_t)g_m_zone->pages[i].order); } - if (left) { + if (left != 0) { left--; tloge("%01d", order); } else { @@ -151,7 +153,7 @@ void *mailbox_alloc(size_t size, unsigned int flag) int order = get_order(ALIGN(size, SZ_4K)); void *addr = NULL; - if (!size || !g_m_zone) { + if ((size == 0) || !g_m_zone) { tlogw("alloc 0 size mailbox or zone struct is NULL\n"); return NULL; } @@ -166,7 +168,7 @@ void *mailbox_alloc(size_t size, unsigned int flag) unsigned int j; head = &g_m_zone->free_areas[i].page_list; - if (list_empty(head)) + if (list_empty(head) != 0) continue; pos = list_first_entry(head, struct mb_page_t, node); @@ -175,24 +177,24 @@ void *mailbox_alloc(size_t size, unsigned int flag) pos->order = order; /* split and add free list */ - for (j = order; j < i; j++) { + for (j = (unsigned int)order; j < i; j++) { struct mb_page_t *new_page = NULL; new_page = pos + (1 << j); new_page->count = 0; - new_page->order = j; + new_page->order = (int)j; list_add_tail(&new_page->node, &g_m_zone->free_areas[j].page_list); } list_del(&pos->node); - addr = page_address(pos->page); + addr = (void *)mailbox_page_address(pos->page); break; } mutex_unlock(&g_mb_lock); - if (addr && (flag & MB_FLAG_ZERO)) { + if (addr && ((flag & MB_FLAG_ZERO) != 0)) { if (memset_s(addr, ALIGN(size, SZ_4K), - 0, ALIGN(size, SZ_4K))) { + 0, ALIGN(size, SZ_4K)) != 0) { tloge("clean mailbox failed\n"); mailbox_free(addr); return NULL; @@ -205,7 +207,7 @@ static void add_max_order_block(unsigned int idex) { struct mb_page_t *self = NULL; - if (idex != g_max_oder || !g_m_zone) + if (idex != (unsigned int)g_max_oder || !g_m_zone) return; /* @@ -217,7 +219,7 @@ static void add_max_order_block(unsigned int idex) &g_m_zone->free_areas[g_max_oder].page_list); } -static bool is_ptr_valid(struct page *page) +static bool is_ptr_valid(const mailbox_page_t *page) { if (!g_m_zone) return false; @@ -234,7 +236,7 @@ static bool is_ptr_valid(struct page *page) void mailbox_free(const void *ptr) { unsigned int i; - struct page *page = NULL; + mailbox_page_t *page = NULL; struct mb_page_t *self = NULL; struct mb_page_t *buddy = NULL; unsigned int self_idx; @@ -245,14 +247,14 @@ void mailbox_free(const void *ptr) return; } - page = virt_to_page((uint64_t)(uintptr_t)ptr); + page = mailbox_virt_to_page((uint64_t)(uintptr_t)ptr); if (!is_ptr_valid(page)) return; mutex_lock(&g_mb_lock); self_idx = page - g_m_zone->all_pages; self = &g_m_zone->pages[self_idx]; - if (!self->count) { + if (self->count == 0) { tloge("already freed in mailbox\n"); mutex_unlock(&g_mb_lock); return; @@ -316,7 +318,7 @@ void *mailbox_copy_alloc(const void *src, size_t size) return NULL; } - if (memcpy_s(mb_ptr, size, src, size)) { + if (memcpy_s(mb_ptr, size, src, size) != 0) { tloge("memcpy to mailbox failed\n"); mailbox_free(mb_ptr); return NULL; @@ -399,13 +401,13 @@ static void mb_dbg_reset(void) #define MB_WRITE_SIZE 64 -static bool is_opt_write_param_valid(struct file *filp, - const char __user *ubuf, size_t cnt, loff_t *ppos) +static bool is_opt_write_param_valid(const struct file *filp, + const char __user *ubuf, size_t cnt, const loff_t *ppos) { if (!filp || !ppos || !ubuf) return false; - if (cnt >= MB_WRITE_SIZE || !cnt) + if (cnt >= MB_WRITE_SIZE || cnt == 0) return false; return true; @@ -423,7 +425,7 @@ static void alloc_dbg_entry(unsigned int alloc_size) } idx = mb_dbg_add_entry(ptr); - if (!idx) + if (idx == 0) mailbox_free(ptr); g_mb_dbg_last_res = idx; } @@ -440,15 +442,15 @@ static ssize_t mb_dbg_opt_write(struct file *filp, if (!is_opt_write_param_valid(filp, ubuf, cnt, ppos)) return -EINVAL; - if (copy_from_user(buf, ubuf, cnt)) + if (copy_from_user(buf, ubuf, cnt) != 0) return -EFAULT; buf[cnt] = 0; value = buf; - if (!strncmp(value, "reset", strlen("reset"))) { + if (strncmp(value, "reset", strlen("reset")) == 0) { tlogi("mb dbg reset\n"); mb_dbg_reset(); - return cnt; + return (ssize_t)cnt; } cmd = strsep(&value, ":"); @@ -457,12 +459,12 @@ static ssize_t mb_dbg_opt_write(struct file *filp, return -EFAULT; } - if (!strncmp(cmd, "alloc", strlen("alloc"))) { + if (strncmp(cmd, "alloc", strlen("alloc")) == 0) { if (kstrtou32(value, 10, &alloc_size) == 0) alloc_dbg_entry(alloc_size); else tloge("invalid value format for mb dbg\n"); - } else if (!strncmp(cmd, "free", strlen("free"))) { + } else if (strncmp(cmd, "free", strlen("free")) == 0) { if (kstrtou32(value, 10, &free_idx) == 0) mb_dbg_remove_entry(free_idx); else @@ -471,7 +473,7 @@ static ssize_t mb_dbg_opt_write(struct file *filp, tloge("invalid format for mb dbg\n"); } - return cnt; + return (ssize_t)cnt; } static ssize_t mb_dbg_opt_read(struct file *filp, char __user *ubuf, @@ -500,6 +502,7 @@ static const struct file_operations g_mb_dbg_opt_fops = { static ssize_t mb_dbg_state_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { + (void)cnt; (void)(filp); (void)(ubuf); (void)(ppos); @@ -524,8 +527,7 @@ static int mailbox_register(const void *mb_pool, unsigned int size) tloge("alloc smc_cmd failed\n"); return -EIO; } - - operation = kzalloc(sizeof(*operation), GFP_KERNEL); + operation = (struct tc_ns_operation *)(uintptr_t)get_operation_vaddr(); if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)operation)) { tloge("alloc operation failed\n"); ret = -EIO; @@ -534,23 +536,28 @@ static int mailbox_register(const void *mb_pool, unsigned int size) operation->paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); - operation->params[0].value.a = virt_to_phys(mb_pool); + operation->params[0].value.a = mailbox_virt_to_phys((uintptr_t)mb_pool); operation->params[0].value.b = - (uint64_t)virt_to_phys(mb_pool) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)mb_pool) >> ADDR_TRANS_NUM; operation->params[1].value.a = size; smc_cmd->cmd_type = CMD_TYPE_GLOBAL; smc_cmd->cmd_id = GLOBAL_CMD_ID_REGISTER_MAILBOX; - smc_cmd->operation_phys = virt_to_phys(operation); + smc_cmd->operation_phys = mailbox_virt_to_phys((uintptr_t)operation); smc_cmd->operation_h_phys = - (uint64_t)virt_to_phys(operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)operation) >> ADDR_TRANS_NUM; - if (tc_ns_smc(smc_cmd)) { + if (is_tee_rebooting()) + ret = send_smc_cmd_rebooting(TSP_REQUEST, 0, 0, smc_cmd); + else + ret= tc_ns_smc(smc_cmd); + + if (ret != 0) { tloge("resigter mailbox failed\n"); ret = -EIO; } - kfree(operation); + free_operation((uint64_t)(uintptr_t)operation); operation = NULL; free_smc_cmd: kfree(smc_cmd); @@ -560,8 +567,25 @@ free_smc_cmd: static void mailbox_debug_init(void) { - g_mb_dbg_dentry = debugfs_create_dir("tz_mailbox", NULL); - debugfs_create_file("state", STATE_MODE, g_mb_dbg_dentry, NULL, &g_mb_dbg_state_fops); +} + +int re_register_mailbox(void) +{ + if (!g_m_zone) + return -EFAULT; + if (g_m_zone->all_pages != NULL) { + if (memset_s((void *)mailbox_page_address(g_m_zone->all_pages), + MAILBOX_POOL_SIZE, 0, MAILBOX_POOL_SIZE) != EOK) { + tloge("memset mailbox failed\n"); + return -EFAULT; + } + + if (mailbox_register((const void *)mailbox_page_address(g_m_zone->all_pages), MAILBOX_POOL_SIZE) != 0) { + tloge("register mailbox failed\n"); + return -EIO; + } + } + return 0; } int mailbox_mempool_init(void) @@ -569,11 +593,11 @@ int mailbox_mempool_init(void) int i; struct mb_page_t *mb_page = NULL; struct mb_free_area_t *area = NULL; - struct page *all_pages = NULL; + mailbox_page_t *all_pages = NULL; size_t zone_len; g_max_oder = get_order(MAILBOX_POOL_SIZE); - tloge("in this RE, mailbox max order is: %d\n", g_max_oder); + tlogi("in this RE, mailbox max order is: %d\n", g_max_oder); /* zone len is fixed, will not overflow */ zone_len = sizeof(*area) * (g_max_oder + 1) + sizeof(*g_m_zone); @@ -583,7 +607,7 @@ int mailbox_mempool_init(void) return -ENOMEM; } - all_pages = koadpt_alloc_pages(GFP_KERNEL, g_max_oder); + all_pages = mailbox_alloc_pages(g_max_oder); if (!all_pages) { tloge("fail to alloc mailbox mempool\n"); kfree(g_m_zone); @@ -591,9 +615,9 @@ int mailbox_mempool_init(void) return -ENOMEM; } - if (mailbox_register(page_address(all_pages), MAILBOX_POOL_SIZE)) { + if (mailbox_register((const void *)mailbox_page_address(all_pages), MAILBOX_POOL_SIZE) != 0) { tloge("register mailbox failed\n"); - __free_pages(all_pages, g_max_oder); + mailbox_free_pages(all_pages, g_max_oder); kfree(g_m_zone); g_m_zone = NULL; return -EIO; @@ -621,10 +645,15 @@ int mailbox_mempool_init(void) return 0; } -void mailbox_mempool_destroy(void) +void free_mailbox_mempool(void) { - __free_pages(g_m_zone->all_pages, g_max_oder); + mailbox_free_pages(g_m_zone->all_pages, g_max_oder); g_m_zone->all_pages = NULL; kfree(g_m_zone); g_m_zone = NULL; + + if (!g_mb_dbg_dentry) + return; + debugfs_remove_recursive(g_mb_dbg_dentry); + g_mb_dbg_dentry = NULL; } diff --git a/core/mailbox_mempool.h b/core/mailbox_mempool.h index 8025fae15abf478711d613ac7e379a259d66f334..b27ad420af99fe8e698256b430d535acef5b57c9 100644 --- a/core/mailbox_mempool.h +++ b/core/mailbox_mempool.h @@ -20,8 +20,11 @@ #include #include +#include "teek_ns_client.h" +#ifndef MAILBOX_POOL_SIZE #define MAILBOX_POOL_SIZE SZ_4M +#endif /* alloc options */ #define MB_FLAG_ZERO 0x1 /* set 0 after alloc page */ @@ -30,8 +33,10 @@ void *mailbox_alloc(size_t size, unsigned int flag); void mailbox_free(const void *ptr); int mailbox_mempool_init(void); -void mailbox_mempool_destroy(void); +void free_mailbox_mempool(void); struct mb_cmd_pack *mailbox_alloc_cmd_pack(void); void *mailbox_copy_alloc(const void *src, size_t size); +int re_register_mailbox(void); +uintptr_t mailbox_virt_to_phys(uintptr_t addr); #endif diff --git a/core/mem.c b/core/mem.c index 72d68e279a1a51e2214502be1ce758024589b04d..117874b1482237a31c50238cb8ae5350430993ca 100644 --- a/core/mem.c +++ b/core/mem.c @@ -33,13 +33,13 @@ #include "agent.h" #include "tc_ns_log.h" #include "mailbox_mempool.h" +#include "internal_functions.h" #include "reserved_mempool.h" void tc_mem_free(struct tc_ns_shared_mem *shared_mem) { if (!shared_mem) return; - if (shared_mem->mem_type == RESERVED_TYPE) { reserved_mem_free(shared_mem->kernel_addr); kfree(shared_mem); @@ -56,12 +56,11 @@ void tc_mem_free(struct tc_ns_shared_mem *shared_mem) static void init_shared_mem(struct tc_ns_shared_mem *sh, void *addr, size_t len) { sh->kernel_addr = addr; - sh->len = len; + sh->len = (uint32_t)len; sh->user_addr = INVALID_MAP_ADDR; sh->user_addr_ca = INVALID_MAP_ADDR; atomic_set(&sh->usage, 0); } - struct tc_ns_shared_mem *tc_mem_allocate(size_t len) { struct tc_ns_shared_mem *shared_mem = NULL; @@ -75,8 +74,9 @@ struct tc_ns_shared_mem *tc_mem_allocate(size_t len) shared_mem->mem_type = VMALLOC_TYPE; len = ALIGN(len, SZ_4K); if (exist_res_mem()) { - if (len > RESEVED_MAX_ALLOC_SIZE || len > RESERVED_MEM_POOL_SIZE) { + if (len > get_res_mem_slice_size()) { tloge("allocate reserved mem size too large\n"); + kfree(shared_mem); return ERR_PTR(-EINVAL); } addr = reserved_mem_alloc(len); @@ -88,8 +88,6 @@ struct tc_ns_shared_mem *tc_mem_allocate(size_t len) tlogw("no more reserved memory to alloc so we use system vmalloc.\n"); } } - - if (len > MAILBOX_POOL_SIZE) { tloge("alloc sharemem size %zu is too large\n", len); kfree(shared_mem); @@ -97,10 +95,11 @@ struct tc_ns_shared_mem *tc_mem_allocate(size_t len) } addr = vmalloc_user(len); if (!addr) { - tloge("alloc maibox failed\n"); + tloge("alloc mailbox failed\n"); kfree(shared_mem); return ERR_PTR(-ENOMEM); } + init_shared_mem(shared_mem, addr, len); return shared_mem; -} \ No newline at end of file +} diff --git a/core/reserved_mempool.c b/core/reserved_mempool.c index b132d58983d42533c19ea5686700dfca662c0e19..43d77317ed4b98ea213e5ecb4064635fbd810fa0 100644 --- a/core/reserved_mempool.c +++ b/core/reserved_mempool.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -40,403 +39,486 @@ #include "tc_ns_log.h" #include "smc_smp.h" -#define RESMEM_PAGE_MAX (RESERVED_MEM_POOL_SIZE >> PAGE_SHIFT) #define STATE_MODE 0440U +#define SLICE_RATE 4 +#define MAX_SLICE 0x400000 +#define MIN_RES_MEM_SIZE 0x400000 struct virt_page { - unsigned long start; + unsigned long start; }; struct reserved_page_t { - struct list_head node; - struct virt_page *page; - int order; - unsigned int count; + struct list_head node; + struct virt_page *page; + int order; + unsigned int count; /* whether be used */ }; struct reserved_free_area_t { - struct list_head page_list; - int order; + struct list_head page_list; + int order; }; struct reserved_zone_t { - struct virt_page *all_pages; - struct reserved_page_t pages[RESMEM_PAGE_MAX]; - struct reserved_free_area_t free_areas[0]; + struct virt_page *all_pages; + struct reserved_page_t *pages; + struct reserved_free_area_t free_areas[0]; }; static struct reserved_zone_t *g_res_zone; static struct mutex g_res_lock; static int g_res_max_order; static unsigned long g_start_vaddr = 0; -static unsigned long g_virt_phy_offset; +static unsigned long g_start_paddr; static struct dentry *g_res_mem_dbg_dentry; +static unsigned int g_res_mem_size = 0; + +static unsigned int get_res_page_size(void) +{ + return g_res_mem_size >> PAGE_SHIFT; +} + +static unsigned int calc_res_mem_size(unsigned int rsize) +{ + unsigned int size = rsize; + unsigned int idx = 0; + + if (size == 0 || (size & (size - 1)) == 0) + return size; + + while (size != 0) { + size = size >> 1; + idx++; + } + return (1 << (idx - 1)); +} + +unsigned int get_res_mem_slice_size(void) +{ + unsigned int size = (g_res_mem_size >> SLICE_RATE); + return (size > MAX_SLICE) ? MAX_SLICE : size; +} bool exist_res_mem(void) { - return g_start_vaddr != 0; + return (g_start_vaddr != 0) && (g_res_mem_size != 0); } unsigned long res_mem_virt_to_phys(unsigned long vaddr) { - return vaddr - g_virt_phy_offset; + return vaddr - g_start_vaddr + g_start_paddr; } int load_reserved_mem(void) { - struct device_node *np = NULL; - struct resource r; - int rc; - void *p = NULL; - - np = of_find_compatible_node(NULL, NULL, "tz_reserved"); - if (np == NULL) { - tlogd("can not find reserved memory.\n"); - return 0; - } - - rc = of_address_to_resource(np, 0, &r); - if (rc) { - tloge("of_address_to_resource error\n"); - return -ENODEV; - } - - p = ioremap(r.start, resource_size(&r)); - if (p == NULL) { - tloge("io remap for reserved memory failed\n"); - return -ENOMEM; - } - - g_start_vaddr = (unsigned long)(uintptr_t)p; - g_virt_phy_offset = g_start_vaddr - (unsigned long)r.start; - return 0; + struct device_node *np = NULL; + struct resource r; + unsigned int res_size; + int rc; + void *p = NULL; + + np = of_find_compatible_node(NULL, NULL, "tz_reserved"); + if (np == NULL) { + tlogd("can not find reserved memory.\n"); + return 0; + } + + rc = of_address_to_resource(np, 0, &r); + if (rc != 0) { + tloge("of_address_to_resource error\n"); + return -ENODEV; + } + + res_size = (unsigned int)resource_size(&r); + if (res_size < MIN_RES_MEM_SIZE) { + tloge("reserved memory size is too small\n"); + return -EINVAL; + } + + p = ioremap(r.start, res_size); + if (p == NULL) { + tloge("io remap for reserved memory failed\n"); + return -ENOMEM; + } + g_start_vaddr = (unsigned long)(uintptr_t)p; + g_start_paddr = (unsigned long)r.start; + g_res_mem_size = calc_res_mem_size(res_size); + + return 0; +} + +void unmap_res_mem(void) +{ + if (exist_res_mem()) { + iounmap((void __iomem *)g_start_vaddr); + g_start_vaddr = 0; + g_res_mem_size = 0; + } } static int create_zone(void) { - size_t zone_len; - int order = get_order(RESERVED_MEM_POOL_SIZE); - g_res_max_order = (order > CONFIG_MAX_RES_MEM_ORDER) ? CONFIG_MAX_RES_MEM_ORDER : order; - zone_len = sizeof(struct reserved_free_area_t) * (g_res_max_order + 1) + sizeof(*g_res_zone); - - g_res_zone = kzalloc(zone_len, GFP_KERNEL); - if (g_res_zone == NULL) { - tloge("fail to create zone\n"); - return -ENOMEM; - } - return 0; + size_t zone_len; + g_res_max_order = get_order(g_res_mem_size); + zone_len = sizeof(struct reserved_free_area_t) * (g_res_max_order + 1) + sizeof(*g_res_zone); + + g_res_zone = kzalloc(zone_len, GFP_KERNEL); + if (g_res_zone == NULL) { + tloge("fail to create zone\n"); + return -ENOMEM; + } + + g_res_zone->pages = kzalloc(sizeof(struct reserved_page_t) * get_res_page_size(), GFP_KERNEL); + if (g_res_zone->pages == NULL) { + tloge("failed to alloc zone pages\n"); + kfree(g_res_zone); + g_res_zone = NULL; + return -ENOMEM; + } + return 0; } static struct virt_page *create_virt_pages(void) { - int i = 0; - struct virt_page *pages = NULL; - - pages = kzalloc(RESMEM_PAGE_MAX * sizeof(struct virt_page), GFP_KERNEL); - if (pages == NULL) { - tloge("alloc pages failed\n"); - return NULL; - } - for(i = 0; i < RESMEM_PAGE_MAX; i++) - pages[i].start = g_start_vaddr + i * PAGE_SIZE; - return pages; + unsigned int i = 0; + struct virt_page *pages = NULL; + + pages = kzalloc(get_res_page_size() * sizeof(struct virt_page), GFP_KERNEL); + if (pages == NULL) { + tloge("alloc pages failed\n"); + return NULL; + } + + for (i = 0; i < get_res_page_size(); i++) + pages[i].start = g_start_vaddr + i * PAGE_SIZE; + return pages; } void free_reserved_mempool(void) { - if (!exist_res_mem()) - return; - kfree(g_res_zone->all_pages); - g_res_zone->all_pages = NULL; - kfree(g_res_zone); - g_res_zone = NULL; + if (!exist_res_mem()) + return; + + if (g_res_zone->all_pages != NULL) { + kfree(g_res_zone->all_pages); + g_res_zone->all_pages = NULL; + } + + if (g_res_zone->pages != NULL) { + kfree(g_res_zone->pages); + g_res_zone->pages = NULL; + } + + if (g_res_zone != NULL) { + kfree(g_res_zone); + g_res_zone = NULL; + } + + if (!g_res_mem_dbg_dentry) + return; + debugfs_remove_recursive(g_res_mem_dbg_dentry); + g_res_mem_dbg_dentry = NULL; } static void show_res_mem_info(void) { - unsigned int i; - struct reserved_page_t *pos = NULL; - struct list_head *head = NULL; - unsigned int used = 0; - - if (g_res_zone == NULL) { - tloge("res zone is NULL\n"); - return; - } - - tloge("############################# reserved memory info #############################\n"); - mutex_lock(&g_res_lock); - for (i = 0; i < RESMEM_PAGE_MAX; i++) { - if (g_res_zone->pages[i].count) { - tloge("page[%02d], order=%02d, count=%d\n", - i, g_res_zone->pages[i].order, - g_res_zone->pages[i].count); - used += (1 << (uint32_t)g_res_zone->pages[i].order); - } - } - tloge("reserved memory total usage:%u%u\n", used, RESMEM_PAGE_MAX); - tloge("------------------------------------------------------------\n"); - - for (i = 0; i < (unsigned int)g_res_max_order; i++) { - head = &g_res_zone->free_areas[i].page_list; - if (list_empty(head)) - tloge("order[%02d] is empty\n", i); - else { - list_for_each_entry(pos, head, node); - tloge("order[%02d]\n", i); - } - } - mutex_unlock(&g_res_lock); - tloge("############################################################################\n"); + unsigned int i; + struct reserved_page_t *pos = NULL; + struct list_head *head = NULL; + unsigned int used = 0; + + if (g_res_zone == NULL) { + tloge("res zone is NULL\n"); + return; + } + + tloge("################## reserved memory info ######################\n"); + mutex_lock(&g_res_lock); + for (i = 0; i < get_res_page_size(); i++) { + if (g_res_zone->pages[i].count != 0) { + tloge("page[%02d], order=%02d, count=%d\n", + i, g_res_zone->pages[i].order, + g_res_zone->pages[i].count); + used += (1 << (uint32_t)g_res_zone->pages[i].order); + } + } + tloge("reserved memory total usage:%u/%u\n", used, get_res_page_size()); + tloge("--------------------------------------------------------------\n"); + + for (i = 0; i < (unsigned int)g_res_max_order; i++) { + head = &g_res_zone->free_areas[i].page_list; + if (list_empty(head) != 0) { + tloge("order[%02d] is empty\n", i); + } else { + list_for_each_entry(pos, head, node) + tloge("order[%02d]\n", i); + } + } + mutex_unlock(&g_res_lock); + + tloge("#############################################################\n"); } static ssize_t mb_res_mem_state_read(struct file *filp, char __user *ubuf, - size_t cnt, loff_t *ppos) + size_t cnt, loff_t *ppos) { - (void)(filp); - (void)(ubuf); - (void)(ppos); - show_res_mem_info(); - return 0; + (void)(filp); + (void)(ubuf); + (void)cnt; + (void)(ppos); + show_res_mem_info(); + return 0; } static const struct file_operations g_res_mem_dbg_state_fops = { - .owner = THIS_MODULE, - .read = mb_res_mem_state_read, + .owner = THIS_MODULE, + .read = mb_res_mem_state_read, }; static void init_res_mem_dentry(void) { - g_res_mem_dbg_dentry = debugfs_create_dir("tz_res_mem", NULL); - debugfs_create_file("state", STATE_MODE, g_res_mem_dbg_dentry, NULL, - &g_res_mem_dbg_state_fops); } static int res_mem_register(unsigned long paddr, unsigned int size) { - struct tc_ns_operation *operation = NULL; - struct tc_ns_smc_cmd *smc_cmd = NULL; - int ret = 0; - - smc_cmd = kzalloc(sizeof(*smc_cmd), GFP_KERNEL); - if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)smc_cmd)) { - tloge("alloc smc_cmd failed\n"); - return -ENOMEM; - } - - operation = kzalloc(sizeof(*operation), GFP_KERNEL); - if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)operation)) { - tloge("alloc operation failed\n"); - ret = -ENOMEM; - goto free_smc_cmd; - } - - operation->paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | - (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); - operation->params[0].value.a = paddr; - operation->params[0].value.b = paddr >> ADDR_TRANS_NUM; - operation->params[1].value.a = size; - - smc_cmd->cmd_type = CMD_TYPE_GLOBAL; - smc_cmd->cmd_id = GLOBAL_CMD_ID_REGISTER_RESMEM; - smc_cmd->operation_phys = virt_to_phys(operation); - smc_cmd->operation_h_phys = virt_to_phys(operation) >> ADDR_TRANS_NUM; - - if (tc_ns_smc(smc_cmd)) { - tloge("register res mem failed\n"); - ret = -EIO; - } - - kfree(operation); - operation = NULL; + struct tc_ns_operation *operation = NULL; + struct tc_ns_smc_cmd *smc_cmd = NULL; + int ret = 0; + + smc_cmd = kzalloc(sizeof(*smc_cmd), GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)smc_cmd)) { + tloge("alloc smc_cmd failed\n"); + return -ENOMEM; + } + + operation = kzalloc(sizeof(*operation), GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)operation)) { + tloge("alloc operation failed\n"); + ret = -ENOMEM; + goto free_smc_cmd; + } + + operation->paramtypes = TEE_PARAM_TYPE_VALUE_INPUT | + (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM); + operation->params[0].value.a = paddr; + operation->params[0].value.b = paddr >> ADDR_TRANS_NUM; + operation->params[1].value.a = size; + + smc_cmd->cmd_type = CMD_TYPE_GLOBAL; + smc_cmd->cmd_id = GLOBAL_CMD_ID_REGISTER_RESMEM; + smc_cmd->operation_phys = virt_to_phys(operation); + smc_cmd->operation_h_phys = virt_to_phys(operation) >> ADDR_TRANS_NUM; + + if (tc_ns_smc(smc_cmd) != 0) { + tloge("resigter res mem failed\n"); + ret = -EIO; + } + + kfree(operation); + operation = NULL; free_smc_cmd: - kfree(smc_cmd); - smc_cmd = NULL; - return ret; + kfree(smc_cmd); + smc_cmd = NULL; + return ret; } -int reserved_mempool_init() +static void zone_init(struct virt_page *all_pages) { - struct virt_page *all_pages = NULL; - struct reserved_free_area_t *area = NULL; - struct reserved_page_t *res_page = NULL; - int ret = 0; - int i; - int max_order_cnt; - unsigned long paddr; - - if (!exist_res_mem()) - return 0; - - ret = create_zone(); - if (ret) - return ret; - - all_pages = create_virt_pages(); - if (all_pages == NULL) { - kfree(g_res_zone); - g_res_zone = NULL; - return -ENOMEM; - } - - paddr = res_mem_virt_to_phys(g_start_vaddr); - ret = res_mem_register(paddr, RESERVED_MEM_POOL_SIZE); - if (ret) { - kfree(all_pages); - kfree(g_res_zone); - g_res_zone = NULL; - return -EIO; - } - - for (i = 0; i < RESMEM_PAGE_MAX; i++) { - g_res_zone->pages[i].order = -1; - g_res_zone->pages[i].count = 0; - g_res_zone->pages[i].page = &all_pages[i]; - } - - for (i = 0; i <= g_res_max_order; i++) { - area = &g_res_zone->free_areas[i]; - INIT_LIST_HEAD(&area->page_list); - area->order = i; - } - - max_order_cnt = RESMEM_PAGE_MAX / (1 << (unsigned int)g_res_max_order); - g_res_zone->all_pages = all_pages; - for (i = 0; i < max_order_cnt; i++) { - int idx = i * (1 << (unsigned int)g_res_max_order); - g_res_zone->pages[idx].order = g_res_max_order; - res_page = &g_res_zone->pages[idx]; - list_add_tail(&res_page->node, &area->page_list); - } - - mutex_init(&g_res_lock); - init_res_mem_dentry(); - return 0; + int i; + struct reserved_free_area_t *area = NULL; + int max_order_cnt; + struct reserved_page_t *res_page = NULL; + + for (i = 0; i < (int)get_res_page_size(); i++) { + g_res_zone->pages[i].order = -1; + g_res_zone->pages[i].count = 0; + g_res_zone->pages[i].page = &all_pages[i]; + } + + for (i = 0; i <= g_res_max_order; i++) { + area = &g_res_zone->free_areas[i]; + INIT_LIST_HEAD(&area->page_list); + area->order = i; + } + + max_order_cnt = (int)(get_res_page_size() / (1 << (unsigned int)g_res_max_order)); + g_res_zone->all_pages = all_pages; + for (i = 0; i < max_order_cnt; i++) { + int idx = i * (1 << (unsigned int)g_res_max_order); + g_res_zone->pages[idx].order = g_res_max_order; + res_page = &g_res_zone->pages[idx]; + list_add_tail(&res_page->node, &area->page_list); + } +} + +int reserved_mempool_init(void) +{ + struct virt_page *all_pages = NULL; + int ret = 0; + unsigned long paddr; + + if (!exist_res_mem()) + return 0; + + ret = create_zone(); + if (ret != 0) + return ret; + + all_pages = create_virt_pages(); + if (all_pages == NULL) { + kfree(g_res_zone->pages); + g_res_zone->pages = NULL; + kfree(g_res_zone); + g_res_zone = NULL; + return -ENOMEM; + } + + paddr = g_start_paddr; + ret = res_mem_register(paddr, g_res_mem_size); + if (ret != 0) { + kfree(all_pages); + all_pages = NULL; + kfree(g_res_zone->pages); + g_res_zone->pages = NULL; + kfree(g_res_zone); + g_res_zone = NULL; + return -EIO; + } + + zone_init(all_pages); + + mutex_init(&g_res_lock); + init_res_mem_dentry(); + return 0; } void *reserved_mem_alloc(size_t size) { - int i, j; - struct reserved_page_t *pos = NULL; - struct list_head *head = NULL; - int order = get_order(ALIGN(size, SZ_4K)); - unsigned long addr = 0; - - bool valid_param = (size > 0 && order <= g_res_max_order && order >= 0); - if (!valid_param) { - tloge("invalid alloc param, size %d, order %d, max %d\n", (int)size, order, g_res_max_order); - return NULL; - } - mutex_lock(&g_res_lock); - for (i = order; i <= g_res_max_order; i++) { - head = &g_res_zone->free_areas[i].page_list; - if (list_empty(head)) - continue; - - pos = list_first_entry(head, struct reserved_page_t, node); - pos->count = 1; - pos->order = order; - - for (j = order; j < i; j++) { - struct reserved_page_t *new_page = NULL; - new_page = pos + (1 << (unsigned int)j); - new_page->count = 0; - new_page->order = j; - list_add_tail(&new_page->node, &g_res_zone->free_areas[j].page_list); - } - list_del(&pos->node); - addr = pos->page->start; - break; - } - mutex_unlock(&g_res_lock); - return (void *)(uintptr_t)addr; + int i, j; + struct reserved_page_t *pos = NULL; + struct list_head *head = NULL; + int order = get_order(ALIGN(size, SZ_4K)); + unsigned long addr = 0; + + bool valid_param = (size > 0 && order <= g_res_max_order && order >= 0); + if (!valid_param) { + tloge("invalid alloc param, size %d, order %d, max %d\n",(int)size, order, g_res_max_order); + return NULL; + } + mutex_lock(&g_res_lock); + for (i = order; i <= g_res_max_order; i++) { + head = &g_res_zone->free_areas[i].page_list; + if (list_empty(head) != 0) + continue; + + pos = list_first_entry(head, struct reserved_page_t, node); + pos->count = 1; + pos->order = order; + + for (j = order; j < i; j++) { + struct reserved_page_t *new_page = NULL; + new_page = pos + (1 << (unsigned int)j); + new_page->count = 0; + new_page->order = j; + list_add_tail(&new_page->node, &g_res_zone->free_areas[j].page_list); + } + list_del(&pos->node); + addr = pos->page->start; + break; + } + mutex_unlock(&g_res_lock); + return (void *)(uintptr_t)addr; } static int get_virt_page_index(const void *ptr) { - unsigned long vaddr = (unsigned long)(uintptr_t)ptr; - unsigned long offset = vaddr - g_start_vaddr; - int pg_idx = offset / (1 << PAGE_SHIFT); - if (pg_idx >= RESMEM_PAGE_MAX || pg_idx < 0) - return -1; - return pg_idx; + unsigned long vaddr = (unsigned long)(uintptr_t)ptr; + unsigned long offset = vaddr - g_start_vaddr; + int pg_idx = offset / (1 << PAGE_SHIFT); + if ((unsigned int)pg_idx >= get_res_page_size() || pg_idx < 0) + return -1; + return pg_idx; } static int buddy_merge(struct virt_page *vpage, int order, unsigned int *page_index) { - int i; - unsigned int cur_idx = 0; - unsigned int buddy_idx = 0; - struct reserved_page_t *self = NULL; - struct reserved_page_t *buddy = NULL; - - for (i = order; i < g_res_max_order; i++) { - cur_idx = vpage -g_res_zone->all_pages; - buddy_idx = cur_idx ^ (1 << (unsigned int)i); - self = &g_res_zone->pages[cur_idx]; - buddy = &g_res_zone->pages[buddy_idx]; - self->count = 0; - - if (buddy->order == i && buddy->count == 0) { - list_del(&buddy->node); - if (cur_idx > buddy_idx) { - vpage = buddy->page; - buddy->order = i + 1; - self->order = -1; - } else { - self->order = i + 1; - buddy->order = -1; - } - } else { - list_add_tail(&self->node, &g_res_zone->free_areas[i].page_list); - return -1; - } - } - - if (order == g_res_max_order) { - cur_idx = vpage - g_res_zone->all_pages; - tlogd("no need to find buddy, cur is %u\n", cur_idx); - *page_index = cur_idx; - return 0; - } - *page_index = (cur_idx > buddy_idx) ? buddy_idx : cur_idx; - return 0; + int i; + unsigned int cur_idx = 0; + unsigned int buddy_idx = 0; + struct reserved_page_t *self = NULL; + struct reserved_page_t *buddy = NULL; + + for (i = order; i < g_res_max_order; i++) { + cur_idx = vpage - g_res_zone->all_pages; + buddy_idx = cur_idx ^ (1 << (unsigned int)i); + self = &g_res_zone->pages[cur_idx]; + buddy = &g_res_zone->pages[buddy_idx]; + self->count = 0; + /* is buddy free */ + if (buddy->order == i && buddy->count == 0) { + /* release buddy */ + list_del(&buddy->node); + /* combine self and buddy */ + if (cur_idx > buddy_idx) { + vpage = buddy->page; + buddy->order = i + 1; + self->order = -1; + } else { + self->order = i + 1; + buddy->order = -1; + } + } else { + /* release self */ + list_add_tail(&self->node, + &g_res_zone->free_areas[i].page_list); + return -1; + } + } + + if (order == g_res_max_order) { + cur_idx = vpage - g_res_zone->all_pages; + tlogd("no need to find buddy, cur is %u\n", cur_idx); + *page_index = cur_idx; + return 0; + } + *page_index = (cur_idx > buddy_idx) ? buddy_idx : cur_idx; + return 0; } void reserved_mem_free(const void *ptr) { - struct reserved_page_t *self = NULL; - int self_idx; - unsigned int page_index; - struct reserved_page_t *max_order_page = NULL; - - if (ptr == NULL) { - tloge("invalid ptr\n"); - return; - } - - mutex_lock(&g_res_lock); - self_idx = get_virt_page_index(ptr); - if (self_idx < 0) { - mutex_unlock(&g_res_lock); - tloge("invalid page\n"); - return; - } - - self = &g_res_zone->pages[self_idx]; - if (!self->count) { - tloge("already free in reserved mempool\n"); - mutex_unlock(&g_res_lock); - return; - } - - if (buddy_merge(self->page, self->order, &page_index) < 0) { - mutex_unlock(&g_res_lock); - return; - } - - max_order_page = &g_res_zone->pages[page_index]; - list_add_tail(&max_order_page->node, - &g_res_zone->free_areas[g_res_max_order].page_list); - mutex_unlock(&g_res_lock); -} \ No newline at end of file + struct reserved_page_t *self = NULL; + int self_idx; + unsigned int page_index; + struct reserved_page_t *max_order_page = NULL; + + if (ptr == NULL) { + tloge("invalid ptr\n"); + return; + } + + mutex_lock(&g_res_lock); + self_idx = get_virt_page_index(ptr); + if (self_idx < 0) { + mutex_unlock(&g_res_lock); + tloge("invalid page\n"); + return; + } + self = &g_res_zone->pages[self_idx]; + if (self->count == 0) { + tloge("already free in reserved mempool\n"); + mutex_unlock(&g_res_lock); + return; + } + + if (buddy_merge(self->page, self->order, &page_index) < 0) { + mutex_unlock(&g_res_lock); + return; + } + + max_order_page = &g_res_zone->pages[page_index]; + list_add_tail(&max_order_page->node, + &g_res_zone->free_areas[g_res_max_order].page_list); + mutex_unlock(&g_res_lock); +} diff --git a/core/reserved_mempool.h b/core/reserved_mempool.h index e4bd2659c77b8522ea887d968c7ae49f4133cb65..af356837c035e0faf8b39653ea19270ba3491cbe 100644 --- a/core/reserved_mempool.h +++ b/core/reserved_mempool.h @@ -16,25 +16,19 @@ * GNU General Public License for more details. */ -#ifndef RESERVED_MEMPOOL_H -#define RESERVED_MEMPOOL_H +#ifndef RESERVED_MEMPOOOL_H +#define RESERVED_MEMPOOOL_H #include #include -#ifndef CONFIG_MAX_RES_MEM_ORDER -#define CONFIG_MAX_RES_MEM_ORDER 15 -#endif - -#define RESERVED_MEM_POOL_SIZE 0x8000000 //128M -#define RESEVED_MAX_ALLOC_SIZE (1 << (CONFIG_MAX_RES_MEM_ORDER + PAGE_SHIFT)) //2^max_order * 4k -#define LIMIT_RES_MEM_ORDER 15 - int load_reserved_mem(void); +void unmap_res_mem(void); void *reserved_mem_alloc(size_t size); void free_reserved_mempool(void); int reserved_mempool_init(void); void reserved_mem_free(const void *ptr); bool exist_res_mem(void); unsigned long res_mem_virt_to_phys(unsigned long vaddr); -#endif \ No newline at end of file +unsigned int get_res_mem_slice_size(void); +#endif diff --git a/core/secs_power_ctrl.h b/core/secs_power_ctrl.h index eb7b572c58883b90d78682f302dedbd7228a1ebc..85b4f2959615cb4ace3153812f3cc5ef714d550f 100644 --- a/core/secs_power_ctrl.h +++ b/core/secs_power_ctrl.h @@ -23,18 +23,18 @@ static int power_on_cc(void) { - return 0; + return 0; } static int power_down_cc(void) { - return 0; + return 0; } static void secs_suspend_status(uint64_t target) { - (void)target; - return; + (void)target; + return; } -#endif \ No newline at end of file +#endif diff --git a/core/session_manager.c b/core/session_manager.c index 3cf6532e6a26a317c838f71e302088f2f95a9eb9..adf2a1d65a608d7f68e9f1315f7a643a38447fdd 100644 --- a/core/session_manager.c +++ b/core/session_manager.c @@ -42,6 +42,7 @@ #include #endif #include +#include #include "smc_smp.h" #include "mem.h" #include "gp_ops.h" @@ -50,8 +51,8 @@ #include "client_hash_auth.h" #include "mailbox_mempool.h" #include "tc_client_driver.h" -#include "tee_trace_event.h" -#include "tz_kthread_affinity.h" +#include "internal_functions.h" +#include "ko_adapt.h" static DEFINE_MUTEX(g_load_app_lock); #define MAX_REF_COUNT (255) @@ -60,16 +61,6 @@ static DEFINE_MUTEX(g_load_app_lock); struct list_head g_service_list; DEFINE_MUTEX(g_service_list_lock); -struct load_img_params { - struct tc_ns_dev_file *dev_file; - const char *file_buffer; - unsigned int file_size; - struct mb_cmd_pack *mb_pack; - char *mb_load_mem; - struct tc_uuid *uuid_return; - unsigned int mb_load_size; -}; - void init_srvc_list(void) { INIT_LIST_HEAD(&g_service_list); @@ -88,7 +79,7 @@ void put_session_struct(struct tc_ns_session *session) if (!session || !atomic_dec_and_test(&session->usage)) return; - if (memset_s(session, sizeof(*session), 0, sizeof(*session))) + if (memset_s(session, sizeof(*session), 0, sizeof(*session)) != 0) tloge("Caution, memset failed!\n"); kfree(session); } @@ -137,6 +128,20 @@ static int add_service_to_dev(struct tc_ns_dev_file *dev, return -EFAULT; } +static void tz_srv_sess_dump(const char *param) +{ + struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; + + (void)param; + smc_cmd.cmd_id = GLOBAL_CMD_ID_DUMP_SRV_SESS; + smc_cmd.cmd_type = CMD_TYPE_GLOBAL; + + livepatch_down_read_sem(); + if (tc_ns_smc(&smc_cmd)) + tloge("send dump service session failed\n"); + livepatch_up_read_sem(); +} + void dump_services_status(const char *param) { struct tc_ns_service *service = NULL; @@ -149,6 +154,8 @@ void dump_services_status(const char *param) atomic_read(&service->usage)); } mutex_unlock(&g_service_list_lock); + + tz_srv_sess_dump(param); } static void del_service_from_dev(struct tc_ns_dev_file *dev, @@ -165,7 +172,7 @@ static void del_service_from_dev(struct tc_ns_dev_file *dev, break; } dev->service_ref[i]--; - if (!dev->service_ref[i]) { + if (dev->service_ref[i] == 0) { tlogd("del service %u from %u\n", i, dev->dev_file_id); dev->services[i] = NULL; @@ -178,7 +185,7 @@ static void del_service_from_dev(struct tc_ns_dev_file *dev, struct tc_ns_session *tc_find_session_withowner( const struct list_head *session_list, - unsigned int session_id, struct tc_ns_dev_file *dev_file) + unsigned int session_id, const struct tc_ns_dev_file *dev_file) { struct tc_ns_session *session = NULL; @@ -205,7 +212,7 @@ struct tc_ns_service *tc_find_service_in_dev(const struct tc_ns_dev_file *dev, for (i = 0; i < SERVICES_MAX_COUNT; i++) { if (dev->services[i] != NULL && - !memcmp(dev->services[i]->uuid, uuid, UUID_LEN)) + memcmp(dev->services[i]->uuid, uuid, UUID_LEN) == 0) return dev->services[i]; } return NULL; @@ -277,20 +284,20 @@ static int tc_ns_need_load_image(unsigned int file_id, } mb_pack->operation.paramtypes = TEEC_MEMREF_TEMP_INOUT; mb_pack->operation.params[0].memref.buffer = - virt_to_phys(mb_param); + mailbox_virt_to_phys((uintptr_t)mb_param); mb_pack->operation.buffer_h_addr[0] = - (uint64_t)virt_to_phys(mb_param) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)mb_param) >> ADDR_TRANS_NUM; mb_pack->operation.params[0].memref.size = SZ_4K; smc_cmd.cmd_id = GLOBAL_CMD_ID_NEED_LOAD_APP; smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.dev_file_id = file_id; smc_cmd.context_id = 0; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; smc_ret = tc_ns_smc(&smc_cmd); - if (smc_ret) { + if (smc_ret != 0) { tloge("smc call returns error ret 0x%x\n", smc_ret); ret = -EFAULT; goto clean; @@ -306,46 +313,116 @@ clean: } int tc_ns_load_secfile(struct tc_ns_dev_file *dev_file, - const void __user *argp) + void __user *argp, bool is_from_client_node) { int ret; - struct load_secfile_ioctl_struct ioctl_arg = { 0, {0}, 0, {NULL} }; + struct load_secfile_ioctl_struct ioctl_arg = { {0}, {0}, {NULL} }; + bool load = true; + void *file_addr = NULL; if (!dev_file || !argp) { tloge("Invalid params !\n"); return -EINVAL; } - if (copy_from_user(&ioctl_arg, argp, sizeof(ioctl_arg))) { + if (copy_from_user(&ioctl_arg, argp, sizeof(ioctl_arg)) != 0) { tloge("copy from user failed\n"); ret = -ENOMEM; return ret; } + if (ioctl_arg.sec_file_info.secfile_type >= LOAD_TYPE_MAX || + ioctl_arg.sec_file_info.secfile_type == LOAD_PATCH) { + tloge("invalid secfile type: %d!", ioctl_arg.sec_file_info.secfile_type); + return -EINVAL; + } + mutex_lock(&g_load_app_lock); - if (ioctl_arg.secfile_type == LOAD_TA) { + if (is_from_client_node) { + if (ioctl_arg.sec_file_info.secfile_type != LOAD_TA && + ioctl_arg.sec_file_info.secfile_type != LOAD_LIB) { + tloge("this node does not allow this type of file to be loaded\n"); + mutex_unlock(&g_load_app_lock); + return -EINVAL; + } + } + + if (ioctl_arg.sec_file_info.secfile_type == LOAD_TA) { ret = tc_ns_need_load_image(dev_file->dev_file_id, ioctl_arg.uuid, - (unsigned int)UUID_LEN); - if (ret == 1) /* 1 means we need to load image */ - ret = tc_ns_load_image(dev_file, ioctl_arg.file_buffer, - ioctl_arg.file_size, NULL, ioctl_arg.secfile_type); - } else if (ioctl_arg.secfile_type == LOAD_LIB) { - ret = tc_ns_load_image(dev_file, ioctl_arg.file_buffer, - ioctl_arg.file_size, NULL, ioctl_arg.secfile_type); - } else if (ioctl_arg.secfile_type == LOAD_DYNAMIC_DRV || ioctl_arg.secfile_type == LOAD_SERVICE) { - ret = tc_ns_load_image(dev_file, ioctl_arg.file_buffer, - ioctl_arg.file_size, NULL, ioctl_arg.secfile_type); - } else { - tloge("invalid secfile type: %d!", ioctl_arg.secfile_type); - ret = -EINVAL; + (unsigned int)UUID_LEN); + if (ret != 1) /* 1 means we need to load image */ + load = false; + } + + if (load) { + file_addr = (void *)(uintptr_t)(ioctl_arg.memref.file_addr | + (((uint64_t)ioctl_arg.memref.file_h_addr) << ADDR_TRANS_NUM)); + ret = tc_ns_load_image(dev_file, file_addr, &ioctl_arg.sec_file_info, NULL); + if (ret != 0) + tloge("load TA secfile: %d failed, ret = 0x%x\n", + ioctl_arg.sec_file_info.secfile_type, ret); } - if (ret) - tloge("load TA secfile: %d failed, ret = %x", - ioctl_arg.secfile_type, ret); mutex_unlock(&g_load_app_lock); + if (copy_to_user(argp, &ioctl_arg, sizeof(ioctl_arg)) != 0) + tloge("copy to user failed\n"); return ret; } +static uint32_t tc_ns_get_uid(void) +{ + struct task_struct *task = NULL; + const struct cred *cred = NULL; + uint32_t uid; + + rcu_read_lock(); + task = get_current(); + get_task_struct(task); + rcu_read_unlock(); + cred = koadpt_get_task_cred(task); + if (!cred) { + tloge("failed to get uid of the task\n"); + put_task_struct(task); + return (uint32_t)(-1); + } + + uid = cred->uid.val; + put_cred(cred); + put_task_struct(task); + tlogd("current uid is %u\n", uid); + return uid; +} + +#ifdef CONFIG_AUTH_SUPPORT_UNAME +static int set_login_information_uname(struct tc_ns_dev_file *dev_file, uint32_t uid) +{ + char uname[MAX_NAME_LENGTH] = { 0 }; + uint32_t username_len = 0; + int ret = tc_ns_get_uname(uid, uname, sizeof(uname), &username_len); + if (ret < 0 || username_len >= MAX_NAME_LENGTH) { + tloge("get user name filed\n"); + return -EFAULT; + } + if (memcpy_s(dev_file->pub_key, MAX_PUBKEY_LEN, uname, username_len)) { + tloge("failed to copy username, pub key len=%u\n", dev_file->pub_key_len); + return -EFAULT; + } + /* use pub_key to store username info */ + dev_file->pub_key_len = username_len; + return 0; +} +#else +static int set_login_information_uid(struct tc_ns_dev_file *dev_file, uint32_t ca_uid) +{ + if (memcpy_s(dev_file->pub_key, MAX_PUBKEY_LEN, &ca_uid, sizeof(ca_uid)) != 0) { + tloge("failed to copy pubkey, pub key len=%u\n", + dev_file->pub_key_len); + return -EFAULT; + } + dev_file->pub_key_len = sizeof(ca_uid); + return 0; +} +#endif + /* * Modify the client context so params id 2 and 3 contain temp pointers to the * public key and package name for the open session. This is used for the @@ -354,48 +431,58 @@ int tc_ns_load_secfile(struct tc_ns_dev_file *dev_file, static int set_login_information(struct tc_ns_dev_file *dev_file, struct tc_ns_client_context *context) { + uint64_t size_addr, buffer_addr; /* The daemon has failed to get login information or not supplied */ - if (!dev_file->pkg_name_len) + if (dev_file->pkg_name_len == 0) return -EINVAL; /* * The 3rd parameter buffer points to the pkg name buffer in the * device file pointer * get package name len and package name */ - context->params[3].memref.size_addr = - (__u64)(uintptr_t)&dev_file->pkg_name_len; - context->params[3].memref.buffer = - (__u64)(uintptr_t)dev_file->pkg_name; + size_addr = (__u64)(uintptr_t)&dev_file->pkg_name_len; + buffer_addr = (__u64)(uintptr_t)dev_file->pkg_name; + context->params[3].memref.size_addr = (__u32)size_addr; + context->params[3].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM); + context->params[3].memref.buffer = (__u32)buffer_addr; + context->params[3].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM); + /* Set public key len and public key */ - if (dev_file->pub_key_len) { - context->params[2].memref.size_addr = - (__u64)(uintptr_t)&dev_file->pub_key_len; - context->params[2].memref.buffer = - (__u64)(uintptr_t)dev_file->pub_key; - } else { + if (dev_file->pub_key_len == 0) { /* If get public key failed, then get uid in kernel */ uint32_t ca_uid = tc_ns_get_uid(); if (ca_uid == (uint32_t)(-1)) { tloge("failed to get uid of the task\n"); goto error; } - dev_file->pub_key_len = sizeof(ca_uid); - context->params[2].memref.size_addr = - (__u64)(uintptr_t)&dev_file->pub_key_len; - if (memcpy_s(dev_file->pub_key, MAX_PUBKEY_LEN, &ca_uid, - dev_file->pub_key_len)) { - tloge("failed to copy pubkey, pub key len=%u\n", - dev_file->pub_key_len); +#ifdef CONFIG_AUTH_SUPPORT_UNAME + if (set_login_information_uname(dev_file, ca_uid) != 0) goto error; - } - context->params[2].memref.buffer = - (__u64)(uintptr_t)dev_file->pub_key; +#else + if (set_login_information_uid(dev_file, ca_uid) != 0) + goto error; +#endif +#ifdef CONFIG_AUTH_HASH + dev_file->pkg_name_len = strlen((unsigned char *)dev_file->pkg_name); +#endif } + size_addr = (__u64)(uintptr_t)&dev_file->pub_key_len; + buffer_addr = (__u64)(uintptr_t)dev_file->pub_key; + context->params[2].memref.size_addr = (__u32)size_addr; + context->params[2].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM); + context->params[2].memref.buffer = (__u32)buffer_addr; + context->params[2].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM); /* Now we mark the 2 parameters as input temp buffers */ context->param_types = teec_param_types( teec_param_type_get(context->param_types, 0), teec_param_type_get(context->param_types, 1), TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT); +#ifdef CONFIG_AUTH_HASH + if(set_login_information_hash(dev_file) != 0) { + tloge("set login information hash failed\n"); + goto error; + } +#endif return 0; error: return -EFAULT; @@ -409,8 +496,14 @@ static int check_login_method(struct tc_ns_dev_file *dev_file, if (!dev_file || !context || !flags) return -EFAULT; + if (is_tee_rebooting()) { + context->returns.code = TEE_ERROR_IS_DEAD; + /* when ret > 0, use context return code */ + return EFAULT; + } + if (context->login.method != TEEC_LOGIN_IDENTIFY) { - tlogd("login method is not supported\n"); + tloge("login method is not supported\n"); return -EINVAL; } @@ -422,7 +515,7 @@ static int check_login_method(struct tc_ns_dev_file *dev_file, return -EINVAL; ret = set_login_information(dev_file, context); - if (ret) { + if (ret != 0) { tloge("set login information failed ret =%d\n", ret); return ret; } @@ -441,7 +534,7 @@ static struct tc_ns_service *tc_ref_service_in_dev(struct tc_ns_dev_file *dev, for (i = 0; i < SERVICES_MAX_COUNT; i++) { if (dev->services[i] != NULL && - !memcmp(dev->services[i]->uuid, uuid, UUID_LEN)) { + memcmp(dev->services[i]->uuid, uuid, UUID_LEN) == 0) { if (dev->service_ref[i] == MAX_REF_COUNT) { *is_full = true; return NULL; @@ -469,7 +562,7 @@ static int tc_ns_service_init(const unsigned char *uuid, uint32_t uuid_len, return ret; } - if (memcpy_s(service->uuid, sizeof(service->uuid), uuid, uuid_len)) { + if (memcpy_s(service->uuid, sizeof(service->uuid), uuid, uuid_len) != 0) { kfree(service); return -EFAULT; } @@ -477,7 +570,7 @@ static int tc_ns_service_init(const unsigned char *uuid, uint32_t uuid_len, INIT_LIST_HEAD(&service->session_list); mutex_init(&service->session_lock); list_add_tail(&service->head, &g_service_list); - tlogd("add service: 0x%x to service list\n", *(uint32_t *)uuid); + tlogd("add service: 0x%x to service list\n", *(const uint32_t *)uuid); atomic_set(&service->usage, 1); mutex_init(&service->operation_lock); *new_service = service; @@ -494,7 +587,7 @@ static struct tc_ns_service *tc_find_service_from_all( return NULL; list_for_each_entry(service, &g_service_list, head) { - if (!memcmp(service->uuid, uuid, sizeof(service->uuid))) + if (memcmp(service->uuid, uuid, sizeof(service->uuid)) == 0) return service; } @@ -535,7 +628,7 @@ static struct tc_ns_service *find_service(struct tc_ns_dev_file *dev_file, ret = tc_ns_service_init(context->uuid, UUID_LEN, &service); /* unlock after init to make sure find service from all is correct */ mutex_unlock(&g_service_list_lock); - if (ret) { + if (ret != 0) { tloge("service init failed"); mutex_unlock(&dev_file->service_lock); return NULL; @@ -543,7 +636,7 @@ static struct tc_ns_service *find_service(struct tc_ns_dev_file *dev_file, add_service: ret = add_service_to_dev(dev_file, service); mutex_unlock(&dev_file->service_lock); - if (ret) { + if (ret != 0) { /* * for new srvc, match init usage to 1; * for srvc already exist, match get; @@ -558,7 +651,7 @@ add_service: static bool is_valid_ta_size(const char *file_buffer, unsigned int file_size) { - if (!file_buffer || !file_size) { + if (!file_buffer || file_size == 0) { tloge("invalid load ta size\n"); return false; } @@ -614,30 +707,30 @@ static void pack_load_frame_cmd(uint32_t load_size, struct tc_uuid *uuid_return = params->uuid_return; mb_pack->operation.params[0].memref.buffer = - virt_to_phys(mb_load_mem); + mailbox_virt_to_phys((uintptr_t)mb_load_mem); mb_pack->operation.buffer_h_addr[0] = - (uint64_t)virt_to_phys(mb_load_mem) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)mb_load_mem) >> ADDR_TRANS_NUM; mb_pack->operation.params[0].memref.size = load_size + sizeof(int); mb_pack->operation.params[2].memref.buffer = - virt_to_phys(uuid_return); + mailbox_virt_to_phys((uintptr_t)uuid_return); mb_pack->operation.buffer_h_addr[2] = - (uint64_t)virt_to_phys(uuid_return) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)uuid_return) >> ADDR_TRANS_NUM; mb_pack->operation.params[2].memref.size = sizeof(*uuid_return); mb_pack->operation.paramtypes = teec_param_types(TEEC_MEMREF_TEMP_INPUT, - TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_VALUE_INPUT); + TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_VALUE_INOUT); smc_cmd->cmd_type = CMD_TYPE_GLOBAL; smc_cmd->cmd_id = GLOBAL_CMD_ID_LOAD_SECURE_APP; smc_cmd->context_id = 0; - smc_cmd->operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd->operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd->operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; } static int32_t load_image_copy_file(struct load_img_params *params, uint32_t load_size, int32_t load_flag, uint32_t loaded_size) { - if (!current->mm) { + if (params->dev_file->kernel_api == TEE_REQ_FROM_KERNEL_MODE) { if (memcpy_s(params->mb_load_mem + sizeof(load_flag), params->mb_load_size - sizeof(load_flag), params->file_buffer + loaded_size, load_size) != 0) { @@ -647,15 +740,15 @@ static int32_t load_image_copy_file(struct load_img_params *params, uint32_t loa return 0; } if (copy_from_user(params->mb_load_mem + sizeof(load_flag), - (void __user *)params->file_buffer + loaded_size, load_size)) { + (const void __user *)params->file_buffer + loaded_size, load_size)) { tloge("file buf get fail\n"); return -EFAULT; } return 0; } -static int load_image_by_frame(struct load_img_params *params, - unsigned int load_times, struct tc_ns_client_return *tee_ret, enum secfile_type_t type) +static int load_image_by_frame(struct load_img_params *params, unsigned int load_times, + struct tc_ns_client_return *tee_ret, struct sec_file_info *sec_file_info) { char *p = params->mb_load_mem; uint32_t load_size; @@ -685,21 +778,25 @@ static int load_image_by_frame(struct load_img_params *params, pack_load_frame_cmd(load_size, params, &smc_cmd); params->mb_pack->operation.params[3].value.a = index; - params->mb_pack->operation.params[1].value.a = (type == LOAD_DYNAMIC_DRV ? 1 : 0); + params->mb_pack->operation.params[1].value.a = sec_file_info->secfile_type; smc_cmd.dev_file_id = params->dev_file->dev_file_id; smc_ret = tc_ns_smc(&smc_cmd); tlogd("configid=%u, ret=%d, load_flag=%d, index=%u\n", params->mb_pack->operation.params[1].value.a, smc_ret, load_flag, index); - if (smc_ret) { + if (smc_ret != 0) { if (tee_ret != NULL) { tee_ret->code = smc_ret; tee_ret->origin = smc_cmd.err_origin; } + sec_file_info->sec_load_err = (int32_t)params->mb_pack->operation.params[3].value.b; return -EFAULT; } + if (!smc_ret && !load_flag && load_image_for_ion(params, tee_ret ? &tee_ret->origin : NULL)) + return -EPERM; + loaded_size += load_size; } return 0; @@ -709,63 +806,101 @@ int tc_ns_load_image_with_lock(struct tc_ns_dev_file *dev, const char *file_buff unsigned int file_size, enum secfile_type_t type) { int ret; + struct sec_file_info sec_file = {0, 0, 0}; if (!dev || !file_buffer) { tloge("dev or file buffer is NULL!\n"); return -EINVAL; } + sec_file.secfile_type = type; + sec_file.file_size = file_size; + mutex_lock(&g_load_app_lock); - ret = tc_ns_load_image(dev, file_buffer, file_size, NULL, type); + ret = tc_ns_load_image(dev, file_buffer, &sec_file, NULL); mutex_unlock(&g_load_app_lock); return ret; } -int tc_ns_load_image(struct tc_ns_dev_file *dev, const char *file_buffer, - unsigned int file_size, struct tc_ns_client_return *tee_ret, enum secfile_type_t type) +static void free_load_image_buffer(struct load_img_params *params) +{ + mailbox_free(params->mb_load_mem); + mailbox_free(params->mb_pack); + mailbox_free(params->uuid_return); +} + +int load_image(struct load_img_params *params, + struct sec_file_info *sec_file_info, struct tc_ns_client_return *tee_ret) { int ret; unsigned int load_times; - struct load_img_params params = { - dev, file_buffer, file_size, NULL, NULL, NULL, 0 - }; + unsigned int file_size; - if (!dev || !file_buffer) { - tloge("dev or file buffer is NULL!\n"); - return -EINVAL; - } + /* tee_ret can be null */ + if (params == NULL || sec_file_info == NULL) + return -1; - if (!is_valid_ta_size(file_buffer, file_size)) - return -EINVAL; + file_size = params->file_size; - params.mb_load_size = (file_size > (SZ_1M - sizeof(int))) ? + params->mb_load_size = (file_size > (SZ_1M - sizeof(int))) ? SZ_1M : ALIGN(file_size, SZ_4K); - ret = alloc_for_load_image(¶ms); - if (ret) + + ret = alloc_for_load_image(params); + if (ret != 0) { + tloge("Alloc load image buf fail!\n"); return ret; + } - if (params.mb_load_size <= sizeof(int)) { + if (params->mb_load_size <= sizeof(int)) { tloge("mb load size is too small!\n"); - ret = -ENOMEM; - goto free_mem; + free_load_image_buffer(params); + return -ENOMEM; } - load_times = file_size / (params.mb_load_size - sizeof(int)); - if (file_size % (params.mb_load_size - sizeof(int))) + + load_times = file_size / (params->mb_load_size - sizeof(int)); + if ((file_size % (params->mb_load_size - sizeof(int))) != 0) load_times += 1; - ret = load_image_by_frame(¶ms, load_times, tee_ret, type); -free_mem: - mailbox_free(params.mb_load_mem); - mailbox_free(params.mb_pack); - mailbox_free(params.uuid_return); - return ret; + + ret = load_image_by_frame(params, load_times, tee_ret, sec_file_info); + if (ret != 0) { + tloge("load image by frame fail!\n"); + free_load_image_buffer(params); + return ret; + } + + free_load_image_buffer(params); + return 0; +} + +int tc_ns_load_image(struct tc_ns_dev_file *dev, const char *file_buffer, + struct sec_file_info *sec_file_info, struct tc_ns_client_return *tee_ret) +{ + unsigned int file_size; + struct load_img_params params = { dev, file_buffer, 0, NULL, NULL, NULL, 0 }; + + if (!dev || !file_buffer || !sec_file_info) { + tloge("dev or file buffer or sec_file_info is NULL!\n"); + return -EINVAL; + } + + file_size = sec_file_info->file_size; + params.file_size = file_size; + + if (!is_valid_ta_size(file_buffer, file_size)) + return -EINVAL; + + return load_image(¶ms, sec_file_info, tee_ret); } static int load_ta_image(struct tc_ns_dev_file *dev_file, struct tc_ns_client_context *context) { int ret; + struct sec_file_info sec_file = {0, 0, 0}; struct tc_ns_client_return tee_ret = {0}; + void *file_addr = NULL; + tee_ret.origin = TEEC_ORIGIN_COMMS; mutex_lock(&g_load_app_lock); @@ -777,9 +912,12 @@ static int load_ta_image(struct tc_ns_dev_file *dev_file, mutex_unlock(&g_load_app_lock); return -1; } - ret = tc_ns_load_image(dev_file, context->file_buffer, - context->file_size, &tee_ret, LOAD_TA); - if (ret) { + file_addr = (void *)(uintptr_t)(context->memref.file_addr | + (((uint64_t)context->memref.file_h_addr) << ADDR_TRANS_NUM)); + sec_file.secfile_type = LOAD_TA; + sec_file.file_size = context->file_size; + ret = tc_ns_load_image(dev_file, file_addr, &sec_file, &tee_ret); + if (ret != 0) { tloge("load image failed, ret=%x", ret); context->returns.code = tee_ret.code; if (tee_ret.origin != TEEC_ORIGIN_COMMS) { @@ -791,6 +929,7 @@ static int load_ta_image(struct tc_ns_dev_file *dev_file, } } mutex_unlock(&g_load_app_lock); + return ret; } @@ -822,15 +961,16 @@ static int proc_open_session(struct tc_ns_dev_file *dev_file, mutex_lock(&service->operation_lock); ret = load_ta_image(dev_file, context); - if (ret) { + if (ret != 0) { tloge("load ta image failed\n"); mutex_unlock(&service->operation_lock); return ret; } ret = tc_client_call(¶ms); - if (ret) { + if (ret != 0) { /* Clean this session secure information */ + kill_ion_by_uuid((struct tc_uuid *)context->uuid); mutex_unlock(&service->operation_lock); tloge("smc call returns error, ret=0x%x\n", ret); return ret; @@ -848,9 +988,13 @@ static int proc_open_session(struct tc_ns_dev_file *dev_file, static void clear_context_param(struct tc_ns_client_context *context) { context->params[2].memref.size_addr = 0; + context->params[2].memref.size_h_addr = 0; context->params[2].memref.buffer = 0; + context->params[2].memref.buffer_h_addr = 0; context->params[3].memref.size_addr = 0; + context->params[3].memref.size_h_addr = 0; context->params[3].memref.buffer = 0; + context->params[3].memref.buffer_h_addr = 0; } int tc_ns_open_session(struct tc_ns_dev_file *dev_file, @@ -867,7 +1011,7 @@ int tc_ns_open_session(struct tc_ns_dev_file *dev_file, } ret = check_login_method(dev_file, context, &flags); - if (ret) + if (ret != 0) goto err_clear_param; context->cmd_id = GLOBAL_CMD_ID_OPEN_SESSION; @@ -891,15 +1035,14 @@ int tc_ns_open_session(struct tc_ns_dev_file *dev_file, mutex_init(&session->ta_session_lock); ret = calc_client_auth_hash(dev_file, context, session); - if (ret) { + if (ret != 0) { tloge("calc client auth hash failed\n"); goto err_free_rsrc; } ret = proc_open_session(dev_file, context, service, session, flags); - if (!ret) + if (ret == 0) goto err_clear_param; - err_free_rsrc: mutex_lock(&dev_file->service_lock); del_service_from_dev(dev_file, service); @@ -912,7 +1055,7 @@ err_clear_param: } static struct tc_ns_session *get_session(struct tc_ns_service *service, - struct tc_ns_dev_file *dev_file, + const struct tc_ns_dev_file *dev_file, const struct tc_ns_client_context *context) { struct tc_ns_session *session = NULL; @@ -952,19 +1095,20 @@ static int close_session(struct tc_ns_dev_file *dev, if (uuid_len != UUID_LEN) return -EINVAL; - if (memset_s(&context, sizeof(context), 0, sizeof(context))) + if (memset_s(&context, sizeof(context), 0, sizeof(context)) != 0) return -EFAULT; - if (memcpy_s(context.uuid, sizeof(context.uuid), uuid, uuid_len)) + if (memcpy_s(context.uuid, sizeof(context.uuid), uuid, uuid_len) != 0) return -EFAULT; context.session_id = session_id; context.cmd_id = GLOBAL_CMD_ID_CLOSE_SESSION; params.flags = TC_CALL_GLOBAL | TC_CALL_SYNC; ret = tc_client_call(¶ms); - if (ret) + if (ret != 0) tloge("close session failed, ret=0x%x\n", ret); + kill_ion_by_uuid((struct tc_uuid *)context.uuid); return ret; } @@ -981,14 +1125,13 @@ static void close_session_in_service_list(struct tc_ns_dev_file *dev, continue; ret = close_session(dev, session, service->uuid, (unsigned int)UUID_LEN, session->session_id); - if (ret) + if (ret != 0) tloge("close session smc failed when close fd!\n"); - mutex_lock(&service->session_lock); list_del(&session->head); mutex_unlock(&service->session_lock); - put_session_struct(session); /* pair with find session */ + put_session_struct(session); /* pair with open session */ } } @@ -998,7 +1141,7 @@ static bool if_exist_unclosed_session(struct tc_ns_dev_file *dev) for (index = 0; index < SERVICES_MAX_COUNT; index++) { if (dev->services[index] != NULL && - !list_empty(&dev->services[index]->session_list)) + list_empty(&dev->services[index]->session_list) == 0) return true; } return false; @@ -1013,7 +1156,7 @@ static int close_session_thread_fn(void *arg) /* close unclosed session */ for (index = 0; index < SERVICES_MAX_COUNT; index++) { if (dev->services[index] != NULL && - !list_empty(&dev->services[index]->session_list)) { + list_empty(&dev->services[index]->session_list) == 0) { service = dev->services[index]; mutex_lock(&service->operation_lock); @@ -1041,6 +1184,10 @@ void close_unclosed_session_in_kthread(struct tc_ns_dev_file *dev) if (!if_exist_unclosed_session(dev)) return; + /* when self recovery, release session in reboot interface */ + if (is_tee_rebooting()) + return; + close_thread = kthread_create(close_session_thread_fn, dev, "close_fn_%6d", dev->dev_file_id); if (unlikely(IS_ERR_OR_NULL(close_thread))) { @@ -1055,7 +1202,7 @@ void close_unclosed_session_in_kthread(struct tc_ns_dev_file *dev) } int tc_ns_close_session(struct tc_ns_dev_file *dev_file, - const struct tc_ns_client_context *context) + struct tc_ns_client_context *context) { int ret = -EINVAL; struct tc_ns_service *service = NULL; @@ -1065,6 +1212,12 @@ int tc_ns_close_session(struct tc_ns_dev_file *dev_file, tloge("invalid dev_file or context\n"); return ret; } + + if (is_tee_rebooting()) { + context->returns.code = TEE_ERROR_IS_DEAD; + return TEE_ERROR_IS_DEAD; + } + service = get_service(dev_file, context); if (!service) { tloge("invalid service\n"); @@ -1083,9 +1236,8 @@ int tc_ns_close_session(struct tc_ns_dev_file *dev_file, ret2 = close_session(dev_file, session, context->uuid, (unsigned int)UUID_LEN, context->session_id); mutex_unlock(&session->ta_session_lock); - if (ret2) + if (ret2 != 0) tloge("close session smc failed!\n"); - mutex_lock(&service->session_lock); list_del(&session->head); mutex_unlock(&service->session_lock); @@ -1120,6 +1272,11 @@ int tc_ns_send_cmd(struct tc_ns_dev_file *dev_file, return ret; } + if (is_tee_rebooting()) { + context->returns.code = TEE_ERROR_IS_DEAD; + return EFAULT; + } + service = get_service(dev_file, context); if (service) { session = get_session(service, dev_file, context); @@ -1141,7 +1298,7 @@ find_session: ret = tc_client_call(¶ms); mutex_unlock(&session->ta_session_lock); put_session_struct(session); - if (ret) + if (ret != 0) tloge("smc call returns error, ret=0x%x\n", ret); return ret; } @@ -1152,10 +1309,10 @@ static int ioctl_session_send_cmd(struct tc_ns_dev_file *dev_file, int ret; ret = tc_ns_send_cmd(dev_file, context); - if (ret) + if (ret != 0) tloge("send cmd failed ret is %d\n", ret); - if (copy_to_user(argp, context, sizeof(*context))) { - if (!ret) + if (copy_to_user(argp, context, sizeof(*context)) != 0) { + if (ret == 0) ret = -EFAULT; } return ret; @@ -1175,19 +1332,18 @@ int tc_client_session_ioctl(struct file *file, unsigned int cmd, } dev_file = file->private_data; - if (copy_from_user(&context, argp, sizeof(context))) { + if (copy_from_user(&context, argp, sizeof(context)) != 0) { tloge("copy from user failed\n"); return -EFAULT; } context.returns.origin = TEEC_ORIGIN_COMMS; - freezer_do_not_count(); switch (cmd) { case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ: ret = tc_ns_open_session(dev_file, &context); - if (ret) + if (ret != 0) tloge("open session failed ret is %d\n", ret); - if (copy_to_user(argp, &context, sizeof(context)) && !ret) + if (copy_to_user(argp, &context, sizeof(context)) != 0 && ret == 0) ret = -EFAULT; break; case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ: @@ -1203,7 +1359,6 @@ int tc_client_session_ioctl(struct file *file, unsigned int cmd, tloge("invalid cmd:0x%x!\n", cmd); return ret; } - freezer_count(); /* * Don't leak ERESTARTSYS to user space. * @@ -1230,3 +1385,59 @@ int tc_client_session_ioctl(struct file *file, unsigned int cmd, } return ret; } + +static void cleanup_session(struct tc_ns_service *service) +{ + struct tc_ns_session *session = NULL; + struct tc_ns_session *session_tmp = NULL; + + if (!service) + return; + + /* close unclosed session */ + if (list_empty(&service->session_list) == 0) { + mutex_lock(&service->operation_lock); + list_for_each_entry_safe(session, session_tmp, &service->session_list, head) { + tlogd("clean up session %u\n", session->session_id); + mutex_lock(&service->session_lock); + list_del(&session->head); + mutex_unlock(&service->session_lock); + put_session_struct(session); + } + mutex_unlock(&service->operation_lock); + } + put_service_struct(service); + + return; +} + +void free_all_session(void) +{ + struct tc_ns_dev_file *dev_file = NULL; + struct tc_ns_dev_file *dev_file_tmp = NULL; + struct tc_ns_dev_list *dev_list = NULL; + int i; + + dev_list = get_dev_list(); + if (!dev_list) { + tloge("cleanup session, dev list is null\n"); + return; + } + mutex_lock(&dev_list->dev_lock); + list_for_each_entry_safe(dev_file, dev_file_tmp, &dev_list->dev_file_list, head) { + mutex_lock(&dev_file->service_lock); + for (i = 0; i < SERVICES_MAX_COUNT; i++) { + if (dev_file->services[i] == NULL) + continue; + get_service_struct(dev_file->services[i]); + /* avoid dead lock in close session */ + mutex_unlock(&dev_file->service_lock); + cleanup_session(dev_file->services[i]); + mutex_lock(&dev_file->service_lock); + dev_file->services[i] = NULL; + } + mutex_unlock(&dev_file->service_lock); + } + mutex_unlock(&dev_list->dev_lock); + return; +} diff --git a/core/session_manager.h b/core/session_manager.h index ff94d1ddc45858d6b41161edb99e8516124f5518..4a08bf02d7629a7e6d1c4fa97d517bcb7cc0e26c 100644 --- a/core/session_manager.h +++ b/core/session_manager.h @@ -27,13 +27,13 @@ int tc_client_session_ioctl(struct file *file, unsigned int cmd, int tc_ns_open_session(struct tc_ns_dev_file *dev_file, struct tc_ns_client_context *context); int tc_ns_close_session(struct tc_ns_dev_file *dev_file, - const struct tc_ns_client_context *context); + struct tc_ns_client_context *context); int tc_ns_send_cmd(struct tc_ns_dev_file *dev_file, struct tc_ns_client_context *context); int tc_ns_load_image(struct tc_ns_dev_file *dev, const char *file_buffer, - unsigned int file_size, struct tc_ns_client_return *tee_ret, enum secfile_type_t type); + struct sec_file_info *sec_file_info, struct tc_ns_client_return *tee_ret); int tc_ns_load_image_with_lock(struct tc_ns_dev_file *dev, - const char *buffer, unsigned int file_size, enum secfile_type_t type); + const char *file_buffer, unsigned int file_size, enum secfile_type_t type); void close_unclosed_session_in_kthread(struct tc_ns_dev_file *dev); struct tc_ns_session *tc_find_session_by_uuid(unsigned int dev_file_id, const struct tc_ns_smc_cmd *cmd); @@ -41,14 +41,17 @@ struct tc_ns_service *tc_find_service_in_dev(const struct tc_ns_dev_file *dev, const unsigned char *uuid, int uuid_size); struct tc_ns_session *tc_find_session_withowner( const struct list_head *session_list, unsigned int session_id, - struct tc_ns_dev_file *dev_file); + const struct tc_ns_dev_file *dev_file); int tc_ns_load_secfile(struct tc_ns_dev_file *dev_file, - const void __user *argp); + void __user *argp, bool is_from_client_node); +int load_image(struct load_img_params *params, + struct sec_file_info *sec_file_info, struct tc_ns_client_return *tee_ret); void get_service_struct(struct tc_ns_service *service); void put_service_struct(struct tc_ns_service *service); void get_session_struct(struct tc_ns_session *session); void put_session_struct(struct tc_ns_session *session); void dump_services_status(const char *param); void init_srvc_list(void); +void free_all_session(void); #endif diff --git a/core/shared_mem.c b/core/shared_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..3e0b0d8fd10dd5eec0abad7448ea0f62680e8e80 --- /dev/null +++ b/core/shared_mem.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include "shared_mem.h" +#include +#include +#include +#include +#include +#include +#include +#include "tc_ns_log.h" +#include "tc_ns_client.h" +#include "teek_ns_client.h" +#include "smc_smp.h" +#include "internal_functions.h" +#include "mailbox_mempool.h" +#include "ko_adapt.h" + +#ifdef CONFIG_SHARED_MEM_RESERVED + +#define CMD_MEM_MIN_SIZE 0x1000 +#define SPI_MEM_MIN_SIZE 0x1000 +#define OPERATION_MEM_MIN_SIZE 0x1000 +uint64_t g_cmd_mem_paddr; +uint64_t g_cmd_mem_size; +uint64_t g_mailbox_paddr; +uint64_t g_mailbox_size; +uint64_t g_log_mem_paddr; +uint64_t g_log_mem_size; +uint64_t g_spi_mem_paddr; +uint64_t g_spi_mem_size; +static mailbox_page_t *g_mailbox_page; +static uintptr_t g_shmem_start_virt; +static uintptr_t g_page_offset; + +int load_tz_shared_mem(struct device_node *np) +{ + int rc; + + rc = of_property_read_u64(np, "tz_shmem_cmd_addr", &g_cmd_mem_paddr); + if (rc != 0) { + tloge("read tz_shmem_cmd_addr failed\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_cmd_size", &g_cmd_mem_size); + if (rc != 0 || g_cmd_mem_size < CMD_MEM_MIN_SIZE) { + tloge("read tz_shmem_cmd_size failed or size too short\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_mailbox_addr", &g_mailbox_paddr); + if (rc != 0) { + tloge("read tz_shmem_mailbox_addr failed\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_mailbox_size", &g_mailbox_size); + if (rc != 0 || g_mailbox_size < MAILBOX_POOL_SIZE + OPERATION_MEM_MIN_SIZE) { + tloge("read tz_shmem_mailbox_size failed or size too short\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_spi_addr", &g_spi_mem_paddr); + if (rc != 0) { + tloge("read tz_shmem_spi_addr failed\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_spi_size", &g_spi_mem_size); + if (rc != 0 || g_spi_mem_size < SPI_MEM_MIN_SIZE) { + tloge("read tz_shmem_spi_size failed or size too short\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_log_addr", &g_log_mem_paddr); + if (rc != 0) { + tloge("read tz_shmem_log_addr failed\n"); + return -ENODEV; + } + + rc = of_property_read_u64(np, "tz_shmem_log_size", &g_log_mem_size); + if (rc != 0 || g_log_mem_size < PAGES_LOG_MEM_LEN) { + tloge("read tz_shmem_log_size failed or size too short\n"); + return -ENODEV; + } + + return 0; +} + +mailbox_page_t *mailbox_alloc_pages(int order) +{ + uint32_t i; + uint32_t page_num = 1 << (unsigned int)order; + uint32_t page_size = page_num * sizeof(mailbox_page_t); + + g_page_offset = MAILBOX_POOL_SIZE / page_num; + g_mailbox_page = kmalloc(page_size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)g_mailbox_page)) { + tloge("Failed to allocate mailbox page\n"); + return NULL; + } + + g_shmem_start_virt = (uintptr_t)ioremap_cache(g_mailbox_paddr, g_mailbox_size); + if (g_shmem_start_virt == 0) { + tloge("io remap for mailbox page failed\n"); + kfree(g_mailbox_page); + g_mailbox_page = NULL; + return NULL; + } + (void)memset_s((void *)g_shmem_start_virt, g_mailbox_size, 0, g_mailbox_size); + g_mailbox_page[0] = (mailbox_page_t)g_shmem_start_virt; + for (i = 1; i < page_num; i++) + g_mailbox_page[i] = g_mailbox_page[i - 1] + g_page_offset; + + return g_mailbox_page; +} + +void mailbox_free_pages(mailbox_page_t *pages, int order) +{ + if (!pages || pages != g_mailbox_page) + return; + + (void)order; + kfree(pages); + g_mailbox_page = NULL; +} + +uintptr_t mailbox_page_address(mailbox_page_t *page) +{ + if (!page) + return 0; + + return (uintptr_t)*page; +} + +uintptr_t mailbox_virt_to_phys(uintptr_t addr) +{ + if (addr < g_shmem_start_virt || addr > g_shmem_start_virt + g_mailbox_size) + return 0; + + return g_mailbox_paddr + (addr - g_shmem_start_virt); +} + +mailbox_page_t *mailbox_virt_to_page(uint64_t ptr) +{ + if (ptr < g_shmem_start_virt || ptr > g_shmem_start_virt + g_mailbox_size) + return 0; + + return &g_mailbox_page[(ptr - g_shmem_start_virt) / g_page_offset]; +} + +uint64_t get_operation_vaddr(void) +{ + return g_shmem_start_virt + MAILBOX_POOL_SIZE; +} + +void free_operation(uint64_t op_vaddr) +{ + (void)op_vaddr; +} + +/* + * This function only for platform, CONFIG_LOG_POOL + * marco controls the log retention of soft reset feature. + * Enable COCNFIG_LOG_POOL macro, this function won't memset + * log pool memory, and the old log before reset can be retention. + */ +uint64_t get_log_mem_vaddr(void) +{ + uint64_t log_vaddr = (uint64_t)(uintptr_t)ioremap_cache(g_log_mem_paddr, g_log_mem_size); + if (log_vaddr == 0) { + tloge("ioremap for log buffer failed\n"); + return 0; + } +#ifndef CONFIG_LOG_POOL + (void)memset_s((void *)(uintptr_t)log_vaddr, g_log_mem_size, 0, g_log_mem_size); +#endif + + return log_vaddr; +} + +uint64_t get_log_mem_paddr(uint64_t log_vaddr) +{ + (void)log_vaddr; + return g_log_mem_paddr; +} + +uint64_t get_log_mem_size(void) +{ + return g_log_mem_size; +} + +void free_log_mem(uint64_t log_vaddr) +{ + iounmap((void __iomem*)(uintptr_t)log_vaddr); +} + +uint64_t get_cmd_mem_vaddr(void) +{ + uint64_t cmd_vaddr = (uint64_t)(uintptr_t)ioremap_cache(g_cmd_mem_paddr, g_cmd_mem_size); + if (cmd_vaddr == 0) { + tloge("io remap for cmd buffer failed\n"); + return 0; + } + (void)memset_s((void *)(uintptr_t)cmd_vaddr, g_cmd_mem_size, 0, g_cmd_mem_size); + return cmd_vaddr; +} + +uint64_t get_cmd_mem_paddr(uint64_t cmd_vaddr) +{ + (void)cmd_vaddr; + return g_cmd_mem_paddr; +} + +void free_cmd_mem(uint64_t cmd_vaddr) +{ + iounmap((void __iomem*)(uintptr_t)cmd_vaddr); +} + +uint64_t get_spi_mem_vaddr(void) +{ + uint64_t spi_vaddr = (uint64_t)(uintptr_t)ioremap_cache(g_spi_mem_paddr, g_spi_mem_size); + if (spi_vaddr == 0) { + tloge("io remap for spi buffer failed\n"); + return 0; + } + (void)memset_s((void *)(uintptr_t)spi_vaddr, g_spi_mem_size, 0, g_spi_mem_size); + return spi_vaddr; +} + +uint64_t get_spi_mem_paddr(uintptr_t spi_vaddr) +{ + (void)spi_vaddr; + return g_spi_mem_paddr; +} + +void free_spi_mem(uint64_t spi_vaddr) +{ + iounmap((void __iomem*)(uintptr_t)spi_vaddr); +} + +#else + +int load_tz_shared_mem(struct device_node *np) +{ + (void)np; + return 0; +} + +mailbox_page_t *mailbox_alloc_pages(int order) +{ + return koadpt_alloc_pages(GFP_KERNEL, order); +} + +void mailbox_free_pages(mailbox_page_t *pages, int order) +{ + if (!pages) + return; + + __free_pages(pages, order); +} + +uintptr_t mailbox_page_address(mailbox_page_t *page) +{ + if (!page) + return 0; + + return (uintptr_t)page_address(page); +} + +uintptr_t mailbox_virt_to_phys(uintptr_t addr) +{ + if (!addr) + return 0; + + return virt_to_phys((void *)addr); +} + +mailbox_page_t *mailbox_virt_to_page(uint64_t ptr) +{ + if (!ptr) + return NULL; + + return virt_to_page(ptr); +} + +uint64_t get_operation_vaddr(void) +{ + return (uint64_t)kzalloc(sizeof(struct tc_ns_operation), GFP_KERNEL); +} + +void free_operation(uint64_t op_vaddr) +{ + if (!op_vaddr) + return; + + kfree((void *)op_vaddr); +} + +uint64_t get_log_mem_vaddr(void) +{ + return __get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(PAGES_LOG_MEM_LEN)); +} + +uint64_t get_log_mem_paddr(uint64_t log_vaddr) +{ + if (!log_vaddr) + return 0; + + return virt_to_phys((void *)(uintptr_t)log_vaddr); +} + +uint64_t get_log_mem_size(void) +{ + return 0; +} + +void free_log_mem(uint64_t log_vaddr) +{ + if (!log_vaddr) + return; + + free_pages(log_vaddr, get_order(PAGES_LOG_MEM_LEN)); +} + +#define PAGES_BIG_SESSION_CMD_LEN 6 +uint64_t get_cmd_mem_vaddr(void) +{ +#ifdef CONFIG_BIG_SESSION + /* we should map at least 64 pages for 1000 sessions, 2^6 > 40 */ + return (uint64_t)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PAGES_BIG_SESSION_CMD_LEN); +#else + return (uint64_t)__get_free_page(GFP_KERNEL | __GFP_ZERO); +#endif +} + +uint64_t get_cmd_mem_paddr(uint64_t cmd_vaddr) +{ + if (!cmd_vaddr) + return 0; + + return virt_to_phys((void *)(uintptr_t)cmd_vaddr); +} + +void free_cmd_mem(uint64_t cmd_vaddr) +{ + if (!cmd_vaddr) + return; + +#ifdef CONFIG_BIG_SESSION + free_pages(cmd_vaddr, PAGES_BIG_SESSION_CMD_LEN); +#else + free_page(cmd_vaddr); +#endif +} + +uint64_t get_spi_mem_vaddr(void) +{ +#ifdef CONFIG_BIG_SESSION + /* we should map at least 3 pages for 100 sessions, 2^2 > 3 */ + return (uint64_t)__get_free_pages(GFP_KERNEL | __GFP_ZERO, CONFIG_NOTIFY_PAGE_ORDER); +#else + return (uint64_t)__get_free_page(GFP_KERNEL | __GFP_ZERO); +#endif +} + +uint64_t get_spi_mem_paddr(uintptr_t spi_vaddr) +{ + if (spi_vaddr == 0) + return 0; + + return virt_to_phys((void *)spi_vaddr); +} + +void free_spi_mem(uint64_t spi_vaddr) +{ + if (!spi_vaddr) + return; + +#ifdef CONFIG_BIG_SESSION + free_pages(spi_vaddr, CONFIG_NOTIFY_PAGE_ORDER); +#else + free_page(spi_vaddr); +#endif +} +#endif diff --git a/core/shared_mem.h b/core/shared_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..a0d4176b4da1221acd8acff8be7bcb83ecf27e46 --- /dev/null +++ b/core/shared_mem.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef SHARED_MEM_H +#define SHARED_MEM_H + +#include +#include + +#ifdef CONFIG_512K_LOG_PAGES_MEM +#define PAGES_LOG_MEM_LEN (512 * SZ_1K) /* mem size: 512 k */ +#else +#define PAGES_LOG_MEM_LEN (256 * SZ_1K) /* mem size: 256 k */ +#endif + +#ifndef CONFIG_SHARED_MEM_RESERVED +typedef struct page mailbox_page_t; +#else +typedef uintptr_t mailbox_page_t; +#endif + +int load_tz_shared_mem(struct device_node *np); + +mailbox_page_t *mailbox_alloc_pages(int order); +void mailbox_free_pages(mailbox_page_t *pages, int order); +uintptr_t mailbox_page_address(mailbox_page_t *page); +mailbox_page_t *mailbox_virt_to_page(uint64_t ptr); +uint64_t get_operation_vaddr(void); +void free_operation(uint64_t op_vaddr); + +uint64_t get_log_mem_vaddr(void); +uint64_t get_log_mem_paddr(uint64_t log_vaddr); +uint64_t get_log_mem_size(void); +void free_log_mem(uint64_t log_vaddr); + +uint64_t get_cmd_mem_vaddr(void); +uint64_t get_cmd_mem_paddr(uint64_t cmd_vaddr); +void free_cmd_mem(uint64_t cmd_vaddr); + +uint64_t get_spi_mem_vaddr(void); +uint64_t get_spi_mem_paddr(uintptr_t spi_vaddr); +void free_spi_mem(uint64_t spi_vaddr); +#endif diff --git a/core/smc_hook.c b/core/smc_hook.c new file mode 100644 index 0000000000000000000000000000000000000000..60d19449856134bf60f1e9a7cd22a98847f8006b --- /dev/null +++ b/core/smc_hook.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +static struct smc_hooks_t { + void (*smc_pre_hook)(void *); + void (*smc_post_hook)(void *); +} g_smc_hooks; + +/* + * we provide a hook function here, + * the specific implementation is implemented by the product itself + */ +void register_smc_hook(void (*pre_hook)(void *), void (*post_hook)(void *)) +{ + g_smc_hooks.smc_pre_hook = pre_hook; + g_smc_hooks.smc_post_hook = post_hook; +} +EXPORT_SYMBOL(register_smc_hook); + +void call_smc_pre_hook(unsigned int cmd_id) +{ + if (g_smc_hooks.smc_pre_hook != NULL) + g_smc_hooks.smc_pre_hook((void *)&cmd_id); +} + +void call_smc_post_hook(unsigned int cmd_id) +{ + if (g_smc_hooks.smc_post_hook != NULL) + g_smc_hooks.smc_post_hook((void *)&cmd_id); +} diff --git a/core/smc_hook.h b/core/smc_hook.h new file mode 100644 index 0000000000000000000000000000000000000000..5b1c00cdc5b1d97215251fa9e910901757ddb5ef --- /dev/null +++ b/core/smc_hook.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef SMC_HOOK_H +#define SMC_HOOK_H + +void call_smc_pre_hook(unsigned int cmd_id); +void call_smc_post_hook(unsigned int cmd_id); + +#endif diff --git a/core/smc_smp.c b/core/smc_smp.c index 1ed37609c6b2b18c8f70abb893650e19f40536e3..a7a2feacc3d46da8a2b10d1981692ec20d3429ec 100644 --- a/core/smc_smp.c +++ b/core/smc_smp.c @@ -62,10 +62,13 @@ #include "tlogger.h" #include "ko_adapt.h" #include "log_cfg_api.h" -#include "tz_kthread_affinity.h" #include "tee_compat_check.h" -#include "tee_trace_event.h" #include "secs_power_ctrl.h" +#include "shared_mem.h" +#include "internal_functions.h" +#ifdef CONFIG_SMC_HOOK +#include "smc_hook.h" +#endif #define PREEMPT_COUNT 10000 #define HZ_COUNT 10 @@ -96,7 +99,7 @@ #define MAX_SIQ_NUM 4 /* Current state of the system */ -static uint8_t g_sys_crash; +static bool g_sys_crash; struct smc_in_params { unsigned long x0; @@ -136,7 +139,7 @@ struct cmd_reuse_info { enum cmd_reuse cmd_usage; }; -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) static struct cpumask g_cpu_mask; static int g_mask_flag = 0; #endif @@ -198,9 +201,6 @@ union crash_inf { } crash_msg; }; -static const char *g_hungtask_monitor_list[] = { -}; - #define compile_time_assert(cond, msg) typedef char g_assert_##msg[(cond) ? 1 : -1] #ifndef CONFIG_BIG_SESSION @@ -214,8 +214,8 @@ static void acquire_smc_buf_lock(smc_buf_lock_t *lock) preempt_disable(); do - ret = cmpxchg(lock, 0, 1); - while (ret); + ret = (int)cmpxchg(lock, 0, 1); + while (ret != 0); } static inline void release_smc_buf_lock(smc_buf_lock_t *lock) @@ -226,11 +226,11 @@ static inline void release_smc_buf_lock(smc_buf_lock_t *lock) static void occupy_setbit_smc_in_doing_entry(int32_t i, int32_t *idx) { - g_cmd_data->in[i].event_nr = i; + g_cmd_data->in[i].event_nr = (unsigned int)i; isb(); wmb(); - set_bit(i, (unsigned long *)g_cmd_data->in_bitmap); - set_bit(i, (unsigned long *)g_cmd_data->doing_bitmap); + set_bit((unsigned int)i, (unsigned long *)g_cmd_data->in_bitmap); + set_bit((unsigned int)i, (unsigned long *)g_cmd_data->doing_bitmap); *idx = i; } @@ -259,7 +259,7 @@ static int occupy_free_smc_in_entry(const struct tc_ns_smc_cmd *cmd) get_smc_retry: acquire_smc_buf_lock(&g_cmd_data->smc_lock); for (i = 0; i < MAX_SMC_CMD; i++) { - if (test_bit(i, (unsigned long *)g_cmd_data->in_bitmap)) + if (test_bit(i, (unsigned long *)g_cmd_data->in_bitmap) != 0) continue; if (memcpy_s(&g_cmd_data->in[i], sizeof(g_cmd_data->in[i]), cmd, sizeof(*cmd)) != EOK) { @@ -284,7 +284,7 @@ get_smc_retry: acquire_smc_buf_lock(&g_cmd_data->smc_lock); isb(); wmb(); - clear_bit(idx, (unsigned long *)g_cmd_data->doing_bitmap); + clear_bit((uint32_t)idx, (unsigned long *)g_cmd_data->doing_bitmap); release_smc_buf_lock(&g_cmd_data->smc_lock); return idx; } @@ -294,21 +294,19 @@ static int reuse_smc_in_entry(uint32_t idx) int rc = 0; acquire_smc_buf_lock(&g_cmd_data->smc_lock); - if (!(test_bit(idx, (unsigned long *)g_cmd_data->in_bitmap) && - test_bit(idx, (unsigned long *)g_cmd_data->doing_bitmap))) { + if (!(test_bit((int32_t)idx, (unsigned long *)g_cmd_data->in_bitmap) != 0 && + test_bit((int32_t)idx, (unsigned long *)g_cmd_data->doing_bitmap) != 0)) { tloge("invalid cmd to reuse\n"); rc = -1; goto out; } if (memcpy_s(&g_cmd_data->in[idx], sizeof(g_cmd_data->in[idx]), - &g_cmd_data->out[idx], sizeof(g_cmd_data->out[idx]))) { + &g_cmd_data->out[idx], sizeof(g_cmd_data->out[idx])) != EOK) { tloge("memcpy failed,%s line:%d", __func__, __LINE__); rc = -1; goto out; } - release_smc_buf_lock(&g_cmd_data->smc_lock); - acquire_smc_buf_lock(&g_cmd_data->smc_lock); isb(); wmb(); clear_bit(idx, (unsigned long *)g_cmd_data->doing_bitmap); @@ -321,14 +319,14 @@ static int copy_smc_out_entry(uint32_t idx, struct tc_ns_smc_cmd *copy, enum cmd_reuse *usage) { acquire_smc_buf_lock(&g_cmd_data->smc_lock); - if (!test_bit(idx, (unsigned long *)g_cmd_data->out_bitmap)) { + if (test_bit((int)idx, (unsigned long *)g_cmd_data->out_bitmap) == 0) { tloge("cmd out %u is not ready\n", idx); release_smc_buf_lock(&g_cmd_data->smc_lock); show_cmd_bitmap(); return -ENOENT; } if (memcpy_s(copy, sizeof(*copy), &g_cmd_data->out[idx], - sizeof(g_cmd_data->out[idx]))) { + sizeof(g_cmd_data->out[idx])) != EOK) { tloge("copy smc out failed\n"); release_smc_buf_lock(&g_cmd_data->smc_lock); return -EFAULT; @@ -336,8 +334,8 @@ static int copy_smc_out_entry(uint32_t idx, struct tc_ns_smc_cmd *copy, isb(); wmb(); - if (g_cmd_data->out[idx].ret_val == TEEC_PENDING2 || - g_cmd_data->out[idx].ret_val == TEEC_PENDING) { + if (g_cmd_data->out[idx].ret_val == (int)TEEC_PENDING2 || + g_cmd_data->out[idx].ret_val == (int)TEEC_PENDING) { *usage = RESEND; } else { clear_bit(idx, (unsigned long *)g_cmd_data->in_bitmap); @@ -371,12 +369,19 @@ static bool is_cmd_working_done(uint32_t idx) bool ret = false; acquire_smc_buf_lock(&g_cmd_data->smc_lock); - if (test_bit(idx, (unsigned long *)g_cmd_data->out_bitmap)) + if (test_bit((int)idx, (unsigned long *)g_cmd_data->out_bitmap) != 0) ret = true; release_smc_buf_lock(&g_cmd_data->smc_lock); return ret; } +void occupy_clean_cmd_buf(void) +{ + acquire_smc_buf_lock(&g_cmd_data->smc_lock); + memset_s(g_cmd_data, sizeof(struct tc_ns_smc_queue), 0, sizeof(struct tc_ns_smc_queue)); + release_smc_buf_lock(&g_cmd_data->smc_lock); +} + static void show_in_bitmap(int *cmd_in, uint32_t len) { uint32_t idx; @@ -387,9 +392,9 @@ static void show_in_bitmap(int *cmd_in, uint32_t len) return; for (idx = 0; idx < MAX_SMC_CMD; idx++) { - if (test_bit(idx, (unsigned long *)g_cmd_data->in_bitmap)) { + if (test_bit((int32_t)idx, (unsigned long *)g_cmd_data->in_bitmap) != 0) { bitmap[idx] = '1'; - cmd_in[in++] = idx; + cmd_in[in++] = (int)idx; } else { bitmap[idx] = '0'; } @@ -408,9 +413,9 @@ static void show_out_bitmap(int *cmd_out, uint32_t len) return; for (idx = 0; idx < MAX_SMC_CMD; idx++) { - if (test_bit(idx, (unsigned long *)g_cmd_data->out_bitmap)) { + if (test_bit((int32_t)idx, (unsigned long *)g_cmd_data->out_bitmap) != 0) { bitmap[idx] = '1'; - cmd_out[out++] = idx; + cmd_out[out++] = (int)idx; } else { bitmap[idx] = '0'; } @@ -427,7 +432,7 @@ static void show_doing_bitmap(void) if (!g_cmd_data) return; for (idx = 0; idx < MAX_SMC_CMD; idx++) { - if (test_bit(idx, (unsigned long *)g_cmd_data->doing_bitmap)) + if (test_bit((int)idx, (unsigned long *)g_cmd_data->doing_bitmap) != 0) bitmap[idx] = '1'; else bitmap[idx] = '0'; @@ -436,7 +441,7 @@ static void show_doing_bitmap(void) tloge("doing bitmap: %s\n", bitmap); } -static void show_single_cmd_info(int *cmd, uint32_t len) +static void show_single_cmd_info(const int *cmd, uint32_t len) { uint32_t idx; @@ -475,8 +480,8 @@ void show_cmd_bitmap(void) return; } - if (memset_s(cmd_in, sizeof(int)* MAX_SMC_CMD, MAX_CHAR, sizeof(int)* MAX_SMC_CMD) || - memset_s(cmd_out, sizeof(int)* MAX_SMC_CMD, MAX_CHAR, sizeof(int)* MAX_SMC_CMD)) { + if (memset_s(cmd_in, sizeof(int)* MAX_SMC_CMD, MAX_CHAR, sizeof(int)* MAX_SMC_CMD) != 0 || + memset_s(cmd_out, sizeof(int)* MAX_SMC_CMD, MAX_CHAR, sizeof(int)* MAX_SMC_CMD) != 0) { tloge("memset failed\n"); goto error; } @@ -619,6 +624,7 @@ static bool match_ta_affinity(struct pending_entry *pe) #else static inline bool match_ta_affinity(struct pending_entry *pe) { + (void)pe; return false; } #endif @@ -638,8 +644,8 @@ bool sigkill_pending(struct task_struct *tsk) return false; } - flag = sigismember(&tsk->pending.signal, SIGKILL) || - sigismember(&tsk->pending.signal, SIGUSR1); + flag = (sigismember(&tsk->pending.signal, SIGKILL) != 0) || + (sigismember(&tsk->pending.signal, SIGUSR1) != 0); if (tsk->signal) return flag || sigismember(&tsk->signal->shared_pending.signal, @@ -647,12 +653,12 @@ bool sigkill_pending(struct task_struct *tsk) return flag; } -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) static void set_cpu_strategy(struct cpumask *old_mask) { unsigned int i; - if (!g_mask_flag) { + if (g_mask_flag == 0) { cpumask_clear(&g_cpu_mask); for (i = 0; i < CONFIG_CPU_AFF_NR; i++) cpumask_set_cpu(i, &g_cpu_mask); @@ -663,7 +669,7 @@ static void set_cpu_strategy(struct cpumask *old_mask) } #endif -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) static void restore_cpu(struct cpumask *old_mask) { /* current equal old means no set cpu affinity, no need to restore */ @@ -757,16 +763,60 @@ static void send_asm_smc_cmd(struct smc_in_params *in_param, } #endif +#ifdef CONFIG_TEE_REBOOT +int send_smc_cmd_rebooting(uint32_t cmd_id, phys_addr_t cmd_addr, uint32_t cmd_type, + const struct tc_ns_smc_cmd *in_cmd) +{ + struct tc_ns_smc_cmd cmd = { {0}, 0 }; + struct smc_in_params in_param = { cmd_id, cmd_addr, cmd_type, cmd_addr >> ADDR_TRANS_NUM, TEE_ERROR_IS_DEAD}; + struct smc_out_params out_param = {0}; + + if (in_cmd != NULL) { + if (memcpy_s(&cmd, sizeof(cmd), in_cmd, sizeof(*in_cmd)) != EOK) { + tloge("memcpy in cmd failed\n"); + return -EFAULT; + } + + if (occupy_free_smc_in_entry(&cmd) == -1) { + tloge("there's no more smc entry\n"); + return -ENOMEM; + } + } + +retry: + isb(); + wmb(); + send_asm_smc_cmd(&in_param, &out_param); + isb(); + wmb(); + + if (out_param.exit_reason == SMC_EXIT_PREEMPTED) + goto retry; + + return out_param.exit_reason; +} +#else +int send_smc_cmd_rebooting(uint32_t cmd_id, phys_addr_t cmd_addr, uint32_t cmd_type, + const struct tc_ns_smc_cmd *in_cmd) +{ + (void)cmd_id; + (void)cmd_addr; + (void)cmd_type; + (void)in_cmd; + return 0; +} +#endif + static noinline int smp_smc_send(uint32_t cmd, unsigned long ops, unsigned long ca, struct smc_cmd_ret *secret, bool need_kill) { struct smc_in_params in_param = { cmd, ops, ca, 0, 0 }; struct smc_out_params out_param = {0}; -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) struct cpumask old_mask; #endif -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) set_cpu_strategy(&old_mask); #endif retry: @@ -805,17 +855,17 @@ retry: goto retry; } } -#if CONFIG_CPU_AFF_NR +#if (CONFIG_CPU_AFF_NR != 0) restore_cpu(&old_mask); #endif - return out_param.ret; + return (int)out_param.ret; } #ifndef CONFIG_ARCH32 static uint64_t send_smc_cmd(uint32_t cmd, phys_addr_t cmd_addr, uint32_t cmd_type, uint8_t wait) { - struct smc_in_params in_param = { cmd, cmd_addr, cmd_type, cmd_addr >> ADDR_TRANS_NUM }; + struct smc_in_params in_param = { cmd, cmd_addr, cmd_type, cmd_addr >> ADDR_TRANS_NUM, 0 }; uint64_t ret = 0; do { @@ -834,7 +884,7 @@ static uint64_t send_smc_cmd(uint32_t cmd, phys_addr_t cmd_addr, [a4] "+r"(in_param.x0): [re0] "r"(&ret): "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7"); - } while (ret == TSP_REQUEST && wait); + } while (ret == TSP_REQUEST && wait != 0); isb(); wmb(); @@ -897,10 +947,10 @@ static void siq_dump(phys_addr_t mode, uint32_t siq_mode) tz_log_write(); } else if (siq_mode == SIQ_DUMP_SHELL) { #ifdef CONFIG_TEE_LOG_DUMP_PATH - (void)tlogger_store_msg(CONFIG_TEE_LOG_DUMP_PATH, - sizeof(CONFIG_TEE_LOG_DUMP_PATH)); + (void)tlogger_store_msg(CONFIG_TEE_LOG_DUMP_PATH, + sizeof(CONFIG_TEE_LOG_DUMP_PATH)); #else - tz_log_write(); + tz_log_write(); #endif } do_cmd_need_archivelog(); @@ -911,7 +961,7 @@ static uint32_t get_free_siq_index(void) uint32_t i; for (i = 0; i < MAX_SIQ_NUM; i++) { - if (g_siq_queue[i] == 0) + if (g_siq_queue[i] == 0) return i; } @@ -923,25 +973,30 @@ static uint32_t get_undo_siq_index(void) uint32_t i; for (i = 0; i < MAX_SIQ_NUM; i++) { - if (g_siq_queue[i] != 0) + if (g_siq_queue[i] != 0) return i; } return MAX_SIQ_NUM; } +#define RUN_SIQ_THREAD 1 +#define STOP_SIQ_THREAD 2 static int siq_thread_fn(void *arg) { int ret; uint32_t i; + (void)arg; - while (1) { - ret = wait_event_interruptible(siq_th_wait, + while (true) { + ret = (int)wait_event_interruptible(siq_th_wait, atomic_read(&g_siq_th_run)); - if (ret) { + if (ret != 0) { tloge("wait event interruptible failed!\n"); return -EINTR; } + if (atomic_read(&g_siq_th_run) == STOP_SIQ_THREAD) + return 0; mutex_lock(&g_siq_lock); do { @@ -950,7 +1005,7 @@ static int siq_thread_fn(void *arg) break; siq_dump((phys_addr_t)(1), g_siq_queue[i]); g_siq_queue[i] = 0; - }while(1); + } while (true); atomic_set(&g_siq_th_run, 0); mutex_unlock(&g_siq_lock); } @@ -995,17 +1050,19 @@ static void upload_audit_event(unsigned int eventindex) } #endif -static void cmd_result_check(struct tc_ns_smc_cmd *cmd) +static void cmd_result_check(const struct tc_ns_smc_cmd *cmd) { - if (cmd->ret_val == TEEC_PENDING || cmd->ret_val == TEEC_PENDING2) + if (cmd->ret_val == (int)TEEC_PENDING || cmd->ret_val == (int)TEEC_PENDING2) tlogd("wakeup command %u\n", cmd->event_nr); - if (cmd->ret_val == TEE_ERROR_TAGET_DEAD) { + if (cmd->ret_val == (int)TEE_ERROR_TAGET_DEAD) { tloge("error smc call: ret = %x and cmd.err_origin=%x\n", cmd->ret_val, cmd->err_origin); cmd_monitor_ta_crash(TYPE_CRASH_TA); ta_crash_report_log(); - } else if (cmd->ret_val == TEE_ERROR_AUDIT_FAIL) { + } else if (cmd->ret_val == (int)TEEC_ERROR_TUI_NOT_AVAILABLE) { + do_ns_tui_release(); + } else if (cmd->ret_val == (int)TEE_ERROR_AUDIT_FAIL) { tloge("error smc call: ret = %x and err-origin=%x\n", cmd->ret_val, cmd->err_origin); #ifdef CONFIG_TEE_AUDIT @@ -1022,13 +1079,13 @@ static void set_shadow_smc_param(struct smc_in_params *in_params, if (out_params->exit_reason == SMC_EXIT_PREEMPTED) { in_params->x0 = TSP_REQUEST; in_params->x1 = SMC_OPS_SCHEDTO; - in_params->x2 = current->pid; + in_params->x2 = (unsigned long)current->pid; in_params->x3 = out_params->ta; in_params->x4 = out_params->target; } else if (out_params->exit_reason == SMC_EXIT_NORMAL) { in_params->x0 = TSP_REQUEST; in_params->x1 = SMC_OPS_SCHEDTO; - in_params->x2 = current->pid; + in_params->x2 = (unsigned long)current->pid; in_params->x3 = 0; in_params->x4 = 0; if (*n_idled > IDLED_COUNT) { @@ -1043,7 +1100,7 @@ static void shadow_wo_pm(const void *arg, struct smc_out_params *out_params, int *n_idled) { struct smc_in_params in_params = { - TSP_REQUEST, SMC_OPS_START_SHADOW, current->pid, 0, *(u64 *)arg + TSP_REQUEST, SMC_OPS_START_SHADOW, current->pid, 0, *(const u64 *)arg }; set_shadow_smc_param(&in_params, out_params, n_idled); @@ -1084,7 +1141,7 @@ static void shadow_wo_pm(const void *arg, struct smc_out_params *out_params, int *n_idled) { struct smc_in_params in_params = { - TSP_REQUEST, SMC_OPS_START_SHADOW, current->pid, 0, *(u32 *)arg + TSP_REQUEST, SMC_OPS_START_SHADOW, current->pid, 0, *(const u32 *)arg }; set_shadow_smc_param(&in_params, out_params, n_idled); @@ -1146,7 +1203,7 @@ static int proc_shadow_thread_normal_exit(struct pending_entry *pe, long long timeout; int rc; - if (power_down_cc()) { + if (power_down_cc() != 0) { tloge("power down cc failed\n"); *ret_val = -1; return CLEAN_WITHOUT_PM; @@ -1154,9 +1211,9 @@ static int proc_shadow_thread_normal_exit(struct pending_entry *pe, *n_preempted = 0; timeout = HZ * (long)(HZ_COUNT + ((uint8_t)current->pid & LOW_BYTE)); - rc = wait_event_freezable_timeout(pe->wq, + rc = (int)wait_event_freezable_timeout(pe->wq, atomic_read(&pe->run), (long)timeout); - if (!rc) + if (rc == 0) (*n_idled)++; if (atomic_read(&pe->run) == SHADOW_EXIT_RUN) { tlogd("shadow thread work quit, be killed\n"); @@ -1175,17 +1232,17 @@ static bool check_shadow_crash(uint64_t crash_reason, int *ret_val) return false; tloge("TEEOS shadow has crashed!\n"); - if (power_down_cc()) + if (power_down_cc() != 0) tloge("power down cc failed\n"); - g_sys_crash = 1; + g_sys_crash = true; cmd_monitor_ta_crash(TYPE_CRASH_TEE); report_log_system_error(); *ret_val = -1; return true; } -static void show_other_exit_reason(struct smc_out_params *params) +static void show_other_exit_reason(const struct smc_out_params *params) { if (params->exit_reason == SMC_EXIT_SHADOW) { tlogd("probe shadow thread non exit, just quit\n"); @@ -1214,7 +1271,7 @@ static int shadow_thread_fn(void *arg) wmb(); retry: - if (power_on_cc()) { + if (power_on_cc() != 0) { ret = -EINVAL; tloge("power on cc failed\n"); goto clean_wo_pm; @@ -1241,7 +1298,7 @@ retry_wo_pm: show_other_exit_reason(¶ms); } - if (power_down_cc()) { + if (power_down_cc() != 0) { tloge("power down cc failed\n"); ret = -1; } @@ -1317,7 +1374,7 @@ int smc_wakeup_broadcast(void) int smc_wakeup_ca(pid_t ca) { - tee_trace_add_event(SPI_WAKEUP, ca); + tee_trace_add_event(SPI_WAKEUP, (uint64_t)ca); return proc_smc_wakeup_ca(ca, 1); } @@ -1329,16 +1386,19 @@ int smc_shadow_exit(pid_t ca) void fiq_shadow_work_func(uint64_t target) { struct smc_cmd_ret secret = { SMC_EXIT_MAX, 0, target }; - + tee_trace_add_event(INTERRUPT_HANDLE_SPI_REE_SCHEDULED, target); secs_suspend_status(target); - if (power_on_cc()) { + if (power_on_cc() != 0) { tloge("power on cc failed\n"); return; } + + livepatch_down_read_sem(); smp_smc_send(TSP_REQUEST, (unsigned long)SMC_OPS_START_FIQSHD, (unsigned long)(uint32_t)(current->pid), &secret, false); + livepatch_up_read_sem(); - if (power_down_cc()) + if (power_down_cc() != 0) tloge("power down cc failed\n"); return; @@ -1396,9 +1456,9 @@ static int smc_ops_normal(struct cmd_reuse_info *info, return 0; if (info->cmd_usage == RESEND) { - if (reuse_smc_in_entry(info->cmd_index)) { + if (reuse_smc_in_entry((uint32_t)info->cmd_index) != 0) { tloge("reuse smc entry failed\n"); - release_smc_entry(info->cmd_index); + release_smc_entry((uint32_t)info->cmd_index); return -ENOMEM; } } else { @@ -1427,6 +1487,7 @@ static int smc_ops_normal(struct cmd_reuse_info *info, static int smp_smc_send_cmd_done(int cmd_index, struct tc_ns_smc_cmd *cmd, struct tc_ns_smc_cmd *in) { + (void)cmd_index; cmd_result_check(cmd); switch (cmd->ret_val) { case TEEC_PENDING2: { @@ -1434,7 +1495,7 @@ static int smp_smc_send_cmd_done(int cmd_index, struct tc_ns_smc_cmd *cmd, /* If the agent does not exist post * the answer right back to the TEE */ - if (agent_process_work(cmd, agent_id)) + if (agent_process_work(cmd, agent_id) != 0) tloge("agent process work failed\n"); return PENDING2_RETRY; } @@ -1442,7 +1503,7 @@ static int smp_smc_send_cmd_done(int cmd_index, struct tc_ns_smc_cmd *cmd, case TEEC_PENDING: /* just copy out, and let out to proceed */ default: - if (memcpy_s(in, sizeof(*in), cmd, sizeof(*cmd))) { + if (memcpy_s(in, sizeof(*in), cmd, sizeof(*cmd)) != EOK) { tloge("memcpy failed,%s line:%d", __func__, __LINE__); cmd->ret_val = -1; } @@ -1493,12 +1554,12 @@ static void print_crash_msg(union crash_inf *crash_info) char syms[SYM_NAME_LEN_MAX] = {0}; if (memcpy_s(syms, SYM_NAME_LEN_MAX, - crash_info->crash_msg.sym_name, SYM_NAME_LEN_1)) + crash_info->crash_msg.sym_name, SYM_NAME_LEN_1) != EOK) tloge("memcpy sym name failed!\n"); if (memcpy_s(syms + SYM_NAME_LEN_1, SYM_NAME_LEN_MAX - SYM_NAME_LEN_1, - crash_info->crash_msg.sym_name_append, SYM_NAME_LEN_2)) + crash_info->crash_msg.sym_name_append, SYM_NAME_LEN_2) != EOK) tloge("memcpy sym_name_append failed!\n"); tloge("====crash app:%s user_sym:%s + <0x%x/0x%x>\n", crash_app_name, syms, off, crash_info->crash_msg.size); @@ -1507,6 +1568,11 @@ static void print_crash_msg(union crash_inf *crash_info) } } +void clr_system_crash_flag(void) +{ + g_sys_crash = false; +} + static int smp_smc_send_process(struct tc_ns_smc_cmd *cmd, u64 ops, struct smc_cmd_ret *cmd_ret, int cmd_index) { @@ -1515,16 +1581,19 @@ static int smp_smc_send_process(struct tc_ns_smc_cmd *cmd, u64 ops, tlogd("smc send start cmd_id = %u, ca = %u\n", cmd->cmd_id, cmd->ca_pid); - if (power_on_cc()) { + if (power_on_cc() != 0) { tloge("power on cc failed\n"); cmd->ret_val = -1; return -1; } +#ifdef CONFIG_SMC_HOOK + call_smc_pre_hook(cmd->cmd_id); +#endif ret = smp_smc_send(TSP_REQUEST, (unsigned long)ops, (unsigned long)(uint32_t)(current->pid), cmd_ret, ops != SMC_OPS_ABORT_TASK); - if (power_down_cc()) { + if (power_down_cc() != 0) { tloge("power down cc failed\n"); cmd->ret_val = -1; return -1; @@ -1543,12 +1612,14 @@ static int smp_smc_send_process(struct tc_ns_smc_cmd *cmd, u64 ops, tloge("TEEOS has crashed!\n"); print_crash_msg(&crash_info); - g_sys_crash = 1; + g_sys_crash = true; cmd_monitor_ta_crash(TYPE_CRASH_TEE); + tee_wake_up_reboot(); +#ifndef CONFIG_TEE_REBOOT report_log_system_error(); - - cmd->ret_val = -1; +#endif + cmd->ret_val = TEE_ERROR_IS_DEAD; return -1; } @@ -1568,11 +1639,11 @@ static int init_for_smc_send(struct tc_ns_smc_cmd *in, return -ENOMEM; } - in->ca_pid = current->pid; + in->ca_pid = (unsigned int)current->pid; if (reuse) return 0; - if (memcpy_s(cmd, sizeof(*cmd), in, sizeof(*in))) { + if (memcpy_s(cmd, sizeof(*cmd), in, sizeof(*in)) != EOK) { tloge("memcpy in cmd failed\n"); release_pending_entry(*pe); return -EFAULT; @@ -1583,6 +1654,7 @@ static int init_for_smc_send(struct tc_ns_smc_cmd *in, static bool is_ca_killed(int cmd_index) { + (void)cmd_index; /* if CA has not been killed */ if (sigkill_pending(current)) { /* signal pending, send abort cmd */ @@ -1596,8 +1668,8 @@ static void clean_smc_resrc(struct cmd_reuse_info info, const struct tc_ns_smc_cmd *cmd, struct pending_entry *pe) { - if (info.cmd_usage != CLEAR && cmd->ret_val != TEEC_PENDING) - release_smc_entry(info.cmd_index); + if (info.cmd_usage != CLEAR && cmd->ret_val != (int)TEEC_PENDING) + release_smc_entry((uint32_t)info.cmd_index); release_pending_entry(pe); } @@ -1605,7 +1677,7 @@ static void clean_smc_resrc(struct cmd_reuse_info info, static int set_abort_cmd(int index) { acquire_smc_buf_lock(&g_cmd_data->smc_lock); - if (!test_bit(index, (unsigned long *)g_cmd_data->doing_bitmap)) { + if (test_bit(index, (unsigned long *)g_cmd_data->doing_bitmap) == 0) { release_smc_buf_lock(&g_cmd_data->smc_lock); tloge("can't abort an unprocess cmd\n"); return -1; @@ -1619,16 +1691,17 @@ static int set_abort_cmd(int index) g_cmd_data->in[index].login_data_phy = 0; g_cmd_data->in[index].login_data_h_addr = 0; - clear_bit(index, (unsigned long *)g_cmd_data->doing_bitmap); + clear_bit((unsigned int)index, (unsigned long *)g_cmd_data->doing_bitmap); release_smc_buf_lock(&g_cmd_data->smc_lock); tloge("set abort cmd success\n"); return 0; } -static enum smc_ops_exit process_abort_cmd(int index, struct pending_entry *pe) +static enum smc_ops_exit process_abort_cmd(int index, const struct pending_entry *pe) { - if (!set_abort_cmd(index)) + (void)pe; + if (set_abort_cmd(index) == 0) return SMC_OPS_ABORT_TASK; return SMC_OPS_SCHEDTO; @@ -1656,7 +1729,7 @@ static void init_timeout_step(uint32_t timeout, struct timeout_step_t *step) if (timeout > RESLEEP_TIMEOUT * MSEC_PER_SEC) timeout = RESLEEP_TIMEOUT * MSEC_PER_SEC; - timeout_in_jiffies = msecs_to_jiffies(timeout); + timeout_in_jiffies = (uint32_t)msecs_to_jiffies(timeout); /* * [timeout_in_jiffies-1, timeout_in_jiffies+2] jiffies @@ -1692,58 +1765,58 @@ enum smc_status_t { ST_RETRY, }; +static long wait_event_internal(struct pending_entry *pe, struct timeout_step_t *step) +{ + if (!current->mm) { + return wait_event_interruptible_timeout(pe->wq, atomic_read(&pe->run), + step->steps[step->cur]); + } else { + return wait_event_timeout(pe->wq, atomic_read(&pe->run), + step->steps[step->cur]); + } +} static enum pending_t proc_ta_pending(struct pending_entry *pe, struct timeout_step_t *step, uint64_t pending_args, uint32_t cmd_index, u64 *ops) { bool kernel_call = false; bool woke_up = false; - /* * if ->mm is NULL, it's a kernel thread and a kthread will never * receive a signal. */ - if (!current->mm) { + uint32_t timeout = (uint32_t)pending_args; + bool timer_no_irq = (pending_args >> 32) == 0 ? false : true; + uint32_t cur_timeout; + if (step->cur == INVALID_STEP_SIZE) + init_timeout_step(timeout, step); + if (!current->mm) kernel_call = true; - if (wait_event_interruptible(pe->wq, atomic_read(&pe->run))) - tloge("kernel CA is interrupted\n"); - } else { - uint32_t timeout = (uint32_t)pending_args; - bool timer_no_irq = (pending_args >> 32) == 0 ? false : true; - uint32_t cur_timeout; - - if (step->cur == INVALID_STEP_SIZE) - init_timeout_step(timeout, step); resleep: - cur_timeout = jiffies_to_msecs(step->steps[step->cur]); - - tee_trace_add_event(SMC_SLEEP, 0); - if (!wait_event_timeout(pe->wq, atomic_read(&pe->run), - step->steps[step->cur])) { - if (step->cur < (step->size - 1)) { - step->cur++; - /* - * As there may no timer irq in TEE, we need a chance to - * run timer's irq handler initiatively by SMC_OPS_SCHEDTO. - */ - if (timer_no_irq) { - *ops = SMC_OPS_SCHEDTO; - return PD_TIMEOUT; - } else { - goto resleep; - } - } - - if (is_ca_killed(cmd_index)) { - *ops = (u64)process_abort_cmd(cmd_index, pe); - return PD_WAKEUP; + cur_timeout = jiffies_to_msecs(step->steps[step->cur]); + tee_trace_add_event(SMC_SLEEP, 0); + if (wait_event_internal(pe, step) == 0) { + if (step->cur < (step->size - 1)) { + step->cur++; + /* + * As there may no timer irq in TEE, we need a chance to + * run timer's irq handler initiatively by SMC_OPS_SCHEDTO. + */ + if (timer_no_irq) { + *ops = SMC_OPS_SCHEDTO; + return PD_TIMEOUT; + } else { + goto resleep; } - } else { - woke_up = true; - tlogd("%s woke up\n", __func__); } + if (is_ca_killed(cmd_index)) { + *ops = (u64)process_abort_cmd(cmd_index, pe); + return PD_WAKEUP; + } + } else { + woke_up = true; + tlogd("%s woke up\n", __func__); } - atomic_set(&pe->run, 0); if (!is_cmd_working_done(cmd_index)) { *ops = SMC_OPS_SCHEDTO; @@ -1753,7 +1826,6 @@ resleep: show_cmd_bitmap(); } tlogd("cmd is done\n"); - return PD_DONE; } @@ -1779,7 +1851,7 @@ static enum smc_status_t proc_normal_exit(struct pending_entry *pe, u64 *ops, } pd_ret = proc_ta_pending(pe, timeout_step, - cmd_ret->ta, cmd_index, ops); + cmd_ret->ta, (uint32_t)cmd_index, ops); if (pd_ret == PD_DONE) return ST_DONE; @@ -1792,12 +1864,12 @@ static enum smc_status_t handle_cmd_working_done( struct tc_ns_smc_cmd *cmd, u64 *ops, struct tc_ns_smc_cmd *in, struct cmd_reuse_info *info) { - if (copy_smc_out_entry(info->cmd_index, cmd, &info->cmd_usage)) { + if (copy_smc_out_entry((uint32_t)info->cmd_index, cmd, &info->cmd_usage) != 0) { cmd->ret_val = TEEC_ERROR_GENERIC; return ST_DONE; } - if (smp_smc_send_cmd_done(info->cmd_index, cmd, in)) { + if (smp_smc_send_cmd_done(info->cmd_index, cmd, in) != 0) { *ops = SMC_OPS_NORMAL; /* cmd will be reused */ return ST_RETRY; } @@ -1813,22 +1885,26 @@ static int smp_smc_send_func(struct tc_ns_smc_cmd *in, bool reuse) struct pending_entry *pe = NULL; u64 ops; struct timeout_step_t timeout_step = - { {0, 0, 0, 0}, TO_STEP_SIZE, -1, false }; + {{0, 0, 0, 0}, TO_STEP_SIZE, -1, false}; - if (init_for_smc_send(in, &pe, &cmd, reuse)) + if (init_for_smc_send(in, &pe, &cmd, reuse) != 0) return TEEC_ERROR_GENERIC; if (reuse) { - info.saved_index = in->event_nr; - info.cmd_index = in->event_nr; + info.saved_index = (int)in->event_nr; + info.cmd_index = (int)in->event_nr; info.cmd_usage = RESEND; } ops = SMC_OPS_NORMAL; retry: +#ifdef CONFIG_TEE_REBOOT + if (is_tee_rebooting() && in->cmd_id == GLOBAL_CMD_ID_SET_SERVE_CMD) + return TEE_ERROR_IS_DEAD; +#endif set_timeout_step(&timeout_step); - if (smc_ops_normal(&info, &cmd, ops)) { + if (smc_ops_normal(&info, &cmd, ops) != 0) { release_pending_entry(pe); return TEEC_ERROR_GENERIC; } @@ -1836,7 +1912,7 @@ retry: if (smp_smc_send_process(&cmd, ops, &cmd_ret, info.cmd_index) == -1) goto clean; - if (!is_cmd_working_done(info.cmd_index)) { + if (!is_cmd_working_done((uint32_t)info.cmd_index)) { if (cmd_ret.exit == SMC_EXIT_NORMAL) { if (proc_normal_exit(pe, &ops, &timeout_step, &cmd_ret, info.cmd_index) == ST_RETRY) @@ -1860,6 +1936,7 @@ clean: static int smc_svc_thread_fn(void *arg) { + (void)arg; while (!kthread_should_stop()) { struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; int ret; @@ -1873,21 +1950,9 @@ static int smc_svc_thread_fn(void *arg) return 0; } -bool is_tee_hungtask(struct task_struct *task) +bool __attribute__((weak)) is_tee_hungtask(struct task_struct *task) { - uint32_t i; - uint32_t hungtask_num = sizeof(g_hungtask_monitor_list) / - sizeof(g_hungtask_monitor_list[0]); - - if (!task) - return false; - for (i = 0; i < hungtask_num; i++) { - if (!strcmp(task->comm, g_hungtask_monitor_list[i])) { - tloge("tee hungtask detected:the hungtask is %s\n", - task->comm); - return true; - } - } + (void)task; return false; } @@ -1896,9 +1961,9 @@ void wakeup_tc_siq(uint32_t siq_mode) { uint32_t i; - if (siq_mode == 0) + if (siq_mode == 0) return; - + mutex_lock(&g_siq_lock); i = get_free_siq_index(); if (i >= MAX_SIQ_NUM) { @@ -1907,7 +1972,7 @@ void wakeup_tc_siq(uint32_t siq_mode) return; } g_siq_queue[i] = siq_mode; - atomic_set(&g_siq_th_run, 1); + atomic_set(&g_siq_th_run, RUN_SIQ_THREAD); mutex_unlock(&g_siq_lock); wake_up_interruptible(&siq_th_wait); } @@ -1923,8 +1988,9 @@ static int proc_tc_ns_smc(struct tc_ns_smc_cmd *cmd, bool reuse) if (g_sys_crash) { tloge("ERROR: sys crash happened!!!\n"); - return TEEC_ERROR_GENERIC; + return TEE_ERROR_IS_DEAD; } + if (!cmd) { tloge("invalid cmd\n"); return TEEC_ERROR_GENERIC; @@ -1954,13 +2020,18 @@ static void smc_work_no_wait(uint32_t type) (void)raw_smc_send(TSP_REQUEST, g_cmd_phys, type, true); } +void send_smc_reset_cmd_buffer(void) +{ + send_smc_cmd_rebooting(TSP_REQUEST, g_cmd_phys, TC_NS_CMD_TYPE_SECURE_CONFIG, NULL); +} + static void smc_work_set_cmd_buffer(struct work_struct *work) { (void)work; smc_work_no_wait(TC_NS_CMD_TYPE_SECURE_CONFIG); } -static void smc_set_cmd_buffer(void) +void smc_set_cmd_buffer(void) { struct work_struct work; @@ -1973,19 +2044,11 @@ static void smc_set_cmd_buffer(void) static int alloc_cmd_buffer(void) { -#ifdef CONFIG_BIG_SESSION - /* we should map at least 64 pages for 1000 sessions, 2^6 > 40 */ - g_cmd_data = (struct tc_ns_smc_queue *)(uintptr_t)__get_free_pages( - GFP_KERNEL | __GFP_ZERO, 6); -#else - g_cmd_data = (struct tc_ns_smc_queue *)(uintptr_t)__get_free_page( - GFP_KERNEL | __GFP_ZERO); -#endif + g_cmd_data = (struct tc_ns_smc_queue *)(uintptr_t)get_cmd_mem_vaddr(); if (!g_cmd_data) return -ENOMEM; - g_cmd_phys = virt_to_phys(g_cmd_data); - + g_cmd_phys = get_cmd_mem_paddr((uint64_t)(uintptr_t)g_cmd_data); return 0; } @@ -2032,12 +2095,12 @@ static int parse_params_from_tee(void) buffer = (void *)(g_cmd_data->in); ret = check_teeos_compat_level((uint32_t *)buffer, COMPAT_LEVEL_BUF_LEN); - if (ret) { + if (ret != 0) { tloge("check teeos compatibility failed\n"); return ret; } if (memset_s(buffer, sizeof(g_cmd_data->in), - 0, sizeof(g_cmd_data->in))) { + 0, sizeof(g_cmd_data->in)) != EOK) { tloge("Clean the command buffer failed\n"); ret = -EFAULT; return ret; @@ -2053,14 +2116,14 @@ int smc_context_init(const struct device *class_dev) return -ENOMEM; ret = alloc_cmd_buffer(); - if (ret) + if (ret != 0) return ret; /* Send the allocated buffer to TrustedCore for init */ smc_set_cmd_buffer(); ret = parse_params_from_tee(); - if (ret) { + if (ret != 0) { tloge("parse params from tee failed\n"); goto free_mem; } @@ -2074,7 +2137,7 @@ int smc_context_init(const struct device *class_dev) } ret = init_smc_related_rsrc(class_dev); - if (ret) + if (ret != 0) goto free_siq_worker; return 0; @@ -2083,7 +2146,7 @@ free_siq_worker: kthread_stop(g_siq_thread); g_siq_thread = NULL; free_mem: - free_page((unsigned long)(uintptr_t)g_cmd_data); + free_cmd_mem((uint64_t)(uintptr_t)g_cmd_data); g_cmd_data = NULL; return ret; } @@ -2095,7 +2158,7 @@ int init_smc_svc_thread(void) if (unlikely(IS_ERR_OR_NULL(g_smc_svc_thread))) { tloge("couldn't create smc_svc_thread %ld\n", PTR_ERR(g_smc_svc_thread)); - return PTR_ERR(g_smc_svc_thread); + return (int)PTR_ERR(g_smc_svc_thread); } tz_kthread_bind_mask(g_smc_svc_thread); wake_up_process(g_smc_svc_thread); @@ -2110,11 +2173,44 @@ int teeos_log_exception_archive(unsigned int eventid, return 0; } -void smc_free_data(void) +void svc_thread_release(void) { - free_page((unsigned long)(uintptr_t)g_cmd_data); if (!IS_ERR_OR_NULL(g_smc_svc_thread)) { kthread_stop(g_smc_svc_thread); g_smc_svc_thread = NULL; } } + +void free_smc_data(void) +{ + struct pending_entry *pe = NULL, *temp = NULL; + + free_cmd_mem((uint64_t)(uintptr_t)g_cmd_data); + smc_wakeup_broadcast(); + svc_thread_release(); + if (!IS_ERR_OR_NULL(g_siq_thread)) { + atomic_set(&g_siq_th_run, STOP_SIQ_THREAD); + wake_up_interruptible(&siq_th_wait); + kthread_stop(g_siq_thread); + g_siq_thread = NULL; + } + +#if (KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE) + flush_kthread_worker(&g_ipi_helper_worker); +#else + kthread_flush_worker(&g_ipi_helper_worker); +#endif + if (!IS_ERR_OR_NULL(g_ipi_helper_thread)) { + kthread_stop(g_ipi_helper_thread); + g_ipi_helper_thread = NULL; + } + free_cmd_monitor(); + + spin_lock(&g_pend_lock); + list_for_each_entry_safe(pe, temp, &g_pending_head, list) { + list_del(&pe->list); + put_task_struct(pe->task); + kfree(pe); + } + spin_unlock(&g_pend_lock); +} diff --git a/core/smc_smp.h b/core/smc_smp.h index 11673ea127fc46aa62898050733683f101833fc7..c36e79700f6a1f39a3db4a83fa2ff925c81b5994 100644 --- a/core/smc_smp.h +++ b/core/smc_smp.h @@ -71,7 +71,7 @@ struct pending_entry { #ifdef BIT_MASK #undef BIT_MASK #endif -#define BIT_MASK(nr) (1UL << (((uint64_t)nr) % sizeof(uint64_t))) +#define BIT_MASK(nr) (1UL << (((uint64_t)(nr)) % sizeof(uint64_t))) #ifdef BIT_WORD #undef BIT_WORD @@ -84,7 +84,7 @@ struct pending_entry { #define DECLARE_BITMAP(name, bits) uint64_t name[BITS_TO_LONGS(bits)] #define SIQ_DUMP_TIMEOUT 1U -#define SIQ_DUMP_SHELL 2U +#define SIQ_DUMP_SHELL 2U typedef uint32_t smc_buf_lock_t; @@ -106,7 +106,7 @@ struct tc_ns_smc_queue { bool sigkill_pending(struct task_struct *tsk); int smc_context_init(const struct device *class_dev); -void smc_free_data(void); +void free_smc_data(void); int tc_ns_smc(struct tc_ns_smc_cmd *cmd); int tc_ns_smc_with_no_nr(struct tc_ns_smc_cmd *cmd); int teeos_log_exception_archive(unsigned int eventid, const char *exceptioninfo); @@ -122,5 +122,13 @@ void foreach_pending_entry(void (*func)(struct pending_entry *)); void put_pending_entry(struct pending_entry *pe); void show_cmd_bitmap(void); void wakeup_tc_siq(uint32_t siq_mode); +void smc_set_cmd_buffer(void); +unsigned long raw_smc_send(uint32_t cmd, phys_addr_t cmd_addr, uint32_t cmd_type, uint8_t wait); +void occupy_clean_cmd_buf(void); +void clr_system_crash_flag(void); +void svc_thread_release(void); +int send_smc_cmd_rebooting(uint32_t cmd_id, phys_addr_t cmd_addr, uint32_t cmd_type, + const struct tc_ns_smc_cmd *in_cmd); +void send_smc_reset_cmd_buffer(void); #endif diff --git a/core/tc_client_driver.c b/core/tc_client_driver.c index a993d2e92c62d06487a714d371a8450ed79c6c89..7c63c3a53958070440052b345faed51e79d95322 100644 --- a/core/tc_client_driver.c +++ b/core/tc_client_driver.c @@ -1,3 +1,4 @@ + /* * tc_client_driver.c * @@ -20,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -59,6 +59,7 @@ #endif #include #include +#include #include "smc_smp.h" #include "teek_client_constants.h" #include "agent.h" @@ -67,32 +68,34 @@ #include "tc_ns_log.h" #include "tc_ns_client.h" #include "mailbox_mempool.h" +#include "shared_mem.h" #include "tz_spi_notify.h" #include "client_hash_auth.h" #include "auth_base_impl.h" #include "tlogger.h" #include "session_manager.h" +#include "internal_functions.h" #include "ko_adapt.h" #include "tz_pm.h" -#include "tz_kthread_affinity.h" #include "reserved_mempool.h" -static dev_t g_tc_ns_client_devt; static struct class *g_driver_class; -static struct cdev g_tc_ns_client_cdev; static struct device_node *g_dev_node; +struct dev_node g_tc_client; +struct dev_node g_tc_private; + #ifdef CONFIG_ACPI static int g_acpi_irq; #endif static unsigned int g_device_file_cnt = 1; static DEFINE_MUTEX(g_device_file_cnt_lock); +static DEFINE_MUTEX(g_set_ca_hash_lock); /* dev node list and itself has mutex to avoid race */ struct tc_ns_dev_list g_tc_ns_dev_list; -static struct task_struct *g_teecd_task; struct tc_ns_dev_list *get_dev_list(void) { @@ -106,19 +109,12 @@ static int tc_ns_get_tee_version(const struct tc_ns_dev_file *dev_file, struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; int ret = 0; struct mb_cmd_pack *mb_pack = NULL; - bool is_teecd = (g_teecd_task == current->group_leader) && - (!tc_ns_get_uid()); if (!argp) { tloge("error input parameter\n"); return -EINVAL; } - if (!is_teecd) { - tloge("ioctl is not from teecd and return\n"); - return -EACCES; - } - mb_pack = mailbox_alloc_cmd_pack(); if (!mb_pack) { tloge("alloc mb pack failed\n"); @@ -129,17 +125,17 @@ static int tc_ns_get_tee_version(const struct tc_ns_dev_file *dev_file, smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = GLOBAL_CMD_ID_GET_TEE_VERSION; smc_cmd.dev_file_id = dev_file->dev_file_id; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; - if (tc_ns_smc(&smc_cmd)) { + if (tc_ns_smc(&smc_cmd) != 0) { ret = -EPERM; tloge("smc call returns error ret 0x%x\n", smc_cmd.ret_val); } version = mb_pack->operation.params[0].value.a; - if (copy_to_user(argp, &version, sizeof(unsigned int))) + if (copy_to_user(argp, &version, sizeof(unsigned int)) != 0) ret = -EFAULT; mailbox_free(mb_pack); @@ -156,8 +152,9 @@ static int get_pack_name_len(struct tc_ns_dev_file *dev_file, const uint8_t *cert_buffer) { uint32_t tmp_len = 0; + dev_file->pkg_name_len = 0; - if (memcpy_s(&tmp_len, sizeof(tmp_len), cert_buffer, sizeof(tmp_len))) + if (memcpy_s(&tmp_len, sizeof(tmp_len), cert_buffer, sizeof(tmp_len)) != 0) return -EFAULT; if (tmp_len == 0 || tmp_len >= MAX_PACKAGE_NAME_LEN) { @@ -174,8 +171,9 @@ static int get_public_key_len(struct tc_ns_dev_file *dev_file, const uint8_t *cert_buffer) { uint32_t tmp_len = 0; + dev_file->pub_key_len = 0; - if (memcpy_s(&tmp_len, sizeof(tmp_len), cert_buffer, sizeof(tmp_len))) + if (memcpy_s(&tmp_len, sizeof(tmp_len), cert_buffer, sizeof(tmp_len)) != 0) return -EFAULT; if (tmp_len > MAX_PUBKEY_LEN) { @@ -192,11 +190,11 @@ static int get_public_key(struct tc_ns_dev_file *dev_file, const uint8_t *cert_buffer) { /* get public key */ - if (!dev_file->pub_key_len) + if (dev_file->pub_key_len == 0) return 0; if (memcpy_s(dev_file->pub_key, MAX_PUBKEY_LEN, cert_buffer, - dev_file->pub_key_len)) { + dev_file->pub_key_len) != 0) { tloge("failed to copy pub key len\n"); return -EINVAL; } @@ -217,7 +215,7 @@ static bool is_cert_buffer_size_valid(int cert_buffer_size) * modulus_size(4bytes) ||modulus buffer * || exponent size || exponent buffer */ - if (cert_buffer_size > MAX_BUF_LEN || !cert_buffer_size) { + if (cert_buffer_size > MAX_BUF_LEN || cert_buffer_size == 0) { tloge("cert buffer size is invalid!\n"); return false; } @@ -247,7 +245,7 @@ static int client_login_prepare(uint8_t *cert_buffer, if (!is_cert_buffer_size_valid(cert_buffer_size)) return -EINVAL; - if (copy_from_user(cert_buffer, buffer, cert_buffer_size)) { + if (copy_from_user(cert_buffer, buffer, cert_buffer_size) != 0) { tloge("Failed to get user login info!\n"); return -EINVAL; } @@ -255,6 +253,20 @@ static int client_login_prepare(uint8_t *cert_buffer, return 0; } +static int tc_login_check(const struct tc_ns_dev_file *dev_file) +{ + int ret = check_teecd_auth(); + if (ret != 0) { + tloge("teec auth failed, ret %d\n", ret); + return -EACCES; + } + + if (!dev_file) + return -EINVAL; + + return 0; +} + static int tc_ns_client_login_func(struct tc_ns_dev_file *dev_file, const void __user *buffer) { @@ -263,8 +275,8 @@ static int tc_ns_client_login_func(struct tc_ns_dev_file *dev_file, uint8_t *temp_cert_buffer = NULL; unsigned int cert_buffer_size = 0; - if (!dev_file) - return -EINVAL; + if (tc_login_check(dev_file) != 0) + return -EFAULT; if (!buffer) { /* @@ -284,31 +296,31 @@ static int tc_ns_client_login_func(struct tc_ns_dev_file *dev_file, } ret = alloc_login_buf(dev_file, &cert_buffer, &cert_buffer_size); - if (ret) { + if (ret != 0) { mutex_unlock(&dev_file->login_setup_lock); return ret; } temp_cert_buffer = cert_buffer; - if (client_login_prepare(cert_buffer, buffer, cert_buffer_size)) { + if (client_login_prepare(cert_buffer, buffer, cert_buffer_size) != 0) { ret = -EINVAL; goto error; } ret = get_pack_name_len(dev_file, cert_buffer); - if (ret) + if (ret != 0) goto error; cert_buffer += sizeof(dev_file->pkg_name_len); if (strncpy_s(dev_file->pkg_name, MAX_PACKAGE_NAME_LEN, cert_buffer, - dev_file->pkg_name_len)) { + dev_file->pkg_name_len) != 0) { ret = -ENOMEM; goto error; } cert_buffer += dev_file->pkg_name_len; ret = get_public_key_len(dev_file, cert_buffer); - if (ret) + if (ret != 0) goto error; cert_buffer += sizeof(dev_file->pub_key_len); @@ -346,11 +358,17 @@ int tc_ns_client_open(struct tc_ns_dev_file **dev_file, uint8_t kernel_api) mutex_unlock(&g_device_file_cnt_lock); INIT_LIST_HEAD(&dev->shared_mem_list); dev->login_setup = 0; +#ifdef CONFIG_AUTH_HASH + dev->cainfo_hash_setup = 0; +#endif dev->kernel_api = kernel_api; dev->load_app_flag = 0; mutex_init(&dev->service_lock); mutex_init(&dev->shared_mem_lock); mutex_init(&dev->login_setup_lock); +#ifdef CONFIG_AUTH_HASH + mutex_init(&dev->cainfo_hash_setup_lock); +#endif init_completion(&dev->close_comp); *dev_file = dev; @@ -371,7 +389,7 @@ void free_dev(struct tc_ns_dev_file *dev) { del_dev_node(dev); tee_agent_clear_dev_owner(dev); - if (memset_s(dev, sizeof(*dev), 0, sizeof(*dev))) + if (memset_s(dev, sizeof(*dev), 0, sizeof(*dev)) != 0) tloge("Caution, memset dev fail!\n"); kfree(dev); } @@ -385,6 +403,10 @@ int tc_ns_client_close(struct tc_ns_dev_file *dev) close_unclosed_session_in_kthread(dev); + if (dev->dev_file_id == tui_attach_device()) + free_tui_caller_info(); + + kill_ion_by_cafd(dev->dev_file_id); /* for thirdparty agent, code runs here only when agent crashed */ send_crashed_event_response_all(dev); free_dev(dev); @@ -397,12 +419,21 @@ void shared_vma_open(struct vm_area_struct *vma) (void)vma; } -static void release_vma_shared_mem(struct tc_ns_dev_file *dev_file, - const struct vm_area_struct *vma) +void shared_vma_close(struct vm_area_struct *vma) { struct tc_ns_shared_mem *shared_mem = NULL; struct tc_ns_shared_mem *shared_mem_temp = NULL; bool find = false; + struct tc_ns_dev_file *dev_file = NULL; + if (!vma) { + tloge("vma is null\n"); + return; + } + dev_file = vma->vm_private_data; + if (!dev_file) { + tloge("vm private data is null\n"); + return; + } mutex_lock(&dev_file->shared_mem_lock); list_for_each_entry_safe(shared_mem, shared_mem_temp, @@ -432,30 +463,6 @@ static void release_vma_shared_mem(struct tc_ns_dev_file *dev_file, mutex_unlock(&dev_file->shared_mem_lock); } -void shared_vma_close(struct vm_area_struct *vma) -{ - struct tc_ns_dev_file *dev_file = NULL; - - if (!vma) { - tloge("vma is null\n"); - return; - } - - dev_file = vma->vm_private_data; - if (!dev_file) { - tloge("vm private data is null\n"); - return; - } - - if (g_teecd_task == current->group_leader && !tc_ns_get_uid() && - ((g_teecd_task->flags & PF_EXITING) || - (current->flags & PF_EXITING))) { - tlogd("teecd is killed, just return in vma close\n"); - return; - } - release_vma_shared_mem(dev_file, vma); -} - static struct vm_operations_struct g_shared_remap_vm_ops = { .open = shared_vma_open, .close = shared_vma_close, @@ -473,7 +480,7 @@ static struct tc_ns_shared_mem *find_sharedmem( * check if aready allocated */ list_for_each_entry(shm_tmp, &dev_file->shared_mem_list, head) { - if (atomic_read(&shm_tmp->offset) == vma->vm_pgoff) { + if ((unsigned long)atomic_read(&shm_tmp->offset) == vma->vm_pgoff) { tlogd("sharemem already alloc, shm tmp->offset=%d\n", atomic_read(&shm_tmp->offset)); /* @@ -481,7 +488,7 @@ static struct tc_ns_shared_mem *find_sharedmem( * 1. this shared mem is already mapped * 2. remap a different size shared_mem */ - if ((shm_tmp->user_addr_ca != INVALID_MAP_ADDR)|| + if ((shm_tmp->user_addr_ca != INVALID_MAP_ADDR) || (vma->vm_end - vma->vm_start != shm_tmp->len)) { tloge("already remap once!\n"); return NULL; @@ -505,14 +512,14 @@ static int remap_shared_mem(struct vm_area_struct *vma, unsigned long pfn = res_mem_virt_to_phys((uintptr_t)(shared_mem->kernel_addr)) >> PAGE_SHIFT; unsigned long size = vma->vm_end - vma->vm_start; ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot); // PAGE_SHARED - if (ret) + if (ret != 0) tloge("remap pfn for user failed, ret %d", ret); return ret; } vma->vm_flags |= VM_USERMAP; ret = remap_vmalloc_range(vma, shared_mem->kernel_addr, 0); - if (ret) + if (ret != 0) tloge("can't remap to user, ret = %d\n", ret); return ret; @@ -546,7 +553,7 @@ static int tc_client_mmap(struct file *filp, struct vm_area_struct *vma) } ret = remap_shared_mem(vma, shared_mem); - if (ret) { + if (ret != 0) { if (only_remap) put_sharemem_struct(shared_mem); else @@ -579,20 +586,20 @@ static int ioctl_register_agent(struct tc_ns_dev_file *dev_file, unsigned long a int ret; struct agent_ioctl_args args; - if (!arg) { + if (arg == 0) { tloge("arg is NULL\n"); return -EFAULT; } - if (copy_from_user(&args, (void *)(uintptr_t)arg, sizeof(args))) { + if (copy_from_user(&args, (void *)(uintptr_t)arg, sizeof(args)) != 0) { tloge("copy agent args failed\n"); return -EFAULT; } ret = tc_ns_register_agent(dev_file, args.id, args.buffer_size, &args.buffer, true); - if (!ret) { - if (copy_to_user((void *)(uintptr_t)arg, &args, sizeof(args))) + if (ret == 0) { + if (copy_to_user((void *)(uintptr_t)arg, &args, sizeof(args)) != 0) tloge("copy agent user addr failed\n"); } @@ -624,11 +631,11 @@ static int ioctl_unregister_agent(const struct tc_ns_dev_file *dev_file, } /* ioctls for the secure storage daemon */ -static long tc_agent_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int public_ioctl(const struct file *file, unsigned int cmd, unsigned long arg, bool is_from_client_node) { int ret = -EINVAL; struct tc_ns_dev_file *dev_file = file->private_data; - + void *argp = (void __user *)(uintptr_t)arg; if (!dev_file) { tloge("invalid params\n"); return -EINVAL; @@ -647,15 +654,8 @@ static long tc_agent_ioctl(struct file *file, unsigned int cmd, unsigned long ar case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: ret = ioctl_unregister_agent(dev_file, arg); break; - case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME: - ret = tc_ns_sync_sys_time( - (struct tc_ns_client_time *)(uintptr_t)arg); - break; - case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY: - ret = tc_ns_set_native_hash(arg, GLOBAL_CMD_ID_SET_CA_HASH); - break; - case TC_NS_CLIENT_IOCTL_LATEINIT: - ret = tc_ns_late_init(arg); + case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ: + ret = tc_ns_load_secfile(file->private_data, argp, is_from_client_node); break; default: tloge("invalid cmd!"); @@ -668,47 +668,131 @@ static long tc_agent_ioctl(struct file *file, unsigned int cmd, unsigned long ar static int tc_ns_send_cancel_cmd(struct tc_ns_dev_file *dev_file, void *argp) { struct tc_ns_client_context client_context = {{0}}; + (void)dev_file; if (!argp) { tloge("argp is NULL input buffer\n"); return -EINVAL; } - if (copy_from_user(&client_context, argp, sizeof(client_context))) { + if (copy_from_user(&client_context, argp, sizeof(client_context)) != 0) { tloge("copy from user failed\n"); return -ENOMEM; } client_context.returns.code = TEEC_ERROR_GENERIC; client_context.returns.origin = TEEC_ORIGIN_COMMS; - tloge("not support send cancle cmd now\n"); - if (copy_to_user(argp, &client_context, sizeof(client_context))) + tloge("not support send cancel cmd now\n"); + if (copy_to_user(argp, &client_context, sizeof(client_context)) != 0) return -EFAULT; return 0; } -uint32_t tc_ns_get_uid(void) +static int get_agent_id(unsigned long arg, unsigned int cmd, uint32_t *agent_id) { - struct task_struct *task = NULL; - const struct cred *cred = NULL; - uint32_t uid; - - rcu_read_lock(); - task = get_current(); - get_task_struct(task); - rcu_read_unlock(); - cred = koadpt_get_task_cred(task); - if (!cred) { - tloge("failed to get uid of the task\n"); - put_task_struct(task); - return (uint32_t)(-1); - } - - uid = cred->uid.val; - put_cred(cred); - put_task_struct(task); - tlogd("current uid is %u\n", uid); - return uid; + struct agent_ioctl_args args; + switch (cmd) { + case TC_NS_CLIENT_IOCTL_WAIT_EVENT: + case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: + *agent_id = (unsigned int)arg; + break; + case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: + case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: + if (copy_from_user(&args, (void *)(uintptr_t)arg, sizeof(args)) != 0) { + tloge("copy agent args failed\n"); + return -EFAULT; + } + *agent_id = args.id; + break; + default: + return -EFAULT; + } + return 0; +} + +static int tc_client_agent_ioctl(const struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -EFAULT; + uint32_t agent_id; + + switch (cmd) { + case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: + case TC_NS_CLIENT_IOCTL_WAIT_EVENT: + case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: + case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: + if (get_agent_id(arg, cmd, &agent_id) != 0) + return ret; + if (check_ext_agent_access(agent_id) != 0) { + tloge("the agent is not access\n"); + return -EPERM; + } + ret = public_ioctl(file, cmd, arg, true); + break; + default: + tloge("invalid cmd 0x%x!", cmd); + break; + } + + return ret; +} + +static void handle_cmd_prepare(unsigned int cmd) +{ + if (cmd == TC_NS_CLIENT_IOCTL_SES_OPEN_REQ || + cmd == TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ || + cmd == TC_NS_CLIENT_IOCTL_SEND_CMD_REQ) + freezer_do_not_count(); + + if (cmd != TC_NS_CLIENT_IOCTL_WAIT_EVENT && + cmd != TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE) + livepatch_down_read_sem(); + return; +} + +static void handle_cmd_finish(unsigned int cmd) +{ + if (cmd != TC_NS_CLIENT_IOCTL_WAIT_EVENT && + cmd != TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE) + livepatch_up_read_sem(); + + if (cmd == TC_NS_CLIENT_IOCTL_SES_OPEN_REQ || + cmd == TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ || + cmd == TC_NS_CLIENT_IOCTL_SEND_CMD_REQ) + freezer_count(); + return; +} + +static long tc_private_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -EFAULT; + void *argp = (void __user *)(uintptr_t)arg; + handle_cmd_prepare(cmd); + switch (cmd) { + case TC_NS_CLIENT_IOCTL_GET_TEE_VERSION: + ret = tc_ns_get_tee_version(file->private_data, argp); + break; + case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY: + mutex_lock(&g_set_ca_hash_lock); + ret = tc_ns_set_native_hash((unsigned long)(uintptr_t)argp, GLOBAL_CMD_ID_SET_CA_HASH); + mutex_unlock(&g_set_ca_hash_lock); + break; + case TC_NS_CLIENT_IOCTL_LATEINIT: + ret = tc_ns_late_init(arg); + break; + case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME: + ret = sync_system_time_from_user( + (struct tc_ns_client_time *)(uintptr_t)arg); + break; + default: + ret = public_ioctl(file, cmd, arg, false); + break; + } + + handle_cmd_finish(cmd); + + return ret; } static long tc_client_ioctl(struct file *file, unsigned int cmd, @@ -717,41 +801,32 @@ static long tc_client_ioctl(struct file *file, unsigned int cmd, int ret = -EFAULT; void *argp = (void __user *)(uintptr_t)arg; + handle_cmd_prepare(cmd); switch (cmd) { case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ: case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ: case TC_NS_CLIENT_IOCTL_SEND_CMD_REQ: ret = tc_client_session_ioctl(file, cmd, arg); break; - case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ: - ret = tc_ns_load_secfile(file->private_data, argp); - break; case TC_NS_CLIENT_IOCTL_CANCEL_CMD_REQ: ret = tc_ns_send_cancel_cmd(file->private_data, argp); break; case TC_NS_CLIENT_IOCTL_LOGIN: ret = tc_ns_client_login_func(file->private_data, argp); break; - case TC_NS_CLIENT_IOCTL_WAIT_EVENT: - case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: - case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: - case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: - case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME: - case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY: - case TC_NS_CLIENT_IOCTL_LATEINIT: - ret = tc_agent_ioctl(file, cmd, arg); - break; case TC_NS_CLIENT_IOCTL_TST_CMD_REQ: ret = tc_ns_tst_cmd(argp); break; - case TC_NS_CLIENT_IOCTL_GET_TEE_VERSION: - ret = tc_ns_get_tee_version(file->private_data, argp); + case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ: + ret = public_ioctl(file, cmd, arg, true); break; default: - tloge("invalid cmd 0x%x!", cmd); + ret = tc_client_agent_ioctl(file, cmd, arg); break; } + handle_cmd_finish(cmd); + tlogd("tc client ioctl ret = 0x%x\n", ret); return (long)ret; } @@ -760,60 +835,53 @@ static int tc_client_open(struct inode *inode, struct file *file) { int ret; struct tc_ns_dev_file *dev = NULL; + (void)inode; + + ret = check_teecd_auth(); + if (ret != 0) { + tloge("teec auth failed, ret %d\n", ret); + return -EACCES; + } - g_teecd_task = current->group_leader; file->private_data = NULL; ret = tc_ns_client_open(&dev, TEE_REQ_FROM_USER_MODE); - if (!ret) + if (ret == 0) file->private_data = dev; return ret; } -static int teec_daemon_close(struct tc_ns_dev_file *dev) +static int tc_client_close(struct inode *inode, struct file *file) { - if (!dev) { - tloge("invalid dev(null)\n"); - return -EINVAL; - } + int ret = 0; + struct tc_ns_dev_file *dev = file->private_data; + (void)inode; - del_dev_node(dev); - kfree(dev); - return 0; + livepatch_down_read_sem(); + ret = tc_ns_client_close(dev); + livepatch_up_read_sem(); + file->private_data = NULL; + + return ret; } -static int tc_client_close(struct inode *inode, struct file *file) +static int tc_private_close(struct inode *inode, struct file *file) { - int ret = 0; struct tc_ns_dev_file *dev = file->private_data; + (void)inode; - if (g_teecd_task == current->group_leader && !tc_ns_get_uid()) { - /* for teecd close fd */ - if ((g_teecd_task->flags & PF_EXITING) || - (current->flags & PF_EXITING)) { - tloge("teecd exit!\n"); - if (is_system_agent(dev)) { - /* for teecd agent close fd */ - send_event_response_single(dev); - free_dev(dev); - } else { - /* for ca damon close fd */ - ret = teec_daemon_close(dev); - } - } else { - /* - * for ca damon close fd when ca damon close fd - * later than HIDL thread - */ - ret = tc_ns_client_close(dev); - } + /* for teecd close fd */ + if (is_system_agent(dev)) { + /* for teecd agent close fd */ + send_event_response_single(dev); + free_dev(dev); } else { - /* for CA(HIDL thread) close fd */ - ret = tc_ns_client_close(dev); + /* for ca damon close fd */ + free_dev(dev); } file->private_data = NULL; - return ret; + return 0; } struct tc_ns_dev_file *tc_find_dev_file(unsigned int dev_file_id) @@ -840,8 +908,19 @@ long tc_compat_client_ioctl(struct file *file, unsigned int cmd, if (!file) return -EINVAL; - arg = (unsigned long)(uintptr_t)compat_ptr(arg); - ret = tc_client_ioctl(file, cmd, arg); + ret = tc_client_ioctl(file, cmd, (unsigned long)(uintptr_t)compat_ptr(arg)); + return ret; +} + +long tc_compat_private_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long ret; + + if (!file) + return -EINVAL; + + ret = tc_private_ioctl(file, cmd, (unsigned long)(uintptr_t)compat_ptr(arg)); return ret; } #endif @@ -857,6 +936,15 @@ static const struct file_operations g_tc_ns_client_fops = { #endif }; +static const struct file_operations g_teecd_fops = { + .owner = THIS_MODULE, + .open = tc_client_open, + .release = tc_private_close, + .unlocked_ioctl = tc_private_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tc_compat_private_ioctl, +#endif +}; #ifdef CONFIG_ACPI static int tzdriver_probe(struct platform_device *pdev) @@ -887,6 +975,7 @@ MODULE_DEVICE_TABLE(acpi, g_tzdriver_acpi_match); static int tzdriver_probe(struct platform_device *pdev) { + (void)pdev; return 0; } @@ -918,26 +1007,9 @@ static struct platform_driver g_tz_platform_driver = { .probe = tzdriver_probe, }; -static int create_cdev(void) -{ - int ret; - - cdev_init(&g_tc_ns_client_cdev, &g_tc_ns_client_fops); - g_tc_ns_client_cdev.owner = THIS_MODULE; - - ret = cdev_add(&g_tc_ns_client_cdev, - MKDEV(MAJOR(g_tc_ns_client_devt), 0), 1); - if (ret < 0) { - tloge("cdev_add failed %d", ret); - return -ENOENT; - } - - return 0; -} - static int load_hw_info(void) { - if (platform_driver_register(&g_tz_platform_driver)) { + if (platform_driver_register(&g_tz_platform_driver) != 0) { tloge("platform register driver failed\n"); return -EFAULT; } @@ -947,6 +1019,7 @@ static int load_hw_info(void) if (!g_dev_node) { tloge("no trusted_core compatible node found\n"); #ifndef CONFIG_ACPI + platform_driver_unregister(&g_tz_platform_driver); return -ENODEV; #endif } @@ -954,56 +1027,122 @@ static int load_hw_info(void) return 0; } -static int tc_ns_client_init(struct device **class_dev) +static int create_dev_node(struct dev_node *node) { int ret; + if (!node || !(node->node_name)) { + tloge("node or member is null\n"); + return -EFAULT; + } + if (alloc_chrdev_region(&(node->devt), 0, 1, + node->node_name) != 0) { + tloge("alloc chrdev region failed"); + ret = -EFAULT; + return ret; + } + node->class_dev = device_create(node->driver_class, NULL, node->devt, + NULL, node->node_name); + if (IS_ERR_OR_NULL(node->class_dev)) { + tloge("class device create failed"); + ret = -ENOMEM; + goto chrdev_region_unregister; + } + node->class_dev->of_node = g_dev_node; - tlogd("tc_ns_client_init"); - ret = load_hw_info(); - if (ret) + cdev_init(&(node->char_dev), node->fops); + (node->char_dev).owner = THIS_MODULE; + + return 0; + +chrdev_region_unregister: + unregister_chrdev_region(node->devt, 1); + return ret; +} + +static int init_dev_node(struct dev_node *node, char *node_name, + struct class *driver_class, const struct file_operations *fops) +{ + int ret = -1; + if (!node) { + tloge("node is NULL\n"); return ret; - - ret = load_reserved_mem(); - if (ret) + } + node->node_name = node_name; + node->driver_class = driver_class; + node->fops = fops; + + ret = create_dev_node(node); + return ret; +} + +static void destory_dev_node(struct dev_node *node, struct class *driver_class) +{ + device_destroy(driver_class, node->devt); + unregister_chrdev_region(node->devt, 1); + return; +} + +static int enable_dev_nodes(void) +{ + int ret; + + ret = cdev_add(&(g_tc_private.char_dev), + MKDEV(MAJOR(g_tc_private.devt), 0), 1); + if (ret < 0) { + tloge("cdev add failed %d", ret); return ret; + } - if (alloc_chrdev_region(&g_tc_ns_client_devt, 0, 1, - TC_NS_CLIENT_DEV)) { - tloge("alloc chrdev region failed"); - return -EFAULT; + ret = cdev_add(&(g_tc_client.char_dev), + MKDEV(MAJOR(g_tc_client.devt), 0), 1); + if (ret < 0) { + tloge("cdev add failed %d", ret); + cdev_del(&(g_tc_private.char_dev)); + return ret; } + return 0; +} + +static int tc_ns_client_init(void) +{ + int ret; + ret = load_hw_info(); + if (ret != 0) + return ret; + + ret = load_reserved_mem(); + if (ret != 0) + return ret; + ret = load_tz_shared_mem(g_dev_node); + if (ret != 0) + goto unmap_res_mem; g_driver_class = class_create(THIS_MODULE, TC_NS_CLIENT_DEV); if (IS_ERR_OR_NULL(g_driver_class)) { tloge("class create failed"); ret = -ENOMEM; - goto chrdev_region_unregister; + goto unmap_res_mem; } - *class_dev = device_create(g_driver_class, NULL, g_tc_ns_client_devt, - NULL, TC_NS_CLIENT_DEV); - if (IS_ERR_OR_NULL(*class_dev)) { - tloge("class device create failed"); - ret = -ENOMEM; - goto destroy_class; + ret = init_dev_node(&g_tc_client, TC_NS_CLIENT_DEV, g_driver_class, &g_tc_ns_client_fops); + if (ret != 0) { + class_destroy(g_driver_class); + goto unmap_res_mem; + } + ret = init_dev_node(&g_tc_private, TC_PRIV_DEV, g_driver_class, &g_teecd_fops); + if (ret != 0) { + destory_dev_node(&g_tc_client, g_driver_class); + class_destroy(g_driver_class); + goto unmap_res_mem; } - - (*class_dev)->of_node = g_dev_node; - if (create_cdev()) - goto class_device_destroy; INIT_LIST_HEAD(&g_tc_ns_dev_list.dev_file_list); mutex_init(&g_tc_ns_dev_list.dev_lock); init_crypto_hash_lock(); init_srvc_list(); return ret; - -class_device_destroy: - device_destroy(g_driver_class, g_tc_ns_client_devt); -destroy_class: - class_destroy(g_driver_class); -chrdev_region_unregister: - unregister_chrdev_region(g_tc_ns_client_devt, 1); +unmap_res_mem: + unmap_res_mem(); return ret; } @@ -1012,34 +1151,43 @@ static int tc_teeos_init(struct device *class_dev) int ret; ret = smc_context_init(class_dev); - if (ret) { + if (ret != 0) { tloge("smc context init failed\n"); return ret; } + ret = tee_init_reboot_thread(); + if (ret != 0) { + tloge("init reboot thread failed\n"); + goto smc_data_free; + } + ret = reserved_mempool_init(); - if (ret) { + if (ret != 0) { tloge("reserved memory init failed\n"); - goto smc_data_free; + goto reboot_thread_free; } ret = mailbox_mempool_init(); - if (ret) { + if (ret != 0) { tloge("tz mailbox init failed\n"); - goto smc_data_free; + goto release_resmem; } ret = tz_spi_init(class_dev, g_dev_node); - if (ret) { + if (ret != 0) { tloge("tz spi init failed\n"); goto release_mempool; } return 0; release_mempool: - mailbox_mempool_destroy(); + free_mailbox_mempool(); +release_resmem: free_reserved_mempool(); +reboot_thread_free: + free_reboot_thread(); smc_data_free: - smc_free_data(); + free_smc_data(); return ret; } @@ -1048,65 +1196,125 @@ static void tc_re_init(const struct device *class_dev) int ret; agent_init(); + ret = tc_ns_register_ion_mem(); + if (ret != 0) + tloge("Failed to register ion mem in tee\n"); #ifdef CONFIG_TZDRIVER_MODULE ret = init_tlogger_service(); - if (ret) + if (ret != 0) tloge("tlogger init failed\n"); #endif - if (init_smc_svc_thread()) { + ret = init_tui(class_dev); + if (ret != 0) + tloge("init_tui failed 0x%x\n", ret); + +#ifndef CONFIG_DISABLE_SVC + if (init_smc_svc_thread() != 0) { tloge("init svc thread\n"); ret = -EFAULT; } +#endif + + if (init_dynamic_mem() != 0) { + tloge("init dynamic mem Failed\n"); + ret = -EFAULT; + } + +#ifdef CONFIG_LIVEPATCH_ENABLE + /* + * access this sys node only after this function is initialized + */ + if (livepatch_init(class_dev)) { + tloge("livepatch init failed\n"); + ret = -EFAULT; + } +#endif - if (ret) + if (ret != 0) tloge("Caution! Running environment init failed!\n"); } static __init int tc_init(void) { - struct device *class_dev = NULL; int ret = 0; init_kthread_cpumask(); - ret = tc_ns_client_init(&class_dev); - if (ret) + ret = tc_ns_client_init(); + if (ret != 0) return ret; - - ret = tc_teeos_init(class_dev); - if (ret) { + ret = tc_teeos_init(g_tc_client.class_dev); + if (ret != 0) { tloge("tc teeos init failed\n"); goto class_device_destroy; } /* run-time environment init failure don't block tzdriver init proc */ - tc_re_init(class_dev); + tc_re_init(g_tc_client.class_dev); + + /* + * Note: the enable_dev_nodes function must be called + * at the end of tc_init + */ + ret = enable_dev_nodes(); + if (ret != 0) { + tloge("enable dev nodes failed\n"); + goto class_device_destroy; + } return 0; class_device_destroy: - device_destroy(g_driver_class, g_tc_ns_client_devt); + destory_dev_node(&g_tc_client, g_driver_class); + destory_dev_node(&g_tc_private, g_driver_class); class_destroy(g_driver_class); - unregister_chrdev_region(g_tc_ns_client_devt, 1); - + platform_driver_unregister(&g_tz_platform_driver); return ret; } +static void free_dev_list(void) +{ + struct tc_ns_dev_file *dev_file = NULL, *temp = NULL; + + mutex_lock(&g_tc_ns_dev_list.dev_lock); + list_for_each_entry_safe(dev_file, temp, &g_tc_ns_dev_list.dev_file_list, head) { + list_del(&dev_file->head); + kfree(dev_file); + } + mutex_unlock(&g_tc_ns_dev_list.dev_lock); +} + static void tc_exit(void) { - tlogd("tz client exit"); - tz_spi_exit(); + tlogi("tz client exit"); + /* + * You should first execute "cdev_del" to + * prevent access to the device node when uninstalling "tzdriver". + */ + cdev_del(&(g_tc_private.char_dev)); + cdev_del(&(g_tc_client.char_dev)); + free_agent(); + free_reboot_thread(); + free_tui(); + free_tz_spi(g_tc_client.class_dev); /* run-time environment exit should before teeos exit */ - device_destroy(g_driver_class, g_tc_ns_client_devt); + destory_dev_node(&g_tc_client, g_driver_class); + destory_dev_node(&g_tc_private, g_driver_class); + platform_driver_unregister(&g_tz_platform_driver); class_destroy(g_driver_class); - unregister_chrdev_region(g_tc_ns_client_devt, 1); - smc_free_data(); - agent_exit(); + free_smc_data(); + free_event_mem(); #ifdef CONFIG_TZDRIVER_MODULE - exit_tlogger_service(); + free_tlogger_service(); #endif - mailbox_mempool_destroy(); + free_interrupt_trace(); + free_mailbox_mempool(); free_reserved_mempool(); - tee_exit_shash_handle(); + free_shash_handle(); + fault_monitor_end(); + free_livepatch(); + free_all_session(); + free_dev_list(); + tlogi("tz client exit finished"); } MODULE_AUTHOR("iTrustee"); diff --git a/core/tc_client_driver.h b/core/tc_client_driver.h index b7a2bd25d02c7401cbdcde489e5f46daa495d42f..3bfeb24b8dbe4963f14a26a893b19d07c63efdf5 100644 --- a/core/tc_client_driver.h +++ b/core/tc_client_driver.h @@ -19,10 +19,19 @@ #define TC_CLIENT_DRIVER_H #include +#include #include "teek_ns_client.h" +struct dev_node { + struct class *driver_class; + struct cdev char_dev; + dev_t devt; + struct device *class_dev; + const struct file_operations *fops; + char *node_name; +}; + struct tc_ns_dev_list *get_dev_list(void); -uint32_t tc_ns_get_uid(void); struct tc_ns_dev_file *tc_find_dev_file(unsigned int dev_file_id); int tc_ns_client_open(struct tc_ns_dev_file **dev_file, uint8_t kernel_api); int tc_ns_client_close(struct tc_ns_dev_file *dev); diff --git a/core/tee_compat_check.c b/core/tee_compat_check.c index fa690d0f700e63a8cd127cacb54f37a70443a6e5..b9baac487122fd90cd8685ca513921c99add35f9 100644 --- a/core/tee_compat_check.c +++ b/core/tee_compat_check.c @@ -22,7 +22,7 @@ #include "teek_ns_client.h" #include "tc_ns_log.h" -int32_t check_teeos_compat_level(uint32_t *buffer, uint32_t size) +int32_t check_teeos_compat_level(const uint32_t *buffer, uint32_t size) { const uint16_t major = TEEOS_COMPAT_LEVEL_MAJOR; const uint16_t minor = TEEOS_COMPAT_LEVEL_MINOR; @@ -42,7 +42,7 @@ int32_t check_teeos_compat_level(uint32_t *buffer, uint32_t size) return -EPERM; } /* just print warning */ - if (buffer[2] != minor) + if (buffer[2] != minor) tlogw("check minor ver failed, minor tz=%u, minor tee=%u\n", minor, buffer[2]); return 0; diff --git a/core/tee_compat_check.h b/core/tee_compat_check.h index 976ec18faac3a4f78034215e9e018ba3b429986e..7a1824098b2d13370dc6237cf4e3a638831318b5 100644 --- a/core/tee_compat_check.h +++ b/core/tee_compat_check.h @@ -25,11 +25,11 @@ * this version number MAJOR.MINOR is used * to identify the compatibility of tzdriver and teeos */ -#define TEEOS_COMPAT_LEVEL_MAJOR 1 +#define TEEOS_COMPAT_LEVEL_MAJOR 2 #define TEEOS_COMPAT_LEVEL_MINOR 0 #define VER_CHECK_MAGIC_NUM 0x5A5A5A5A #define COMPAT_LEVEL_BUF_LEN 12 -int32_t check_teeos_compat_level(uint32_t *buffer, uint32_t size); +int32_t check_teeos_compat_level(const uint32_t *buffer, uint32_t size); #endif diff --git a/core/tee_trace_event.c b/core/tee_trace_event.c deleted file mode 100644 index 38d651a0008722c7226a973b241d10a75197f21c..0000000000000000000000000000000000000000 --- a/core/tee_trace_event.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * tee_trace_event.c - * - * functions for TEE trace - * - * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "tee_trace_event.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define TEE_TASK_NAME_LEN 16 /* same as tcb_prop->tcb_name */ - -#define trace_event_name(event_id, enable) \ - [event_id] = { #event_id, enable} - -#define compile_time_assert(cond, msg) typedef char g_assert_##msg[(cond) ? 1 : -1] - -struct tee_view_state_t { - const char *name; - bool enable; -}; - -/* Make sure it has the same order as 'enum tee_event_id' */ -static struct tee_view_state_t view_state[TEE_EVENT_MAX] = { - trace_event_name(INVOKE_CMD_START, true), - trace_event_name(INVOKE_CMD_END, true), - trace_event_name(SMC_SEND, true), - trace_event_name(SMC_DONE, true), - trace_event_name(SMC_IN, true), - trace_event_name(SMC_OUT, true), - trace_event_name(SMC_SLEEP, true), - trace_event_name(SMC_PREEMPT, true), - trace_event_name(GTASK_GET_CMD, false), - trace_event_name(GTASK_PUT_CMD, false), - trace_event_name(GTASK_REQ_TA, false), - trace_event_name(GTASK_RESP_TA, false), - trace_event_name(SPI_WAKEUP, true), - trace_event_name(SCHED_IN, true), - trace_event_name(SCHED_OUT, true), -}; - -static const char* trace_task[] = { - /* add ta name like this "echo_task" */ -}; - -compile_time_assert(ARRAY_SIZE(trace_task) <= TEE_TRACE_TASK_MAX, - trace_task_too_large); - -struct tee_trace_event_t { - enum tee_event_id id; - uint32_t ca_pid; - uint64_t time; - uint64_t add_info; -}; - -struct tee_trace_stream_t { - uint32_t total; - uint32_t cur; - struct tee_trace_event_t events[TEE_TRACE_EVENT_NUM]; -}; - -struct tee_trace_mem_t { - bool start; - uint32_t freq; - bool enable[TEE_EVENT_MAX]; - uint32_t trace_task; - char trace_task_name[TEE_TRACE_TASK_MAX][TEE_TASK_NAME_LEN]; - struct tee_trace_stream_t *streams[NR_CPUS]; -}; - -#define TRACE_STREAM_SIZE ALIGN(sizeof(struct tee_trace_stream_t), PAGE_SIZE) -#define TRACE_MEM_SIZE ALIGN(sizeof(struct tee_trace_mem_t), PAGE_SIZE) - -/* pages associate with g_event_mem */ -static struct page *g_event_pages; -/* pages associate with g_event_mem->streams[NR_CPUS] */ -static struct page *g_stream_pages[NR_CPUS]; -static struct tee_trace_mem_t *g_event_mem; - -void tee_trace_add_event(enum tee_event_id id, uint64_t add_info) -{ - int32_t cpu_id = raw_smp_processor_id(); - struct tee_trace_stream_t *stream = NULL; - struct tee_trace_event_t *event = NULL; - - if (id < INVOKE_CMD_START || id >= TEE_EVENT_MAX) - return; - - if (g_event_mem == NULL || !g_event_mem->start || !g_event_mem->enable[id]) - return; - preempt_disable(); - stream = g_event_mem->streams[cpu_id]; - event = &stream->events[stream->cur]; - - if (unlikely((stream->cur + 1) >= stream->total)) { - tloge("events buffer too small\n"); - preempt_enable(); - return; - } - - event->id = id; - event->ca_pid = current->pid; - event->time = arch_timer_get_cntkctl(); - event->add_info = (add_info == 0) ? current->pid : add_info; - stream->cur++; - preempt_enable(); -} - -struct trace_mem_cmd_t { - uint64_t trace_mem; - uint64_t trace_mem_size; - uint64_t trace_streams[NR_CPUS]; -}; - -static void *init_cmd_of_trace_mem(void) -{ - uint32_t i; - struct trace_mem_cmd_t *p = - mailbox_alloc(sizeof(struct trace_mem_cmd_t), MB_FLAG_ZERO); - - if (p == NULL) - return NULL; - - p->trace_mem = virt_to_phys(g_event_mem); - p->trace_mem_size = TRACE_MEM_SIZE; - for (i = 0; i < NR_CPUS; i++) - p->trace_streams[i] = virt_to_phys(g_event_mem->streams[i]); - - return p; -} - -static int tee_trace_event_send_cmd(uint32_t cmd) -{ - int ret = 0; - struct tc_ns_smc_cmd smc_cmd = { { 0 }, 0}; - struct mb_cmd_pack *mb_pack = NULL; - void *cmd_buffer = NULL; - - mb_pack = mailbox_alloc_cmd_pack(); - if (mb_pack == NULL) - return -ENOMEM; - - switch (cmd) { - case GLOBAL_CMD_ID_TRACE_ENABLE: - mb_pack->operation.paramtypes = TEE_PARAM_TYPE_MEMREF_INPUT; - cmd_buffer = init_cmd_of_trace_mem(); - if (cmd_buffer == NULL) { - mailbox_free(mb_pack); - return -ENOMEM; - } - mb_pack->operation.params[0].memref.buffer = virt_to_phys(cmd_buffer); - mb_pack->operation.buffer_h_addr[0] = - virt_to_phys(cmd_buffer) >> ADDR_TRANS_NUM; - mb_pack->operation.params[0].memref.size = - ALIGN(sizeof(struct trace_mem_cmd_t), PAGE_SIZE); - break; - default: - mailbox_free(mb_pack); - return -EINVAL; - } - smc_cmd.cmd_type = CMD_TYPE_GLOBAL; - smc_cmd.cmd_id = cmd; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); - smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; - - if (tc_ns_smc(&smc_cmd)) { - ret = -EIO; - tloge("trace cmd 0x%x failed\n", cmd); - } - if (cmd_buffer != NULL) - mailbox_free(cmd_buffer); - mailbox_free(mb_pack); - - return ret; -} - -static void free_event_mem(void) -{ - uint32_t i; - - (void)memset_s(g_event_mem, TRACE_MEM_SIZE, 0, TRACE_MEM_SIZE); - - for (i = 0; i < NR_CPUS; i++) { - if (g_stream_pages[i] != NULL) { - __free_pages(g_stream_pages[i], get_order(TRACE_STREAM_SIZE)); - g_stream_pages[i] = NULL; - } - } - - __free_pages(g_event_pages, get_order(TRACE_MEM_SIZE)); - g_event_mem = NULL; -} - -static int init_event_mem(void) -{ - uint32_t i; - int ret; - - g_event_pages = koadpt_alloc_pages(GFP_KERNEL, get_order(TRACE_MEM_SIZE)); - if (g_event_pages == NULL) { - tloge("alloc event mem (size 0x%lx) failed\n", TRACE_MEM_SIZE); - return -ENOMEM; - } - - g_event_mem = page_address(g_event_pages); - (void)memset_s(g_event_mem, TRACE_MEM_SIZE, 0, TRACE_MEM_SIZE); - - for (i = 0; i < NR_CPUS; i++) { - g_stream_pages[i] = - koadpt_alloc_pages(GFP_KERNEL, get_order(TRACE_STREAM_SIZE)); - if (!g_stream_pages[i]) { - tloge("alloc stream mem (size 0x%lx) failed\n", TRACE_STREAM_SIZE); - ret = -ENOMEM; - goto clean; - } - g_event_mem->streams[i] = page_address(g_stream_pages[i]); - } - - for (i = 0; i < TEE_EVENT_MAX; i++) - g_event_mem->enable[i] = view_state[i].enable; - - g_event_mem->trace_task = ARRAY_SIZE(trace_task); - for (i = 0; i < ARRAY_SIZE(trace_task); i++) - if (strcpy_s(g_event_mem->trace_task_name[i], TEE_TASK_NAME_LEN, - trace_task[i]) != EOK) { - tloge("task name %s too long\n", trace_task[i]); - ret = -EINVAL; - goto clean; - } - g_event_mem->freq = arch_timer_get_cntfrq(); - for (i = 0; i < NR_CPUS; i++) - g_event_mem->streams[i]->total = TEE_TRACE_EVENT_NUM; - - return 0; -clean: - free_event_mem(); - return ret; -} - -int tee_trace_event_enable(void) -{ - int ret; - - if (g_event_mem != NULL) - return 0; - - ret = init_event_mem(); - if (ret != 0) - return ret; - - ret = tee_trace_event_send_cmd(GLOBAL_CMD_ID_TRACE_ENABLE); - if (ret != 0) { - free_event_mem(); - tloge("register tee trace mem failed\n"); - return ret; - } - return 0; -} - -int tee_trace_event_start(void) -{ - uint32_t cpu; - - if (g_event_mem == NULL) - return 0; - - for (cpu = 0;cpu < NR_CPUS; cpu++) { - g_event_mem->streams[cpu]->cur = 0; - (void)memset_s(g_event_mem->streams[cpu]->events, - sizeof(struct tee_trace_event_t) * TEE_TRACE_EVENT_NUM, 0, - sizeof(struct tee_trace_event_t) * TEE_TRACE_EVENT_NUM); - } - g_event_mem->start = true; - smp_mb(); - - return 0; -} - -int tee_trace_event_stop(void) -{ - if (g_event_mem == NULL || !g_event_mem->start) - return 0; - g_event_mem->start = false; - smp_mb(); - return 0; -} - -void get_tee_trace_start(struct tee_trace_view_t *view) -{ - uint32_t i; - - if (g_event_mem == NULL || view == NULL) - return; - - for (i = 0; i < NR_CPUS; i++) { - uint64_t time = g_event_mem->streams[i]->events[0].time; - if (time != 0 && (view->start == 0 || view->start > time)) - view->start = time; - view->total += g_event_mem->streams[i]->cur; - view->end[i] = g_event_mem->streams[i]->cur; - view->at[i] = 0; - } -} - -int get_tee_trace_next(struct tee_trace_view_t *view, uint32_t *event_id, - const char **event_name, uint32_t *cpu, uint32_t *ca_pid, - uint64_t *time, uint64_t *add_info) -{ - uint32_t i; - int32_t index = -1; - uint64_t first = 0; - struct tee_trace_event_t *event = NULL; - - if (g_event_mem == NULL || !g_event_mem->start || view == NULL) - return -1; - - for (i = 0; i < NR_CPUS; i++) { - if (view->at[i] < view->end[i]) { - if (index == -1 || - first > g_event_mem->streams[i]->events[view->at[i]].time) { - first = g_event_mem->streams[i]->events[view->at[i]].time; - index = i; - } - } - } - if (index == -1) - return -1; - - event = &g_event_mem->streams[index]->events[view->at[index]]; - *event_id = event->id; - *event_name = view_state[event->id].name; - *cpu = (uint32_t)index; - *ca_pid = event->ca_pid; - *time = (event->time - view->start) * USEC_PER_SEC / g_event_mem->freq; - *add_info = event->add_info; - view->at[index]++; - - return 0; -} - -const char *get_tee_trace_task_name(uint32_t task_idx) -{ - if (task_idx >= ARRAY_SIZE(trace_task)) - return NULL; - return trace_task[task_idx]; -} \ No newline at end of file diff --git a/core/teek_app_load.c b/core/teek_app_load.c index 68723eabae4aa5fdaba0074312ef9f0c45bdbc26..924675990399cc90dbcf1daa69df29c40d812572 100644 --- a/core/teek_app_load.c +++ b/core/teek_app_load.c @@ -41,7 +41,6 @@ static int32_t teek_open_app_file(struct file *fp, char **file_buf, uint32_t tot } read_size = (uint32_t)kernel_read(fp, file_buffer, total_img_len, &pos); - if (read_size != total_img_len) { tloge("read ta file failed, read size/total size=%u/%u\n", read_size, total_img_len); vfree(file_buffer); @@ -64,6 +63,12 @@ static int32_t teek_read_app(const char *load_file, char **file_buf, uint32_t *f return TEEC_ERROR_BAD_PARAMETERS; } + if (!fp->f_inode) { + tloge("node is NULL\n"); + filp_close(fp, 0); + return TEEC_ERROR_BAD_PARAMETERS; + } + *file_len = (uint32_t)(fp->f_inode->i_size); ret = teek_open_app_file(fp, file_buf, *file_len); @@ -90,8 +95,8 @@ int32_t teek_get_app(const char *ta_path, char **file_buf, uint32_t *file_len) { int32_t ret; - /* ta path is NULL or user CA means no need to load TA */ - if (!ta_path || current->mm != NULL) + /* ta path is NULL means no need to load TA */ + if (!ta_path) return TEEC_SUCCESS; if (!file_buf || !file_len) { diff --git a/core/teek_client_api.c b/core/teek_client_api.c index d641e9bef8c03ad47e0a7b33604ae6105ec9bd85..0c6879390410e23f78c61bcf0f824c7c5d0790eb 100644 --- a/core/teek_client_api.c +++ b/core/teek_client_api.c @@ -29,10 +29,10 @@ #include #include #include -#include "teek_client_id.h" #include "tc_ns_log.h" #include "tc_ns_client.h" #include "gp_ops.h" +#include "internal_functions.h" #include "session_manager.h" #include "tc_client_driver.h" #include "teek_app_load.h" @@ -42,33 +42,31 @@ static void encode_for_part_mem(struct tc_ns_client_context *context, { uint32_t diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT - (uint32_t)TEEC_MEMREF_TEMP_INPUT; + uint64_t size_addr, buffer_addr; if (idex >= TEE_PARAM_NUM) return; if (param_type[idex] == TEEC_MEMREF_WHOLE) { context->params[idex].memref.offset = 0; - context->params[idex].memref.size_addr = - (__u64)(uintptr_t) - (&(oper->params[idex].memref.parent->size)); + size_addr = (__u64)(uintptr_t)(&(oper->params[idex].memref.parent->size)); } else { - context->params[idex].memref.offset = - oper->params[idex].memref.offset; - context->params[idex].memref.size_addr = - (__u64)(uintptr_t) - (&(oper->params[idex].memref.size)); + context->params[idex].memref.offset = oper->params[idex].memref.offset; + size_addr = (__u64)(uintptr_t)(&(oper->params[idex].memref.size)); } + context->params[idex].memref.size_addr = (__u32)size_addr; + context->params[idex].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM); + if (oper->params[idex].memref.parent->is_allocated) { - context->params[idex].memref.buffer = - (__u64)(uintptr_t) - oper->params[idex].memref.parent->buffer; + buffer_addr = (__u64)(uintptr_t)oper->params[idex].memref.parent->buffer; } else { - context->params[idex].memref.buffer = - (__u64)(uintptr_t) + buffer_addr = (__u64)(uintptr_t) oper->params[idex].memref.parent->buffer + oper->params[idex].memref.offset; context->params[idex].memref.offset = 0; } + context->params[idex].memref.buffer = (__u32)buffer_addr; + context->params[idex].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM); /* translate the paramType to know the driver */ if (param_type[idex] == TEEC_MEMREF_WHOLE) { @@ -98,6 +96,7 @@ static uint32_t proc_teek_encode(struct tc_ns_client_context *cli_context, { uint32_t param_type[TEE_PARAM_NUM]; uint32_t idex; + uint64_t buffer_addr, size_addr, a_addr, b_addr; param_type[0] = teec_param_type_get(operation->paramtypes, 0); @@ -109,29 +108,29 @@ static uint32_t proc_teek_encode(struct tc_ns_client_context *cli_context, teec_param_type_get(operation->paramtypes, 3); for (idex = 0; idex < TEE_PARAM_NUM; idex++) { if (is_tmp_mem(param_type[idex])) { - cli_context->params[idex].memref.buffer = - (__u64)(uintptr_t) - (operation->params[idex].tmpref.buffer); - cli_context->params[idex].memref.size_addr = - (__u64)(uintptr_t) - (&operation->params[idex].tmpref.size); + buffer_addr = (__u64)(uintptr_t)(operation->params[idex].tmpref.buffer); + size_addr = (__u64)(uintptr_t)(&operation->params[idex].tmpref.size); + cli_context->params[idex].memref.buffer = (__u32)buffer_addr; + cli_context->params[idex].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM); + cli_context->params[idex].memref.size_addr = (__u32)size_addr; + cli_context->params[idex].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM); } else if (is_ref_mem(param_type[idex])) { encode_for_part_mem(cli_context, operation, idex, param_type); } else if (is_val_param(param_type[idex])) { - cli_context->params[idex].value.a_addr = - (__u64)(uintptr_t) - (&(operation->params[idex].value.a)); - cli_context->params[idex].value.b_addr = - (__u64)(uintptr_t) - (&(operation->params[idex].value.b)); + a_addr = (__u64)(uintptr_t)(&(operation->params[idex].value.a)); + b_addr = (__u64)(uintptr_t)(&(operation->params[idex].value.b)); + cli_context->params[idex].value.a_addr = (__u32)a_addr; + cli_context->params[idex].value.a_h_addr = (__u32)(a_addr >> ADDR_TRANS_NUM); + cli_context->params[idex].value.b_addr = (__u32)b_addr; + cli_context->params[idex].value.b_h_addr = (__u32)(b_addr >> ADDR_TRANS_NUM); } else if (is_ion_param(param_type[idex])) { - cli_context->params[idex].value.a_addr = - (__u64)(uintptr_t) - (&(operation->params[idex].ionref.ion_share_fd)); - cli_context->params[idex].value.b_addr = - (__u64)(uintptr_t) - (&(operation->params[idex].ionref.ion_size)); + a_addr = (__u64)(uintptr_t)(&(operation->params[idex].ionref.ion_share_fd)); + b_addr = (__u64)(uintptr_t)(&(operation->params[idex].ionref.ion_size)); + cli_context->params[idex].value.a_addr = (__u32)a_addr; + cli_context->params[idex].value.a_h_addr = (__u32)(a_addr >> ADDR_TRANS_NUM); + cli_context->params[idex].value.b_addr = (__u32)b_addr; + cli_context->params[idex].value.b_h_addr = (__u32)(b_addr >> ADDR_TRANS_NUM); } else if (param_type[idex] == TEEC_NONE) { /* do nothing */ } else { @@ -157,7 +156,7 @@ static uint32_t teek_init_context(struct tc_ns_client_context *cli_context, (uint32_t)TEEC_MEMREF_TEMP_INPUT; if (memset_s(cli_context, sizeof(*cli_context), - 0x00, sizeof(*cli_context))) { + 0x00, sizeof(*cli_context)) != 0) { tloge("memset error, init cli context failed\n"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -165,7 +164,7 @@ static uint32_t teek_init_context(struct tc_ns_client_context *cli_context, cli_context->returns.origin = TEEC_ORIGIN_COMMS; if (memcpy_s(cli_context->uuid, sizeof(cli_context->uuid), - (uint8_t *)&service_id, sizeof(service_id))) { + (uint8_t *)&service_id, sizeof(service_id)) != 0) { tloge("memcpy error, init cli context failed\n"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -181,7 +180,7 @@ static uint32_t teek_init_context(struct tc_ns_client_context *cli_context, static uint32_t teek_check_tmp_mem( const struct teec_tempmemory_reference *tmpref) { - if (!tmpref->buffer || !tmpref->size) { + if (!tmpref->buffer || (tmpref->size == 0)) { tloge("tmpref buffer is null, or size is zero\n"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -219,15 +218,15 @@ static uint32_t teek_check_ref_mem( return TEEC_ERROR_BAD_PARAMETERS; } if (param_type == TEEC_MEMREF_PARTIAL_INPUT) { - if (!(memref->parent->flags & TEEC_MEM_INPUT)) + if ((memref->parent->flags & TEEC_MEM_INPUT) == 0) return TEEC_ERROR_BAD_PARAMETERS; } else if (param_type == TEEC_MEMREF_PARTIAL_OUTPUT) { - if (!(memref->parent->flags & TEEC_MEM_OUTPUT)) + if ((memref->parent->flags & TEEC_MEM_OUTPUT) == 0) return TEEC_ERROR_BAD_PARAMETERS; } else if (param_type == TEEC_MEMREF_PARTIAL_INOUT) { - if (!(memref->parent->flags & TEEC_MEM_INPUT)) + if ((memref->parent->flags & TEEC_MEM_INPUT) == 0) return TEEC_ERROR_BAD_PARAMETERS; - if (!(memref->parent->flags & TEEC_MEM_OUTPUT)) + if ((memref->parent->flags & TEEC_MEM_OUTPUT) == 0) return TEEC_ERROR_BAD_PARAMETERS; } else if (param_type == TEEC_MEMREF_WHOLE) { /* if type is TEEC_MEMREF_WHOLE, ignore it */ @@ -262,7 +261,7 @@ uint32_t teek_check_operation(const struct teec_operation *operation) if (!operation) return TEEC_SUCCESS; - if (!operation->started) { + if (operation->started == 0) { tloge("sorry, cancellation not support\n"); return TEEC_ERROR_NOT_IMPLEMENTED; } @@ -392,11 +391,18 @@ static bool is_oper_param_valid(const struct teec_operation *operation) } static uint32_t check_open_sess_params(struct teec_context *context, - const struct teec_operation *operation) + const struct teec_operation *operation, const struct teec_uuid *destination, + uint32_t connection_method) { struct tc_ns_dev_file *dev_file = NULL; uint32_t teec_ret; + if (!context || !operation || !destination || + connection_method != TEEC_LOGIN_IDENTIFY) { + tloge("invalid input params\n"); + return TEEC_ERROR_BAD_PARAMETERS; + } + if (!is_oper_param_valid(operation)) return TEEC_ERROR_BAD_PARAMETERS; @@ -411,13 +417,13 @@ static uint32_t check_open_sess_params(struct teec_context *context, return TEEC_ERROR_BAD_PARAMETERS; } else { if (memset_s(dev_file->pkg_name, sizeof(dev_file->pkg_name), - 0, MAX_PACKAGE_NAME_LEN)) { + 0, MAX_PACKAGE_NAME_LEN) != 0) { tloge("memset error\n"); return TEEC_ERROR_BAD_PARAMETERS; } if (memcpy_s(dev_file->pkg_name, sizeof(dev_file->pkg_name), operation->params[3].tmpref.buffer, - operation->params[3].tmpref.size)) { + operation->params[3].tmpref.size) != 0) { tloge("memcpy error\n"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -442,7 +448,7 @@ static uint32_t open_session_and_switch_ret(struct teec_session *session, uint32_t teec_ret; ret = tc_ns_open_session(context->dev, cli_context); - if (!ret) { + if (ret == 0) { tlogd("open session success\n"); session->session_id = cli_context->session_id; session->service_id = *destination; @@ -483,6 +489,7 @@ static uint32_t proc_teek_open_session(struct teec_context *context, struct tc_ns_client_context cli_context; struct tc_ns_client_login cli_login = {0}; bool load_app_flag = false; + char *file_buffer = NULL; /* connectionData current not used */ (void)(connection_data); @@ -490,15 +497,21 @@ static uint32_t proc_teek_open_session(struct teec_context *context, *return_origin = origin; /* First, check parameters is valid or not */ - if (!context || !operation || !destination || - !session || connection_method != TEEC_LOGIN_IDENTIFY) { - tloge("invalid input params\n"); + if (!session) { + tloge("invalid session\n"); teec_ret = TEEC_ERROR_BAD_PARAMETERS; goto set_ori; } + /* + * ca may call closesession even if opensession failed, + * we set session->context here to avoid receive a illegal ptr, + * same as libteec_vendor + */ + session->context = context; + cli_login.method = TEEC_LOGIN_IDENTIFY; - teec_ret = check_open_sess_params(context, operation); + teec_ret = check_open_sess_params(context, operation, destination, connection_method); if (teec_ret != TEEC_SUCCESS) goto set_ori; @@ -515,20 +528,24 @@ static uint32_t proc_teek_open_session(struct teec_context *context, goto set_ori; } - teec_ret = teek_get_app(context->ta_path, &cli_context.file_buffer, + teec_ret = (uint32_t)teek_get_app(context->ta_path, &file_buffer, &cli_context.file_size); if (teec_ret != TEEC_SUCCESS) goto set_ori; + cli_context.memref.file_addr = (uint32_t)(uintptr_t)file_buffer; + cli_context.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)file_buffer) >> ADDR_TRANS_NUM); load_app_flag = true; + livepatch_down_read_sem(); teec_ret = open_session_and_switch_ret(session, context, destination, &cli_context, &origin); + livepatch_up_read_sem(); set_ori: if (teec_ret != TEEC_SUCCESS && return_origin != NULL) *return_origin = origin; - teek_free_app(load_app_flag, &cli_context.file_buffer); + teek_free_app(load_app_flag, &file_buffer); return teec_ret; } @@ -556,7 +573,7 @@ EXPORT_SYMBOL(teek_open_session); * This function closes an opened Session. */ -static bool is_close_sess_param_valid(struct teec_session *session) +static bool is_close_sess_param_valid(const struct teec_session *session) { tlogd("teek_close_session started\n"); @@ -583,14 +600,14 @@ void teek_close_session(struct teec_session *session) tloge("init cli context failed just return\n"); return; } - + livepatch_down_read_sem(); ret = tc_ns_close_session(session->context->dev, &cli_context); - if (!ret) { + livepatch_up_read_sem(); + if (ret == 0) { session->session_id = 0; if (memset_s((uint8_t *)(&session->service_id), - sizeof(session->service_id), 0x00, UUID_LEN)) + sizeof(session->service_id), 0x00, UUID_LEN) != 0) tloge("memset error\n"); - session->ops_cnt = 0; session->context = NULL; } else { @@ -605,8 +622,11 @@ static uint32_t proc_invoke_cmd(struct teec_session *session, int32_t ret; uint32_t teec_ret; + livepatch_down_read_sem(); ret = tc_ns_send_cmd(session->context->dev, cli_context); - if (!ret) { + livepatch_up_read_sem(); + + if (ret == 0) { tlogd("invoke cmd success\n"); teec_ret = TEEC_SUCCESS; } else if (ret < 0) { @@ -646,7 +666,7 @@ uint32_t teek_invoke_command(struct teec_session *session, uint32_t cmd_id, } teec_ret = teek_check_operation(operation); - if (teec_ret) { + if (teec_ret != 0) { tloge("operation is invalid\n"); goto set_ori; } @@ -654,7 +674,7 @@ uint32_t teek_invoke_command(struct teec_session *session, uint32_t cmd_id, /* Paramters all right, start execution */ teec_ret = teek_init_context(&cli_context, session->service_id, session->session_id, cmd_id, &cli_login); - if (teec_ret) { + if (teec_ret != 0) { tloge("init cli context failed\n"); goto set_ori; } @@ -663,7 +683,7 @@ uint32_t teek_invoke_command(struct teec_session *session, uint32_t cmd_id, if (operation) { cli_context.started = operation->cancel_flag; teec_ret = proc_teek_encode(&cli_context, operation); - if (teec_ret) { + if (teec_ret != 0) { goto set_ori; } } @@ -671,7 +691,7 @@ uint32_t teek_invoke_command(struct teec_session *session, uint32_t cmd_id, teec_ret = proc_invoke_cmd(session, &cli_context, &origin); set_ori: - if (teec_ret && return_origin) + if ((teec_ret != 0) && return_origin) *return_origin = origin; return teec_ret; } @@ -680,14 +700,18 @@ EXPORT_SYMBOL(teek_invoke_command); uint32_t teek_send_secfile(struct teec_session *session, const char *file_buffer, unsigned int file_size) { - if (!file_buffer || !file_size || !session || + uint32_t ret; + + if (!file_buffer || (file_size == 0) || !session || !session->context || !session->context->dev) { tloge("params error!\n"); return TEEC_ERROR_BAD_PARAMETERS; } - - return (uint32_t)tc_ns_load_image_with_lock(session->context->dev, - file_buffer, file_size, LOAD_TA); + livepatch_down_read_sem(); + ret = (uint32_t)tc_ns_load_image_with_lock(session->context->dev, + file_buffer, file_size, LOAD_TA); + livepatch_up_read_sem(); + return ret; } EXPORT_SYMBOL(teek_send_secfile); @@ -706,6 +730,8 @@ EXPORT_SYMBOL(TEEK_SendSecfile); uint32_t teek_register_shared_memory(struct teec_context *context, struct teec_sharedmemory *sharedmem) { + (void)context; + (void)sharedmem; tloge("teek_register_shared_memory not supported\n"); return TEEC_ERROR_NOT_SUPPORTED; } @@ -750,7 +776,7 @@ TEEC_Result TEEK_OpenSession(TEEC_Context *context, TEEC_Session *session, { return (TEEC_Result)teek_open_session( (struct teec_context *)context, (struct teec_session *)session, - (struct teec_uuid *)destination, connectionMethod, connectionData, + (const struct teec_uuid *)destination, connectionMethod, connectionData, (struct teec_operation *)operation, returnOrigin); } EXPORT_SYMBOL(TEEK_OpenSession); diff --git a/core/tz_pm.c b/core/tz_pm.c index 654fc7e8eba0994d979f989b1492f535d0095740..9fdfb80644fc22c4baea4c179d2280fb7ccdd2e5 100644 --- a/core/tz_pm.c +++ b/core/tz_pm.c @@ -47,7 +47,7 @@ static void *tc_vmap(phys_addr_t paddr, size_t size) offset = paddr & ~PAGE_MASK; paddr &= PAGE_MASK; - pages_count = PAGE_ALIGN(size + offset) / PAGE_SIZE; + pages_count = (uint32_t)(PAGE_ALIGN(size + offset) / PAGE_SIZE); pages = kzalloc(sizeof(struct page *) * pages_count, GFP_KERNEL); if (pages == NULL) @@ -67,6 +67,7 @@ static void *tc_vmap(phys_addr_t paddr, size_t size) static int tc_s4_alloc_crypto_buffer(struct device *dev, char **kernel_mem_addr) { + (void)dev; if (RESERVED_SECOS_S4_BASE > S4_ADDR_4G) { tloge("addr is invalid\n"); return -EFAULT; @@ -260,13 +261,14 @@ static int tc_s4_transfer_data(char *kernel_mem_addr, uint32_t crypt_op) } static int tc_s4_pm_ops(struct device *dev, uint32_t power_op, - uint32_t crypt_op, char *kernel_mem_addr) + uint32_t crypt_op, char *kernel_mem_addr) { int ret; + (void)dev; - if (power_op == TSP_S4_SUSPEND) + if (power_op == TSP_S4_SUSPEND) g_s4_kernel_mem_addr = kernel_mem_addr; - else + else kernel_mem_addr = g_s4_kernel_mem_addr; isb(); @@ -274,7 +276,7 @@ static int tc_s4_pm_ops(struct device *dev, uint32_t power_op, /* notify TEEOS to suspend all pm driver */ if (power_op == TSP_S4_SUSPEND) { - ret = tc_s4_suspend_or_resume(power_op); + ret = (int)tc_s4_suspend_or_resume(power_op); if (ret != 0) { tloge("tc s4 suspend failed\n"); return ret; @@ -282,14 +284,14 @@ static int tc_s4_pm_ops(struct device *dev, uint32_t power_op, } ret = tc_s4_transfer_data(kernel_mem_addr, crypt_op); - if (ret != 0){ + if (ret != 0) { tloge("transfer data failed, power_op=0x%x\n", power_op); return ret; } /* notify TEEOS to resume all pm driver */ if (power_op == TSP_S4_RESUME) { - ret = tc_s4_suspend_or_resume(power_op); + ret = (int)tc_s4_suspend_or_resume(power_op); if (ret != 0) { tloge("tc s4 resume failed\n"); return ret; @@ -315,6 +317,7 @@ int tc_s4_pm_suspend(struct device *dev) free_resource(kernel_mem_addr); tloge("s4 suspend failed\n"); } + return ret; } @@ -325,7 +328,7 @@ int tc_s4_pm_resume(struct device *dev) ret = tc_s4_pm_ops(dev, TSP_S4_RESUME, TSP_S4_DECRYPT_AND_COPY, g_s4_kernel_mem_addr); if (ret != 0) tloge("s4 resume failed\n"); - + free_resource(g_s4_kernel_mem_addr); return ret; } diff --git a/core/tz_spi_notify.c b/core/tz_spi_notify.c index edf4cc7998556eb89456a25de7ac69c8e3e3b597..587ef497c50c98b1a33e3074b135656841c4ef91 100644 --- a/core/tz_spi_notify.c +++ b/core/tz_spi_notify.c @@ -43,7 +43,8 @@ #include "mailbox_mempool.h" #include "smc_smp.h" #include "session_manager.h" -#include "tz_kthread_affinity.h" +#include "internal_functions.h" +#include "shared_mem.h" #define DEFAULT_SPI_NUM 111 @@ -128,7 +129,7 @@ union notify_context { struct notify_data_entry { uint32_t entry_type : 31; - uint32_t filled : 1; + uint32_t filled : 1; union notify_context context; }; @@ -192,7 +193,7 @@ static void walk_callback_list( list_for_each_entry(callback_func_t, &g_ta_callback_func_list.callback_list, head) { if (memcmp(callback_func_t->uuid, tc_notify_data_timer->uuid, - UUID_SIZE)) + UUID_SIZE) != 0) continue; if (tc_notify_data_timer->property.timer_class == @@ -234,10 +235,10 @@ static int find_notify_sess( temp_svc = tc_find_service_in_dev(temp_dev_file, tc_notify_data_timer->uuid, UUID_LEN); + get_service_struct(temp_svc); mutex_unlock(&temp_dev_file->service_lock); if (!temp_svc) break; - get_service_struct(temp_svc); mutex_lock(&temp_svc->session_lock); *temp_ses = tc_find_session_withowner( @@ -275,7 +276,7 @@ static void tc_notify_timer_fn(struct notify_data_entry *notify_data_entry) tc_notify_data_timer->property.timer_id); walk_callback_list(tc_notify_data_timer); - if (find_notify_sess(tc_notify_data_timer, &temp_ses, &enc_found)) + if (find_notify_sess(tc_notify_data_timer, &temp_ses, &enc_found) != 0) return; if (tc_notify_data_timer->property.timer_class == TIMER_GENERIC) { @@ -308,7 +309,7 @@ static noinline int get_notify_data_entry(struct notify_data_entry *copy) struct notify_data_entry *e = &g_notify_data->entry[i]; filled = e->filled; smp_mb(); - if (!filled) + if (filled == 0) continue; switch (e->entry_type) { case NOTIFY_DATA_ENTRY_TIMER: @@ -381,7 +382,7 @@ static void tc_notify_shadowexit_fn(const struct notify_data_entry *entry) const struct notify_context_wakeup *tc_notify_wakeup = NULL; tc_notify_wakeup = &(entry->context.wakeup); - if (smc_shadow_exit(tc_notify_wakeup->ca_thread_id)) + if (smc_shadow_exit(tc_notify_wakeup->ca_thread_id) != 0) tloge("shadow ca exit failed: %d\n", (int)tc_notify_wakeup->ca_thread_id); } @@ -442,25 +443,26 @@ static void spi_broadcast_notifications(void) return; } - missed = __xchg(0, &g_notify_data->meta.context.meta.missed, + missed = (uint32_t)__xchg(0, &g_notify_data->meta.context.meta.missed, MISSED_COUNT); - if (!missed) + if (missed == 0) return; - if (missed & (1U << NOTIFY_DATA_ENTRY_WAKEUP)) { + if ((missed & (1U << NOTIFY_DATA_ENTRY_WAKEUP)) != 0) { smc_wakeup_broadcast(); missed &= ~(1U << NOTIFY_DATA_ENTRY_WAKEUP); } - if (missed & (1U << NOTIFY_DATA_ENTRY_FIQSHD)) { + if ((missed & (1U << NOTIFY_DATA_ENTRY_FIQSHD)) != 0) { tc_notify_fiqshd_fn(NULL); missed &= ~(1U << NOTIFY_DATA_ENTRY_FIQSHD); } - if (missed) + if (missed != 0) tloge("missed spi notification mask %x\n", missed); } static void tc_notify_fn(struct work_struct *dummy) { struct notify_data_entry copy = {0}; + (void)dummy; while (get_notify_data_entry(©) == 0) { switch (copy.entry_type) { @@ -488,7 +490,7 @@ static void tc_notify_fn(struct work_struct *dummy) default: tloge("invalid entry type = %u\n", copy.entry_type); } - if (memset_s(©, sizeof(copy), 0, sizeof(copy))) + if (memset_s(©, sizeof(copy), 0, sizeof(copy)) != 0) tloge("memset copy failed\n"); } spi_broadcast_notifications(); @@ -498,18 +500,26 @@ static irqreturn_t tc_secure_notify(int irq, void *dev_id) { #define N_WORK 8 int i; + int queued = 0; static struct work_struct tc_notify_works[N_WORK]; static int init; + (void)dev_id; - if (!init) { + if (init == 0) { for (i = 0; i < N_WORK; i++) INIT_WORK(&tc_notify_works[i], tc_notify_fn); init = 1; } for (i = 0; i < N_WORK; i++) { - if (queue_work(g_tz_spi_wq, &tc_notify_works[i])) + if (queue_work(g_tz_spi_wq, &tc_notify_works[i])) { + queued = 1; break; + } } + if (queued == 1) + tee_trace_add_event(INTERRUPT_HANDLE_SPI_REE_RESPONSE, (uint64_t)irq); + else + tee_trace_add_event(INTERRUPT_HANDLE_SPI_REE_MISS, (uint64_t)irq); #undef N_WORK return IRQ_HANDLED; @@ -534,7 +544,7 @@ int tc_ns_register_service_call_back_func(const char *uuid, void *func, } list_for_each_entry(callback_func, &g_ta_callback_func_list.callback_list, head) { - if (!memcmp(callback_func->uuid, uuid, UUID_SIZE)) { + if (memcmp(callback_func->uuid, uuid, UUID_SIZE) == 0) { callback_func->callback_func = (void (*)(void *))func; tlogd("succeed to find uuid ta_callback_func_list\n"); goto find_callback; @@ -548,7 +558,7 @@ int tc_ns_register_service_call_back_func(const char *uuid, void *func, goto find_callback; } - if (memcpy_s(new_callback->uuid, UUID_SIZE, uuid, UUID_SIZE)) { + if (memcpy_s(new_callback->uuid, UUID_SIZE, uuid, UUID_SIZE) != 0) { kfree(new_callback); new_callback = NULL; ret = -ENOMEM; @@ -583,7 +593,7 @@ int tc_ns_tst_cmd(void *argp) return 0; } -static int send_notify_cmd(unsigned int cmd_id) +int send_notify_cmd(unsigned int cmd_id) { struct tc_ns_smc_cmd smc_cmd = { {0}, 0 }; int ret = 0; @@ -597,27 +607,35 @@ static int send_notify_cmd(unsigned int cmd_id) TEE_PARAM_TYPE_VALUE_INPUT | TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM; mb_pack->operation.params[0].value.a = - virt_to_phys(g_notify_data); - mb_pack->operation.params[0].value.b = (uint64_t)virt_to_phys(g_notify_data) >> ADDR_TRANS_NUM; + (unsigned int)(get_spi_mem_paddr((uintptr_t)g_notify_data)); + mb_pack->operation.params[0].value.b = + (unsigned int)(get_spi_mem_paddr((uintptr_t)g_notify_data) >> ADDR_TRANS_NUM); mb_pack->operation.params[1].value.a = SZ_4K; smc_cmd.cmd_type = CMD_TYPE_GLOBAL; smc_cmd.cmd_id = cmd_id; smc_cmd.operation_phys = - virt_to_phys(&mb_pack->operation); - smc_cmd.operation_h_phys = (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; + (unsigned int)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); + smc_cmd.operation_h_phys = + (unsigned int)((uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM); + + if (is_tee_rebooting()) + ret = send_smc_cmd_rebooting(TSP_REQUEST, 0, 0, &smc_cmd); + else + ret = tc_ns_smc(&smc_cmd); - if (tc_ns_smc(&smc_cmd)) { + if (ret != 0) { ret = -EPERM; tloge("register notify mem failed\n"); } + mailbox_free(mb_pack); return ret; } +static unsigned int g_irq = DEFAULT_SPI_NUM; static int config_spi_context(struct device *class_dev, struct device_node *np) { - unsigned int irq = DEFAULT_SPI_NUM; int ret; #ifndef CONFIG_ACPI @@ -629,14 +647,14 @@ static int config_spi_context(struct device *class_dev, struct device_node *np) /* Map IRQ 0 from the OF interrupts list */ #ifdef CONFIG_ACPI - irq = (unsigned int)get_acpi_tz_irq(); + g_irq = (unsigned int)get_acpi_tz_irq(); #else - irq = irq_of_parse_and_map(np, 0); + g_irq = irq_of_parse_and_map(np, 0); #endif - ret = devm_request_irq(class_dev, irq, tc_secure_notify, + ret = devm_request_irq(class_dev, g_irq, tc_secure_notify, IRQF_NO_SUSPEND, TC_NS_CLIENT_DEV, NULL); if (ret < 0) { - tloge("device irq %u request failed %d", irq, ret); + tloge("device irq %u request failed %d", g_irq, ret); return ret; } @@ -664,19 +682,11 @@ int tz_spi_init(struct device *class_dev, struct device_node *np) tz_workqueue_bind_mask(g_tz_spi_wq, WQ_HIGHPRI); ret = config_spi_context(class_dev, np); - if (ret) + if (ret != 0) goto clean; if (!g_notify_data) { -#ifdef CONFIG_BIG_SESSION - /* we should map at least 3 pages for 100 sessions, 2^2 > 3 */ - g_notify_data = (struct notify_data_struct *) - (uintptr_t)__get_free_pages( - GFP_KERNEL | __GFP_ZERO, CONFIG_NOTIFY_PAGE_ORDER); -#else - g_notify_data = (struct notify_data_struct *) - (uintptr_t)__get_free_page(GFP_KERNEL | __GFP_ZERO); -#endif + g_notify_data = (struct notify_data_struct *)(uintptr_t)get_spi_mem_vaddr(); if (!g_notify_data) { tloge("get free page failed for notification data\n"); ret = -ENOMEM; @@ -684,10 +694,10 @@ int tz_spi_init(struct device *class_dev, struct device_node *np) } ret = send_notify_cmd(GLOBAL_CMD_ID_REGISTER_NOTIFY_MEMORY); - if (ret) { + if (ret != 0) { tloge("shared memory failed ret is 0x%x\n", ret); ret = -EFAULT; - free_page((unsigned long)(uintptr_t)g_notify_data); + free_spi_mem((uint64_t)(uintptr_t)g_notify_data); g_notify_data = NULL; goto clean; } @@ -700,21 +710,14 @@ int tz_spi_init(struct device *class_dev, struct device_node *np) return 0; clean: - tz_spi_exit(); + free_tz_spi(class_dev); return ret; } -void tz_spi_exit(void) +void free_tz_spi(struct device *class_dev) { if (g_notify_data) { - if (send_notify_cmd(GLOBAL_CMD_ID_UNREGISTER_NOTIFY_MEMORY)) - tloge("unregister notify data mem failed\n"); -#ifdef CONFIG_BIG_SESSION - free_pages((unsigned long)(uintptr_t)g_notify_data, - CONFIG_NOTIFY_PAGE_ORDER); -#else - free_page((unsigned long)(uintptr_t)g_notify_data); -#endif + free_spi_mem((uint64_t)(uintptr_t)g_notify_data); g_notify_data = NULL; } @@ -723,4 +726,8 @@ void tz_spi_exit(void) destroy_workqueue(g_tz_spi_wq); g_tz_spi_wq = NULL; } + if (!class_dev) + return; + + devm_free_irq(class_dev, g_irq, NULL); } diff --git a/core/tz_spi_notify.h b/core/tz_spi_notify.h index 712e2808ddccf3859e8c1988fdf495111540e3fc..1722dc365eebdd88940860070a83964b328fb510 100644 --- a/core/tz_spi_notify.h +++ b/core/tz_spi_notify.h @@ -22,7 +22,8 @@ #include "teek_ns_client.h" int tz_spi_init(struct device *class_dev, struct device_node *np); -void tz_spi_exit(void); +void free_tz_spi(struct device *class_dev); int tc_ns_tst_cmd(void *argp); +int send_notify_cmd(unsigned int cmd_id); #endif diff --git a/ko_adapt.c b/ko_adapt.c index d4c9519b9b3b2f22f434d4bd87ba1b3834533d1a..a094b2805adfca6bd396a75afcc15d29d5895e12 100644 --- a/ko_adapt.c +++ b/ko_adapt.c @@ -31,9 +31,7 @@ typedef const struct cred *(get_task_cred_func)(struct task_struct *); typedef void (kthread_bind_mask_func)(struct task_struct *, const struct cpumask *); - typedef struct page *(alloc_pages_func)(gfp_t gfp_mask, unsigned int order); - typedef struct workqueue_attrs *(alloc_workqueue_attrs_func)(gfp_t gfp_mask); typedef void (free_workqueue_attrs_func)(struct workqueue_attrs *attrs); @@ -109,6 +107,7 @@ struct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) struct workqueue_attrs *attrs; + (void)gfp_mask; attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (!attrs) { @@ -116,7 +115,7 @@ struct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask) return NULL; } - if (alloc_cpumask_var(&attrs->cpumask, GFP_KERNEL) != 0) { + if (alloc_cpumask_var(&attrs->cpumask, GFP_KERNEL) == false) { tloge("alloc cpumask var fail\n"); kfree(attrs); return NULL; @@ -143,9 +142,9 @@ struct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask) void koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) - if (!attrs) + if(!attrs) return; - + free_cpumask_var(attrs->cpumask); kfree(attrs); #else diff --git a/ko_adapt.h b/ko_adapt.h index 5148ec381f92bf202efb56e19244412b21f4f3ad..b0a524c896189b392ec453134867129a1bd2335b 100644 --- a/ko_adapt.h +++ b/ko_adapt.h @@ -66,7 +66,7 @@ static inline struct workqueue_attrs *koadpt_alloc_workqueue_attrs( #else (void)gfp_mask; return alloc_workqueue_attrs(); -#endif +#endif } static inline void koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs) diff --git a/tc_ns_client.h b/tc_ns_client.h index 163ed74f9bb1607cd4fe9216b5ead8c5f5fb276f..3d5325287047b407223985f1a433f83fb6e7f5ac 100644 --- a/tc_ns_client.h +++ b/tc_ns_client.h @@ -38,9 +38,9 @@ #endif #if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) -#define mm_sem_lock(mm) mm->mmap_lock +#define mm_sem_lock(mm) (mm)->mmap_lock #else -#define mm_sem_lock(mm) mm->mmap_sem +#define mm_sem_lock(mm) (mm)->mmap_sem #endif struct tc_ns_client_login { @@ -50,18 +50,19 @@ struct tc_ns_client_login { union tc_ns_client_param { struct { - __u64 buffer; - __u64 offset; - __u64 size_addr; + __u32 buffer; + __u32 buffer_h_addr; + __u32 offset; + __u32 h_offset; + __u32 size_addr; + __u32 size_h_addr; } memref; struct { - __u64 a_addr; - __u64 b_addr; + __u32 a_addr; + __u32 a_h_addr; + __u32 b_addr; + __u32 b_h_addr; } value; - struct { - __u64 buffer; - __u64 size_addr; - }sharedmem; }; struct tc_ns_client_return { @@ -82,7 +83,10 @@ struct tc_ns_client_context { unsigned int file_size; union { char *file_buffer; - unsigned long long file_addr; + struct { + uint32_t file_addr; + uint32_t file_h_addr; + } memref; }; }; @@ -96,17 +100,27 @@ enum secfile_type_t { LOAD_SERVICE, LOAD_LIB, LOAD_DYNAMIC_DRV, + LOAD_PATCH, + LOAD_TYPE_MAX, }; -struct load_secfile_ioctl_struct { +struct sec_file_info { enum secfile_type_t secfile_type; - unsigned char uuid[UUID_LEN]; uint32_t file_size; + int32_t sec_load_err; +}; + +struct load_secfile_ioctl_struct { + struct sec_file_info sec_file_info; + unsigned char uuid[UUID_LEN]; union { char *file_buffer; - unsigned long long file_addr; + struct { + uint32_t file_addr; + uint32_t file_h_addr; + } memref; }; -}; +}__attribute__((packed)); struct agent_ioctl_args { uint32_t id; @@ -120,7 +134,10 @@ struct agent_ioctl_args { struct tc_ns_client_crl { union { uint8_t *buffer; - unsigned long long addr; + struct { + uint32_t buffer_addr; + uint32_t buffer_h_addr; + } memref; }; uint32_t size; }; diff --git a/tc_ns_log.h b/tc_ns_log.h index 4d43d3879c5cf9462ed8102a7d159363369b2b69..f69c07a63482fc6a797bc64c67ad59059a3f55fa 100644 --- a/tc_ns_log.h +++ b/tc_ns_log.h @@ -37,32 +37,32 @@ enum { #define tlogv(fmt, args...) \ do { \ if (TZ_DEBUG_VERBOSE >= TEE_LOG_MASK) \ - pr_info("([%s] %i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ + pr_info("[%s] (%i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ } while (0) #define tlogd(fmt, args...) \ do { \ if (TZ_DEBUG_DEBUG >= TEE_LOG_MASK) \ - pr_info("([%s] %i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ + pr_info("[%s] (%i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ } while (0) #define tlogi(fmt, args...) \ do { \ if (TZ_DEBUG_INFO >= TEE_LOG_MASK) \ - pr_info("([%s] %i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ + pr_info("[%s] (%i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ } while (0) #define tlogw(fmt, args...) \ do { \ if (TZ_DEBUG_WARN >= TEE_LOG_MASK) \ - pr_warn("([%s] %i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ + pr_warn("[%s] (%i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args); \ } while (0) #define tloge(fmt, args...) \ - pr_err("([%s] %i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args) + pr_err("[%s] (%i, %s)%s: " fmt, MOD_TEE, current->pid, current->comm, __func__, ## args) #endif diff --git a/teek_client_api.h b/teek_client_api.h index 75c6e172f5dbee66a0987a4af4fa556dc294028a..355b7ab4152638c51271f1e3bca96778bb5d9307 100644 --- a/teek_client_api.h +++ b/teek_client_api.h @@ -18,7 +18,6 @@ #ifndef TEEK_CLIENT_API_H #define TEEK_CLIENT_API_H -#include "teek_ns_client.h" #include "teek_client_type.h" #define TEEC_PARAM_TYPES(param0_type, param1_type, param2_type, param3_type) \ @@ -30,8 +29,6 @@ #define TEEC_VALUE_UNDEF 0xFFFFFFFF -#ifdef CONFIG_KERNEL_CLIENT - /* * for history reason, we supply two set interface * first set is uncapitalized and satisfies kernel code rule @@ -95,88 +92,4 @@ TEEC_Result TEEK_InvokeCommand(TEEC_Session *session, TEEC_Operation *operation, uint32_t *returnOrigin); -#else - -static inline int teek_is_agent_alive(unsigned int agent_id) -{ - return TEEC_SUCCESS; -} - -static inline int TEEK_IsAgentAlive(unsigned int agent_id) -{ - return TEEC_SUCCESS; -} - -static inline uint32_t teek_initialize_context(const char *name, - struct teec_context *context) -{ - return TEEC_SUCCESS; -} - -static inline TEEC_Result TEEK_InitializeContext(const char *name, - TEEC_Context *context) -{ - return TEEC_SUCCESS; -} - -static inline void teek_finalize_context(struct teec_context *context) -{ - (void)context; -} - -static inline void TEEK_FinalizeContext(TEEC_Context *context) -{ - (void)context; -} - -static inline uint32_t teek_open_session(struct teec_context *context, - struct teec_session *session, - const struct teec_uuid *destination, - uint32_t connection_method, - const void *connection_data, - const struct teec_operation *operation, - uint32_t *return_origin) -{ - return TEEC_SUCCESS; -} - -static inline TEEC_Result TEEK_OpenSession(TEEC_Context *context, - TEEC_Session *session, const TEEC_UUID *destination, - uint32_t connectionMethod, const void *connectionData, - TEEC_Operation *operation, uint32_t *returnOrigin) -{ - return TEEC_SUCCESS; -} - -static inline void teek_close_session(struct teec_session *session) -{ - (void)session; -} - -static inline void TEEK_CloseSession(TEEC_Session *session) -{ - (void)session; -} - -static inline uint32_t teek_invoke_command(struct teec_session *session, - uint32_t cmd_id, struct teec_operation *operation, - uint32_t *return_origin) -{ - return TEEC_SUCCESS; -} - -static inline TEEC_Result TEEK_InvokeCommand(TEEC_Session *session, - uint32_t commandID, TEEC_Operation *operation, uint32_t *returnOrigin) -{ - return TEEC_SUCCESS; -} - -static inline uint32_t teek_send_secfile(struct teec_session *session, - const char *file_buffer, unsigned int file_size) -{ - return TEEC_SUCCESS; -} - -#endif - #endif diff --git a/teek_client_constants.h b/teek_client_constants.h index 1b508cc1877e43e719426d0d9c961f5cceaf7ed5..652c120c839a06c49b293a2959675bdc296e8e5b 100644 --- a/teek_client_constants.h +++ b/teek_client_constants.h @@ -15,7 +15,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include #ifndef TEEK_CLIENT_CONSTANTS_H #define TEEK_CLIENT_CONSTANTS_H @@ -109,6 +108,7 @@ enum teec_result { TEEC_ERROR_SEC_FLASH_NOT_AVAILABLE, TEEC_ERROR_CA_AUTH_FAIL = 0xFFFFCFE5, TEE_ERROR_AUDIT_FAIL = 0xFFFF9112, + TEE_ERROR_IS_DEAD = 0xFFFFABAB, }; enum TEEC_ReturnCodeOrigin { @@ -134,7 +134,7 @@ enum TEEC_ParamType { TEEC_MEMREF_TEMP_INOUT = 0x07, TEEC_ION_INPUT = 0x08, TEEC_ION_SGLIST_INPUT = 0x09, - TEEC_MEMREF_SHARED_INOUT = 0xa, + TEEC_MEMREF_SHARED_INOUT = 0x0a, TEEC_MEMREF_WHOLE = 0xc, TEEC_MEMREF_PARTIAL_INPUT = 0xd, TEEC_MEMREF_PARTIAL_OUTPUT = 0xe, @@ -151,7 +151,7 @@ enum TEE_ParamType { TEE_PARAM_TYPE_MEMREF_INOUT = 0x7, TEE_PARAM_TYPE_ION_INPUT = 0x8, TEE_PARAM_TYPE_ION_SGLIST_INPUT = 0x9, - TEE_PARAM_TYPE_MEMREF_SHARED_INOUT = 0xa, + TEE_PARAM_TYPE_MEMREF_SHARED_INOUT = 0x0a, TEE_PARAM_TYPE_RESMEM_INPUT = 0xc, TEE_PARAM_TYPE_RESMEM_OUTPUT = 0xd, TEE_PARAM_TYPE_RESMEM_INOUT = 0xe @@ -165,7 +165,35 @@ enum TEEC_LoginMethod { TEEC_LOGIN_USER_APPLICATION = 0x5, TEEC_LOGIN_GROUP_APPLICATION = 0x6, TEEC_LOGIN_IDENTIFY = 0x7, - TEEK_LOGIN_IDENTIFY = 0x80000001 + TEEK_LOGIN_IDENTIFY = 0x80000001, }; +/* Add event id's name in 'view_state[]' in same order */ +enum tee_event_id { + INVOKE_CMD_START, + INVOKE_CMD_END, + SMC_SEND, + SMC_DONE, + SMC_IN, + SMC_OUT, + SMC_SLEEP, + SMC_PREEMPT, + GTASK_GET_CMD, + GTASK_PUT_CMD, + GTASK_REQ_TA, + GTASK_RESP_TA, + SPI_WAKEUP, + SCHED_IN, + SCHED_OUT, + INTERRUPT_HANDLE_SPI_START, + INTERRUPT_HANDLE_SPI_REE_RESPONSE, + INTERRUPT_HANDLE_SPI_REE_MISS, + INTERRUPT_HANDLE_SPI_REE_SCHEDULED, + INTERRUPT_HANDLE_SPI_END, + INTERRUPT_HANDLE_START, + INTERRUPT_HANDLE_END, + TEE_EVENT_MAX +}; + +#define TZ_WQ_MAX_ACTIVE 1 #endif diff --git a/teek_client_type.h b/teek_client_type.h index 1588e1abee631a82f8e4c83b492767b7b257ba3e..b75976a016198715da1794c8c2e6f038c5dc7296 100644 --- a/teek_client_type.h +++ b/teek_client_type.h @@ -47,7 +47,7 @@ struct teec_session { struct teec_sharedmemory { void *buffer; - size_t size; + uint32_t size; uint32_t flags; uint32_t ops_cnt; bool is_allocated; @@ -57,13 +57,13 @@ struct teec_sharedmemory { struct teec_tempmemory_reference { void *buffer; - size_t size; + uint32_t size; }; struct teec_registeredmemory_reference { struct teec_sharedmemory *parent; - size_t size; - size_t offset; + uint32_t size; + uint32_t offset; }; @@ -74,7 +74,7 @@ struct teec_value { struct teec_ion_reference { int ion_share_fd; - size_t ion_size; + uint32_t ion_size; }; union teec_parameter { @@ -94,79 +94,23 @@ struct teec_operation { typedef uint32_t TEEC_Result; -typedef struct { - uint32_t timeLow; - uint16_t timeMid; - uint16_t timeHiAndVersion; - uint8_t clockSeqAndNode[8]; -} TEEC_UUID; +typedef struct teec_uuid TEEC_UUID; -typedef struct { - void *dev; - uint8_t *ta_path; - struct list_head session_list; - struct list_head shrd_mem_list; -} TEEC_Context; +typedef struct teec_context TEEC_Context; -typedef struct { - uint32_t session_id; - TEEC_UUID service_id; - uint32_t ops_cnt; - struct list_head head; - TEEC_Context *context; -} TEEC_Session; +typedef struct teec_session TEEC_Session; -typedef struct { - void *buffer; - size_t size; - uint32_t flags; - uint32_t ops_cnt; - bool is_allocated; - struct list_head head; - TEEC_Context *context; -} TEEC_SharedMemory; - -typedef struct { - void *buffer; - size_t size; -} TEEC_TempMemoryReference; +typedef struct teec_sharedmemory TEEC_SharedMemory; -typedef struct { - TEEC_SharedMemory *parent; - size_t size; - size_t offset; -} TEEC_RegisteredMemoryReference; +typedef struct teec_tempmemory_reference TEEC_TempMemoryReference; -typedef struct { - uint32_t a; - uint32_t b; -} TEEC_Value; +typedef struct teec_registeredmemory_reference TEEC_RegisteredMemoryReference; -typedef struct { - int ion_share_fd; - size_t ion_size; -} TEEC_IonReference; +typedef struct teec_value TEEC_Value; -typedef union { - TEEC_TempMemoryReference tmpref; - TEEC_RegisteredMemoryReference memref; - TEEC_Value value; - TEEC_IonReference ionref; -} TEEC_Parameter; +typedef struct teec_ion_reference TEEC_IonReference; -typedef struct { - uint32_t event_type; - /* Tui event type */ - uint32_t value; - /* return value, is keycode if tui event is getKeycode */ - uint32_t notch; /* notch size of phone */ - uint32_t width; /* width of foldable screen */ - uint32_t height; /* height of foldable screen */ - uint32_t fold_state; /* state of foldable screen */ - uint32_t display_state; /* one state of folded state */ - uint32_t phy_width; /* real width of the mobile */ - uint32_t phy_height; /* real height of the mobile */ -} TEEC_TUI_Parameter; +typedef union teec_parameter TEEC_Parameter; typedef struct { uint32_t started; diff --git a/teek_ns_client.h b/teek_ns_client.h index 52a0d2ed95031f882cd5f7c1c4a4c64f265c8939..54fafe3631d7e537b841e37c9baac832b5fe88b9 100644 --- a/teek_ns_client.h +++ b/teek_ns_client.h @@ -22,12 +22,12 @@ #include #include #include -#include #include "tc_ns_client.h" #include "tc_ns_log.h" #define TC_NS_CLIENT_IOC_MAGIC 't' #define TC_NS_CLIENT_DEV "tc_ns_client" +#define TC_PRIV_DEV "tc_private" #define TC_NS_CLIENT_DEV_NAME "/dev/tc_ns_client" #define EXCEPTION_MEM_SIZE (8*1024) /* mem for exception handling */ @@ -103,6 +103,10 @@ struct tc_ns_dev_file { */ bool login_setup; struct mutex login_setup_lock; /* for login_setup */ +#ifdef CONFIG_AUTH_HASH + bool cainfo_hash_setup; + struct mutex cainfo_hash_setup_lock; +#endif uint32_t pkg_name_len; uint8_t pkg_name[MAX_PACKAGE_NAME_LEN]; uint32_t pub_key_len; @@ -120,10 +124,6 @@ union tc_ns_parameter { unsigned int a; unsigned int b; } value; - struct { - unsigned int buffer; - unsigned int size; - } sharedmem; }; struct tc_ns_login { @@ -169,8 +169,8 @@ struct tc_ns_smc_cmd { int ret_val; unsigned int event_nr; unsigned int uid; - unsigned int ca_pid; /* pid */ - unsigned int pid; /* tgid */ + unsigned int ca_pid; /* pid */ + unsigned int pid; /* tgid */ unsigned int eventindex; /* tee audit event index for upload */ bool started; } __attribute__((__packed__)); @@ -202,7 +202,31 @@ struct tc_ns_session { struct mb_cmd_pack { struct tc_ns_operation operation; unsigned char login_data[MAX_SHA_256_SZ * NUM_OF_SO + MAX_SHA_256_SZ]; +}; +struct load_img_params { + struct tc_ns_dev_file *dev_file; + const char *file_buffer; + unsigned int file_size; + struct mb_cmd_pack *mb_pack; + char *mb_load_mem; + struct tc_uuid *uuid_return; + unsigned int mb_load_size; }; -#endif \ No newline at end of file +struct tc_call_params { + struct tc_ns_dev_file *dev; + struct tc_ns_client_context *context; + struct tc_ns_session *sess; + uint8_t flags; +}; + +struct tc_op_params { + struct mb_cmd_pack *mb_pack; + struct tc_ns_smc_cmd *smc_cmd; + struct tc_ns_temp_buf local_tmpbuf[TEE_PARAM_NUM]; + uint32_t trans_paramtype[TEE_PARAM_NUM]; + bool op_inited; +}; + +#endif diff --git a/tlogger/log_cfg_api.h b/tlogger/log_cfg_api.h index b2d0beeaacc45a6e7d96c2f6a4ff4aff717cc01c..70fd1d54542c39b35353ce059d3eb1ed2e3b2957 100644 --- a/tlogger/log_cfg_api.h +++ b/tlogger/log_cfg_api.h @@ -21,7 +21,7 @@ #include #if ((defined(CONFIG_BBOX_MEM) || defined(CONFIG_RDR_MEM) || \ - defined(CONFIG_PAGES_MEM) || defined(CONFIG_TEELOG))) + defined(CONFIG_PAGES_MEM)) && defined(CONFIG_TEELOG)) int register_log_mem(uint64_t *addr, uint32_t *len); int register_log_exception(void); void report_log_system_error(void); @@ -62,7 +62,11 @@ static inline void unmap_log_mem(const int *log_buffer) { (void)log_buffer; } - +static inline void get_log_chown(const uid_t *user, const gid_t *group) +{ + (void)user; + (void)group; +} static inline void unregister_log_exception(void) { } diff --git a/tlogger/log_pages_cfg.c b/tlogger/log_pages_cfg.c index 3e5270d4675511458669fa163ddbd27393b692bb..e2b1092365912a767b18f89340bc3a690a7d3506 100644 --- a/tlogger/log_pages_cfg.c +++ b/tlogger/log_pages_cfg.c @@ -32,10 +32,12 @@ #include #include "tc_ns_log.h" #include "tlogger.h" +#include "shared_mem.h" void unregister_log_exception(void) { } + int register_log_exception(void) { return 0; @@ -48,21 +50,21 @@ struct pages_module_result { struct pages_module_result g_mem_info = {0}; -#ifdef CONFIG_512K_LOG_PAGES_MEM -#define PAGES_LOG_MEM_LEN (512 * SZ_1K) /* mem size: 512 k */ -#else -#define PAGES_LOG_MEM_LEN (256 * SZ_1K) /* mem size: 256 k */ -#endif - static int tee_pages_register_core(void) { - g_mem_info.log_addr = (uintptr_t)__get_free_pages( - GFP_KERNEL | __GFP_ZERO, get_order(PAGES_LOG_MEM_LEN)); + if (g_mem_info.log_addr != 0 || g_mem_info.log_len != 0) { + if (memset_s((void *)g_mem_info.log_addr, g_mem_info.log_len, 0, g_mem_info.log_len) != 0) { + tloge("clean log memory failed\n"); + return -EFAULT; + } + return 0; + } + + g_mem_info.log_addr = get_log_mem_vaddr(); if (IS_ERR_OR_NULL((void *)(uintptr_t)g_mem_info.log_addr)) { tloge("get log mem error\n"); return -1; } - g_mem_info.log_len = PAGES_LOG_MEM_LEN; return 0; } @@ -80,14 +82,14 @@ int register_log_mem(uint64_t *addr, uint32_t *len) } ret = tee_pages_register_core(); - if (ret) + if (ret != 0) return ret; - mem_addr = virt_to_phys((void *)(uintptr_t)g_mem_info.log_addr); + mem_addr = get_log_mem_paddr(g_mem_info.log_addr); mem_len = g_mem_info.log_len; ret = register_mem_to_teeos(mem_addr, mem_len, true); - if (ret) + if (ret != 0) return ret; *addr = g_mem_info.log_addr; @@ -119,7 +121,16 @@ int *map_log_mem(uint64_t mem_addr, uint32_t mem_len) void unmap_log_mem(int *log_buffer) { - free_pages((unsigned long)(uintptr_t)log_buffer, - get_order(PAGES_LOG_MEM_LEN)); + free_log_mem((uint64_t)(uintptr_t)log_buffer); } +void get_log_chown(uid_t *user, gid_t *group) +{ + if (!user || !group) { + tloge("user or group buffer is null\n"); + return; + } + + *user = ROOT_UID; + *group = FILE_CHOWN_GID; +} diff --git a/tlogger/tlogger.c b/tlogger/tlogger.c index 3853c81c2dc26c47bc668fc02d6164fb064fddde..90183a18d8837c2fc8f4f5e6ca77cea9d174ce03 100644 --- a/tlogger/tlogger.c +++ b/tlogger/tlogger.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "smc_smp.h" #include "mailbox_mempool.h" #include "teek_client_constants.h" @@ -33,6 +34,7 @@ #include "log_cfg_api.h" #include "tc_ns_log.h" #include "ko_adapt.h" +#include "internal_functions.h" /* for log item ----------------------------------- */ #define LOG_ITEM_MAGIC 0x5A5A @@ -42,7 +44,7 @@ /* =================================================== */ #define LOGGER_LOG_TEEOS "teelog" /* tee os log */ -#define __TEELOGGERIO 0xBE /* for ioctl */ +#define LOGGERIOCTL 0xBE /* for ioctl */ #define DUMP_START_MAGIC "Dump SPI notification" #define DUMP_END_MAGIC "Dump task states END" @@ -55,14 +57,14 @@ /* get tee verison */ #define MAX_TEE_VERSION_LEN 256 #define TEELOGGER_GET_VERSION \ - _IOR(__TEELOGGERIO, GET_VERSION_BASE, char[MAX_TEE_VERSION_LEN]) + _IOR(LOGGERIOCTL, GET_VERSION_BASE, char[MAX_TEE_VERSION_LEN]) /* set the log reader pos to current pos */ #define TEELOGGER_SET_READERPOS_CUR \ - _IO(__TEELOGGERIO, SET_READERPOS_CUR_BASE) + _IO(LOGGERIOCTL, SET_READERPOS_CUR_BASE) #define TEELOGGER_SET_TLOGCAT_STAT \ - _IO(__TEELOGGERIO, SET_TLOGCAT_STAT_BASE) + _IO(LOGGERIOCTL, SET_TLOGCAT_STAT_BASE) #define TEELOGGER_GET_TLOGCAT_STAT \ - _IO(__TEELOGGERIO, GET_TLOGCAT_STAT_BASE) + _IO(LOGGERIOCTL, GET_TLOGCAT_STAT_BASE) int g_tlogcat_f = 0; @@ -87,8 +89,9 @@ struct log_item { unsigned char uuid[UUID_LEN]; unsigned char log_source_type; unsigned char reserved[LOG_ITEM_RESERVED_LEN]; + unsigned char log_level; unsigned char new_line; /* '\n' char, easy viewing log in bbox.bin file */ - unsigned char log_buffer[0]; + unsigned char log_buffer[]; }; /* --- for log mem --------------------------------- */ @@ -109,14 +112,14 @@ struct log_buffer_flag { uint32_t last_pos; uint32_t write_loops; uint32_t log_level; - uint32_t reserved[LOG_BUFFER_RESERVED_LEN]; + uint32_t reserved[LOG_BUFFER_RESERVED_LEN]; /* [0] for magic, [1] for serial_no */ uint32_t max_len; unsigned char version_info[VERSION_INFO_LEN]; }; struct log_buffer { struct log_buffer_flag flag; - unsigned char buffer_start[0]; + unsigned char buffer_start[]; }; static struct log_buffer *g_log_buffer = NULL; @@ -161,7 +164,7 @@ static struct tlogger_log *get_reader_log(const struct file *file) return reader->log; } -static bool check_log_item_validite(struct log_item *item, +static bool check_log_item_validite(const struct log_item *item, uint32_t item_max_size) { bool con = (item && (item->magic == LOG_ITEM_MAGIC) && @@ -187,7 +190,7 @@ static struct log_item *get_next_log_item(const unsigned char *buffer_start, while ((i + sizeof(*item) + LOG_ITEM_LEN_ALIGN) <= scope_len) { *pos = read_pos + i; - item = (struct log_item *)(buffer_start + read_pos + i); + item = (struct log_item *)(uintptr_t)(buffer_start + read_pos + i); max_size = (((scope_len - i) > LOG_ITEM_MAX_LEN) ? LOG_ITEM_MAX_LEN : (scope_len - i)); if (check_log_item_validite(item, max_size)) @@ -212,7 +215,7 @@ static uint32_t parse_log_item(char __user *buf, size_t count, bool *user_buffer_left) { struct log_item *next_item = NULL; - uint32_t buf_left; + size_t buf_left; uint32_t buf_written; uint32_t item_len; bool con = false; @@ -242,7 +245,7 @@ static uint32_t parse_log_item(char __user *buf, size_t count, start_pos += item_len; if (copy_to_user(buf + buf_written, - (void *)next_item, item_len)) + (void *)next_item, item_len) != 0) tloge("copy failed, item len %u\n", item_len); buf_written += item_len; @@ -275,7 +278,7 @@ static ssize_t get_buffer_info(struct tlogger_reader *reader, ret = memcpy_s(buffer_flag, sizeof(*buffer_flag), &buffer_tmp->flag, sizeof(buffer_tmp->flag)); mutex_unlock(&log->mutex_info); - if (ret) { + if (ret != 0) { tloge("memcpy failed %d\n", ret); return -EAGAIN; } @@ -287,7 +290,7 @@ static ssize_t get_buffer_info(struct tlogger_reader *reader, #define LOG_BUFFER_MAX_LEN 0x100000 static ssize_t get_last_read_pos(struct log_buffer_flag *log_flag, - struct tlogger_reader *reader, uint32_t *log_last_pos, uint32_t *is_read) + const struct tlogger_reader *reader, uint32_t *log_last_pos, uint32_t *is_read) { uint32_t buffer_max_len = g_log_mem_len - sizeof(*g_log_buffer); @@ -332,7 +335,7 @@ static ssize_t proc_read_ret(uint32_t buf_written, { ssize_t ret; - if (!buf_written) { + if (buf_written == 0) { ret = LOG_READ_STATUS_ERROR; } else { ret = buf_written; @@ -342,8 +345,8 @@ static ssize_t proc_read_ret(uint32_t buf_written, return ret; } -static ssize_t check_read_params(struct file *file, - char __user *buf, size_t count) +static ssize_t check_read_params(const struct file *file, + const char __user *buf, size_t count) { if (count < LOG_ITEM_MAX_LEN) return -EINVAL; @@ -419,7 +422,7 @@ static ssize_t process_tlogger_read(struct file *file, (void)pos; ret = check_read_params(file, buf, count); - if (ret) + if (ret != 0) return ret; reader = file->private_data; @@ -427,11 +430,11 @@ static ssize_t process_tlogger_read(struct file *file, return -EINVAL; ret = get_buffer_info(reader, &buffer_flag, &log_buffer); - if (ret) + if (ret != 0) return ret; ret = get_last_read_pos(&buffer_flag, reader, &last_pos, &is_read); - if (!is_read) + if (is_read == 0) return ret; return trigger_parse_log(buf, count, last_pos, log_buffer, reader); @@ -478,7 +481,7 @@ static int process_tlogger_open(struct inode *inode, tlogd("open logger open ++\n"); /* not support seek */ ret = nonseekable_open(inode, file); - if (ret) + if (ret != 0) return ret; tlogd("Before get log from minor\n"); @@ -542,8 +545,8 @@ static int process_tlogger_release(struct inode *ignored, g_tlogcat_count--; mutex_unlock(&log->mutex_info); - tlogi("logger_release r_is_tlogf-%u\n", reader->r_is_tlogf); - if (reader->r_is_tlogf) + tlogd("logger_release r_is_tlogf-%u\n", reader->r_is_tlogf); + if (reader->r_is_tlogf != 0) g_tlogcat_f = 0; kfree(reader); @@ -557,7 +560,7 @@ static unsigned int process_tlogger_poll(struct file *file, struct tlogger_reader *reader = NULL; struct tlogger_log *log = NULL; struct log_buffer *buffer = NULL; - unsigned int ret = POLLOUT | POLLWRNORM; + uint32_t ret = POLLOUT | POLLWRNORM; tlogd("logger_poll ++\n"); if (!file) { @@ -654,21 +657,21 @@ static int get_teeos_version(uint32_t cmd, unsigned long arg) { int ret; - if (!(_IOC_DIR(cmd) & _IOC_READ)) { + if ((_IOC_DIR(cmd) & _IOC_READ) == 0) { tloge("check get version cmd failed\n"); return -1; } ret = check_user_arg(arg, sizeof(g_log_buffer->flag.version_info)); - if (!ret) { + if (ret == 0) { tloge("check version info arg failed\n"); return -1; } if (copy_to_user((void __user *)(uintptr_t)arg, (void *)g_log_buffer->flag.version_info, - sizeof(g_log_buffer->flag.version_info))) { + sizeof(g_log_buffer->flag.version_info)) != 0) { tloge("version info copy failed\n"); return -1; } @@ -696,7 +699,7 @@ static long process_tlogger_ioctl(struct file *file, switch (cmd) { case TEELOGGER_GET_VERSION: - if (!get_teeos_version(cmd, arg)) + if (get_teeos_version(cmd, arg) == 0) ret = 0; break; case TEELOGGER_SET_READERPOS_CUR: @@ -747,6 +750,7 @@ static int __init register_device(const char *log_name, int ret; struct tlogger_log *log = NULL; unsigned char *buffer = (unsigned char *)addr; + (void)size; log = kzalloc(sizeof(*log), GFP_KERNEL); if (!log) { @@ -788,10 +792,10 @@ out_free_log: return ret; } -static struct log_item *msg_get_next(const unsigned char *buffer_start, - uint32_t read_pos, int scope_len, uint32_t max_len) +static struct log_item *msg_get_next(unsigned char *buffer_start, + uint32_t read_pos, uint32_t scope_len, uint32_t max_len) { - int i = 0; + uint32_t i = 0; struct log_item *item = NULL; uint32_t item_max_size; uint32_t len; @@ -820,7 +824,47 @@ static struct log_item *msg_get_next(const unsigned char *buffer_start, return NULL; } -#define OPEN_FILE_MODE 0644U +#ifdef CONFIG_TZDRIVER_MODULE +/* there is no way to chown in kernel-5.10 for ko */ +static int tlogger_chown(const char *file_path, uint32_t file_path_len) +{ + (void)file_path; + (void)file_path_len; + + return 0; +} +#else +static int tlogger_chown(const char *file_path, uint32_t file_path_len) +{ + (void)file_path_len; + uid_t user = ROOT_UID; + gid_t group = ROOT_GID; + int ret; + mm_segment_t old_fs; + + get_log_chown(&user, &group); + + /* not need modify chown attr */ + if (group == ROOT_GID && user == ROOT_UID) + return 0; + + old_fs = get_fs(); + set_fs(KERNEL_DS); +#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) + ret = (int)ksys_chown((const char __user *)file_path, user, group); +#else + ret = (int)sys_chown((const char __user *)file_path, user, group); +#endif + if (ret != 0) { + tloge("sys chown for last teemsg file error\n"); + set_fs(old_fs); + return -1; + } + + set_fs(old_fs); + return 0; +} +#endif static int write_version_to_msg(struct file *filep, loff_t *pos) @@ -840,7 +884,7 @@ static int write_version_to_msg(struct file *filep, } static int write_part_log_to_msg(struct file *filep, - const unsigned char *buffer, uint32_t buffer_max_len, loff_t *pos, + unsigned char *buffer, uint32_t buffer_max_len, loff_t *pos, uint32_t read_off, uint32_t read_off_end) { struct log_item *next_item = NULL; @@ -874,7 +918,7 @@ static int write_part_log_to_msg(struct file *filep, } static int write_log_to_msg(struct file *filep, - const unsigned char *buffer, uint32_t buffer_max_len, loff_t *pos, + unsigned char *buffer, uint32_t buffer_max_len, loff_t *pos, uint32_t read_off, uint32_t read_off_end) { if (read_off < read_off_end) { @@ -889,6 +933,67 @@ static int write_log_to_msg(struct file *filep, } } +#ifdef CONFIG_TEE_LOG_DUMP_PATH +static void update_dumpmsg_offset(uint32_t *read_start, uint32_t *read_end, + uint32_t read_off, uint32_t read_off_end, uint32_t *dump_start_flag, uint32_t *dump_end_flag) +{ + struct log_item *next_item = NULL; + unsigned char *buffer = g_log_buffer->buffer_start; + uint32_t buffer_max_len = g_log_mem_len - sizeof(*g_log_buffer); + ssize_t item_len; + ssize_t total_len = 0; + + next_item = msg_get_next(buffer, read_off, + LOG_ITEM_MAX_LEN, buffer_max_len); + + while (next_item && read_off <= read_off_end) { + item_len = next_item->buffer_len + sizeof(*next_item); + if (strstr(next_item->log_buffer, DUMP_START_MAGIC)) { + *read_start = read_off; + *dump_start_flag = 1; + } else if (strstr(next_item->log_buffer, DUMP_END_MAGIC)) { + *read_end = read_off; + *dump_end_flag = 1; + } + read_off = (unsigned char *)next_item - buffer + item_len; + total_len += item_len; + if (total_len >= buffer_max_len) + break; + + next_item = msg_get_next(buffer, read_off, + LOG_ITEM_MAX_LEN, buffer_max_len); + } +} +#endif + +#ifdef CONFIG_TEE_LOG_DUMP_PATH +static int get_dumpmsg_offset(uint32_t *read_start, uint32_t *read_end) +{ + uint32_t read_off = *read_start; + uint32_t read_off_end = *read_end; + uint32_t buffer_max_len = g_log_mem_len - sizeof(*g_log_buffer); + uint32_t dump_start_flag = 0; + uint32_t dump_end_flag = 0; + + if (read_off < read_off_end) { + update_dumpmsg_offset(read_start, read_end, read_off, read_off_end, + &dump_start_flag, &dump_end_flag); + } else { + update_dumpmsg_offset(read_start, read_end, read_off, buffer_max_len, + &dump_start_flag, &dump_end_flag); + update_dumpmsg_offset(read_start, read_end, 0, read_off_end, + &dump_start_flag, &dump_end_flag); + } + + if (dump_start_flag == 0 || dump_end_flag == 0) { + tloge("can't find dump start or end\n"); + return -1; + } else { + return 0; + } +} +#endif + static int get_msg_buffer(unsigned char **buffer, uint32_t *buffer_max_len, uint32_t *read_start, uint32_t *read_end, const char *file_path, uint32_t file_path_len) @@ -908,7 +1013,18 @@ static int get_msg_buffer(unsigned char **buffer, uint32_t *buffer_max_len, *read_start = 0; *read_end = *buffer_max_len; - +#ifdef CONFIG_TEE_LOG_DUMP_PATH + if (strcmp(file_path, CONFIG_TEE_LOG_DUMP_PATH) == 0) { + *read_start = g_last_read_offset; + *read_end = ((struct log_buffer*)g_log->buffer_info)->flag.last_pos; + if (get_dumpmsg_offset(read_start, read_end) != 0) { + tloge("get dump offset failed\n"); + return -1; + } + } +#else + (void)file_path; +#endif addr = kmalloc(*buffer_max_len, GFP_KERNEL); if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)addr)) { ret = -ENOMEM; @@ -936,7 +1052,7 @@ free_res: static int open_msg_file(struct file **file, const char *file_path, uint32_t file_path_len) { - struct file *filep; + struct file *filep = NULL; (void)file_path_len; filep = filp_open(file_path, O_CREAT | O_RDWR | O_TRUNC, OPEN_FILE_MODE); @@ -972,16 +1088,20 @@ int tlogger_store_msg(const char *file_path, uint32_t file_path_len) /* copy logs from log memory, then parse the logs */ ret = get_msg_buffer(&buffer, &buffer_max_len, &read_start, &read_end, file_path, file_path_len); - if (ret) + if (ret != 0) return ret; /* exception handling, store trustedcore exception info to file */ ret = open_msg_file(&filep, file_path, file_path_len); - if (ret) + if (ret != 0) + goto free_res; + + ret = tlogger_chown(file_path, file_path_len); + if (ret != 0) goto free_res; ret = write_version_to_msg(filep, &pos); - if (ret) + if (ret != 0) goto free_res; ret = write_log_to_msg(filep, buffer, buffer_max_len, @@ -1031,12 +1151,17 @@ int register_mem_to_teeos(uint64_t mem_addr, uint32_t mem_len, bool is_cache_mem */ mb_pack->operation.params[2].value.a = is_cache_mem; - smc_cmd.operation_phys = virt_to_phys(&mb_pack->operation); + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); smc_cmd.operation_h_phys = - (uint64_t)virt_to_phys(&mb_pack->operation) >> ADDR_TRANS_NUM; - ret = tc_ns_smc(&smc_cmd); + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; + + if (is_tee_rebooting()) + ret = send_smc_cmd_rebooting(TSP_REQUEST, 0, 0, &smc_cmd); + else + ret = tc_ns_smc(&smc_cmd); + mailbox_free(mb_pack); - if (ret) + if (ret != 0) tloge("Send log mem info failed\n"); return ret; @@ -1046,11 +1171,11 @@ static int register_mem_cfg(uint64_t *addr, uint32_t *len) { int ret; ret = register_log_mem(addr, len); - if (ret) + if (ret != 0) tloge("register log mem failed %x\n", ret); ret = register_log_exception(); - if (ret) + if (ret != 0) tloge("teeos register exception to log module failed\n"); return ret; @@ -1062,7 +1187,6 @@ static int check_log_mem(uint64_t mem_addr, uint32_t mem_len) tloge("log mem init error, too small len:0x%x\n", mem_len); return -1; } - if (!mem_addr) { tloge("mem init failed!!! addr is 0\n"); return -1; @@ -1070,17 +1194,17 @@ static int check_log_mem(uint64_t mem_addr, uint32_t mem_len) return 0; } -static __init int register_tloger(void) +int register_tloger_mem(void) { int ret; uint64_t mem_addr = 0; ret = register_mem_cfg(&mem_addr, &g_log_mem_len); - if (ret) + if (ret != 0) return ret; ret = check_log_mem(mem_addr, g_log_mem_len); - if (ret) + if (ret != 0) return ret; g_log_buffer = @@ -1090,10 +1214,17 @@ static __init int register_tloger(void) g_log_buffer->flag.max_len = g_log_mem_len - sizeof(*g_log_buffer); - tloge("tlogcat verison 1.0.0\n"); + return ret; +} + +static int register_tloger_device(void) +{ + int ret; + + tlogi("tlogcat version 1.0.0\n"); ret = register_device(LOGGER_LOG_TEEOS, (uintptr_t)g_log_buffer, sizeof(*g_log_buffer) + g_log_buffer->flag.max_len); - if (ret) { + if (ret != 0) { unmap_log_mem((int *)g_log_buffer); g_log_buffer = NULL; g_log_mem_len = 0; @@ -1102,6 +1233,19 @@ static __init int register_tloger(void) return ret; } +static int register_tloger(void) +{ + int ret; + + ret = register_tloger_mem(); + if (ret != 0) + return ret; + + ret = register_tloger_device(); + + return ret; +} + static void unregister_mem_cfg(void) { if (g_log_buffer) @@ -1129,12 +1273,12 @@ static void unregister_tlogger(void) } #ifdef CONFIG_TZDRIVER_MODULE -__init int init_tlogger_service(void) +int init_tlogger_service(void) { return register_tloger(); } -void exit_tlogger_service(void) +void free_tlogger_service(void) { unregister_tlogger(); } @@ -1144,7 +1288,7 @@ static int __init init_tlogger_service(void) return register_tloger(); } -static void __exit exit_tlogger_service(void) +static void __exit free_tlogger_service(void) { unregister_tlogger(); } @@ -1152,7 +1296,7 @@ static void __exit exit_tlogger_service(void) #ifdef CONFIG_TZDRIVER device_initcall(init_tlogger_service); -module_exit(exit_tlogger_service); +module_exit(free_tlogger_service); MODULE_AUTHOR("iTrustee"); MODULE_DESCRIPTION("TrustCore Logger"); diff --git a/tlogger/tlogger.h b/tlogger/tlogger.h index cd96048b8b61cbb0782e89478c31c7c58aa2d976..f1ef7730190911bd335a2d3238e8bdd114ecf7a1 100644 --- a/tlogger/tlogger.h +++ b/tlogger/tlogger.h @@ -20,7 +20,18 @@ #include -#define UINT64_MAX (uint64_t)(~((uint64_t)0)) +#define OPEN_FILE_MODE 0640U +#define ROOT_UID 0 +#define ROOT_GID 0 +#define SYSTEM_GID 1000 +#ifdef LAST_TEE_MSG_ROOT_GID +#define FILE_CHOWN_GID 0 +#else +/* system gid for last_teemsg file sys chown */ +#define FILE_CHOWN_GID 1000 +#endif + +#define UINT64_MAX (uint64_t)(~((uint64_t)0)) /* 0xFFFFFFFFFFFFFFFF */ #ifdef CONFIG_TEELOG void tz_log_write(void); @@ -29,7 +40,8 @@ int register_mem_to_teeos(uint64_t mem_addr, uint32_t mem_len, bool is_cache_mem #ifdef CONFIG_TZDRIVER_MODULE int init_tlogger_service(void); -void exit_tlogger_service(void); +void free_tlogger_service(void); +int register_tloger_mem(void); #endif #else @@ -55,7 +67,7 @@ static inline int init_tlogger_service(void) { return 0; } -static inline int exit_tlogger_service(void) +static inline void free_tlogger_service(void) { } #endif diff --git a/tzdriver_internal/include/internal_functions.h b/tzdriver_internal/include/internal_functions.h new file mode 100644 index 0000000000000000000000000000000000000000..05104f84aca393619c68be1bd0f71536560b10eb --- /dev/null +++ b/tzdriver_internal/include/internal_functions.h @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef INTERNAL_FUNCTIONS_H +#define INTERNAL_FUNCTIONS_H + +#include +#include +#include "teek_ns_client.h" +#include "teek_client_constants.h" + +#ifdef CONFIG_STATIC_ION +#include "static_ion_mem.h" +#else +static inline int tc_ns_register_ion_mem(void) +{ + return 0; +} +#endif + +#ifndef CONFIG_HISI_VLTMM +static inline void vltmm_agent_register(void) +{ + return; +} +#endif + +#ifndef CONFIG_TEE_FAULT_MANAGER +static inline void fault_monitor_start(int32_t type) +{ + (void)type; + return; +} + +static inline void fault_monitor_end(void) +{ + return; +} +#endif + +#ifdef CONFIG_DYNAMIC_ION +#include "dynamic_ion_mem.h" +#else +static inline bool is_ion_param(uint32_t param_type) +{ + (void)param_type; + return false; +} + +static inline int load_image_for_ion(const struct load_img_params *params, int32_t *ret_origin) +{ + (void)params; + (void)ret_origin; + return 0; +} + +static inline int init_dynamic_mem(void) +{ + return 0; +} + +static inline int load_app_use_configid(uint32_t configid, uint32_t cafd, + const struct tc_uuid *uuid, uint32_t size) +{ + (void)configid; + (void)cafd; + (void)uuid; + (void)size; + return 0; +} + +static inline void kill_ion_by_cafd(unsigned int cafd) +{ + (void)cafd; + return; +} + +static inline void kill_ion_by_uuid(const struct tc_uuid *uuid) +{ + (void)uuid; + return; +} +#endif + +#ifndef CONFIG_ION_HISI +static inline int alloc_for_ion(const struct tc_call_params *call_params, + struct tc_op_params *op_params, uint8_t kernel_params, + uint32_t param_type, unsigned int index) +{ + (void)call_params; + (void)op_params; + (void)kernel_params; + (void)param_type; + (void)index; + tloge("not support ion and related feature!\n"); + return -1; +} +#endif + +#ifndef CONFIG_ION_HISI_SECSG +static inline int alloc_for_ion_sglist(const struct tc_call_params *call_params, + struct tc_op_params *op_params, uint8_t kernel_params, + uint32_t param_type, unsigned int index) +{ + (void)call_params; + (void)op_params; + (void)kernel_params; + (void)param_type; + (void)index; + tloge("not support seg and related feature!\n"); + return -1; +} +#endif + +#ifdef CONFIG_KTHREAD_AFFINITY +#include "tz_kthread_affinity.h" +#else +static inline void init_kthread_cpumask(void) +{ +} + +static inline void tz_kthread_bind_mask(struct task_struct *kthread) +{ + (void)kthread; +} + +static inline void tz_workqueue_bind_mask(struct workqueue_struct *wq, + uint32_t flag) +{ + (void)wq; + (void)flag; +} +#endif + +#ifdef CONFIG_TEE_TUI +#include "tui.h" +#else +static inline bool is_tui_agent(unsigned int agent_id) +{ + (void)agent_id; + return false; +} + +static inline int init_tui(const struct device *dev) +{ + (void)dev; + return 0; +} + +static inline void free_tui(void) +{ +} + +static inline void unregister_tui_driver(const char *name) +{ + (void)name; +} + +static inline int send_tui_msg_config(int type, int val, const void *data) +{ + (void)type; + (void)val; + (void)data; + return 0; +} + +static inline void set_tui_caller_info(unsigned int devid, int pid) +{ + (void)devid; + (void)pid; +} + +static inline void free_tui_caller_info(void) +{ +} + +static inline unsigned int tui_attach_device(void) +{ + return 0; +} +static inline int is_tui_in_use(int pid_value) +{ + (void)pid_value; + return 0; +} + +static inline void do_ns_tui_release(void) +{ +} + +static inline int tc_ns_tui_event(struct tc_ns_dev_file *dev_file, const void *argp) +{ + (void)dev_file; + (void)argp; + return 0; +} +#endif + +#ifdef CONFIG_LIVEPATCH_ENABLE +#include "livepatch_cmd.h" +#else +static inline int livepatch_init(const struct device *dev) +{ + (void)dev; + return 0; +} +static inline void livepatch_down_read_sem(void) +{ +} +static inline void livepatch_up_read_sem(void) +{ +} +static inline void free_livepatch(void) +{ +} +#endif + +#ifdef CONFIG_TEE_TRACE +#include "tee_trace_event.h" +#include "tee_trace_interrupt.h" +#else +static inline void tee_trace_add_event(enum tee_event_id id, uint64_t add_info) +{ + (void)id; + (void)add_info; +} +static inline void free_event_mem(void) +{ +} +static inline void free_interrupt_trace(void) +{ +} +#endif + +#ifdef CONFIG_TEE_REBOOT +#include "reboot.h" +#else +static inline bool is_tee_rebooting(void) +{ + return false; +} +static inline int tee_init_reboot_thread(void) +{ + return 0; +} +static inline int tee_wake_up_reboot(void) +{ + return 0; +} +static inline void free_reboot_thread(void) +{ + return; +} +#endif + +#endif diff --git a/kthread_affinity/tz_kthread_affinity.c b/tzdriver_internal/kthread_affinity/tz_kthread_affinity.c similarity index 99% rename from kthread_affinity/tz_kthread_affinity.c rename to tzdriver_internal/kthread_affinity/tz_kthread_affinity.c index c1fc5428a83014ef07c64db78f1011a4a4c1cb14..3cf85bd6edc288f05b6b270941c5d707a01eff2d 100644 --- a/kthread_affinity/tz_kthread_affinity.c +++ b/tzdriver_internal/kthread_affinity/tz_kthread_affinity.c @@ -67,7 +67,7 @@ void tz_workqueue_bind_mask(struct workqueue_struct *wq, uint32_t flag) cpumask_copy(attrs->cpumask, &g_kthread_cpumask); ret = apply_workqueue_attrs(wq, attrs); - if (ret) + if (ret != 0) tloge("apply workqueue attrs failed %d\n", ret); koadpt_free_workqueue_attrs(attrs); } diff --git a/kthread_affinity/tz_kthread_affinity.h b/tzdriver_internal/kthread_affinity/tz_kthread_affinity.h similarity index 76% rename from kthread_affinity/tz_kthread_affinity.h rename to tzdriver_internal/kthread_affinity/tz_kthread_affinity.h index 25953e91f30dac6fe0af8f8886a59c54676cd167..9973100590b17200d98b31528bbdfbd82aae6372 100644 --- a/kthread_affinity/tz_kthread_affinity.h +++ b/tzdriver_internal/kthread_affinity/tz_kthread_affinity.h @@ -21,27 +21,9 @@ #include #include -#define TZ_WQ_MAX_ACTIVE 1 - #ifdef CONFIG_KTHREAD_AFFINITY void init_kthread_cpumask(void); void tz_kthread_bind_mask(struct task_struct *kthread); void tz_workqueue_bind_mask(struct workqueue_struct *wq, uint32_t flag); -#else -static inline void init_kthread_cpumask(void) -{ -} - -static inline void tz_kthread_bind_mask(struct task_struct *kthread) -{ - (void)kthread; -} - -static inline void tz_workqueue_bind_mask(struct workqueue_struct *wq, - uint32_t flag) -{ - (void)wq; - (void)flag; -} #endif #endif diff --git a/kthread_affinity/tz_kthread_cpumask.h b/tzdriver_internal/kthread_affinity/tz_kthread_cpumask.h similarity index 100% rename from kthread_affinity/tz_kthread_cpumask.h rename to tzdriver_internal/kthread_affinity/tz_kthread_cpumask.h diff --git a/kthread_affinity/tz_kthread_cpumask_dts.c b/tzdriver_internal/kthread_affinity/tz_kthread_cpumask_dts.c similarity index 100% rename from kthread_affinity/tz_kthread_cpumask_dts.c rename to tzdriver_internal/kthread_affinity/tz_kthread_cpumask_dts.c diff --git a/tzdriver_internal/tee_trace_event/tee_trace_event.c b/tzdriver_internal/tee_trace_event/tee_trace_event.c new file mode 100644 index 0000000000000000000000000000000000000000..cd1203f23694771f416a8478cc3041215dc63da0 --- /dev/null +++ b/tzdriver_internal/tee_trace_event/tee_trace_event.c @@ -0,0 +1,464 @@ +/* + * tee_trace_event.c + * + * functions for TEE trace + * + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "tee_trace_event.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "internal_functions.h" +#include "tee_trace_interrupt.h" + +#define TEE_TASK_NAME_LEN 16 /* same as tcb_prop->tcb_name */ + +#define trace_event_name(event_id, enable) \ + [event_id] = { #event_id, enable } + +#define compile_time_assert(cond, msg) typedef char g_assert_##msg[(cond) ? 1 : -1] + +struct tee_view_state_t { + const char *name; + bool enable; +}; + +/* Make sure it has the same order as 'enum tee_event_id' */ +static struct tee_view_state_t view_state[TEE_EVENT_MAX] = { + trace_event_name(INVOKE_CMD_START, true), + trace_event_name(INVOKE_CMD_END, true), + trace_event_name(SMC_SEND, true), + trace_event_name(SMC_DONE, true), + trace_event_name(SMC_IN, true), + trace_event_name(SMC_OUT, true), + trace_event_name(SMC_SLEEP, true), + trace_event_name(SMC_PREEMPT, true), + trace_event_name(GTASK_GET_CMD, false), + trace_event_name(GTASK_PUT_CMD, false), + trace_event_name(GTASK_REQ_TA, false), + trace_event_name(GTASK_RESP_TA, false), + trace_event_name(SPI_WAKEUP, true), + trace_event_name(SCHED_IN, true), + trace_event_name(SCHED_OUT, true), + trace_event_name(INTERRUPT_HANDLE_SPI_START, true), + trace_event_name(INTERRUPT_HANDLE_SPI_REE_RESPONSE, true), + trace_event_name(INTERRUPT_HANDLE_SPI_REE_MISS, true), + trace_event_name(INTERRUPT_HANDLE_SPI_REE_SCHEDULED, true), + trace_event_name(INTERRUPT_HANDLE_SPI_END, true), + trace_event_name(INTERRUPT_HANDLE_START, true), + trace_event_name(INTERRUPT_HANDLE_END, true), +}; + +static const char* trace_task[] = { + /* add ta name like this "echo_task", */ +}; +compile_time_assert(ARRAY_SIZE(trace_task) <= TEE_TRACE_TASK_MAX, + trace_task_too_large); + +struct tee_trace_event_t { + enum tee_event_id id; + uint32_t ca_pid; + uint64_t time; + uint64_t add_info; +}; + +struct tee_trace_stream_t { + uint32_t total; + uint32_t cur; + uint32_t overflowed; + struct tee_trace_event_t events[TEE_TRACE_EVENT_NUM]; +}; + +struct tee_trace_mem_t { + bool start; + uint32_t freq; + uint32_t loop_enable; + bool enable[TEE_EVENT_MAX]; + uint32_t trace_task; + char trace_task_name[TEE_TRACE_TASK_MAX][TEE_TASK_NAME_LEN]; + struct tee_trace_stream_t *streams[NR_CPUS]; +}; + +#define TRACE_STREAM_SIZE ALIGN(sizeof(struct tee_trace_stream_t), PAGE_SIZE) +#define TRACE_MEM_SIZE ALIGN(sizeof(struct tee_trace_mem_t), PAGE_SIZE) + +/* pages associate with g_event_mem */ +static struct page *g_event_pages; +/* pages associate with g_event_mem->streams[NR_CPUS] */ +static struct page *g_stream_pages[NR_CPUS]; +static struct tee_trace_mem_t *g_event_mem; +static uint64_t g_trace_start_time; +void tee_trace_add_event(enum tee_event_id id, uint64_t add_info) +{ + int32_t cpu_id = raw_smp_processor_id(); + struct tee_trace_stream_t *stream = NULL; + struct tee_trace_event_t *event = NULL; + + if (id < INVOKE_CMD_START || id >= TEE_EVENT_MAX) + return; + + if (g_event_mem == NULL || !g_event_mem->start || !g_event_mem->enable[id]) + return; + + preempt_disable(); + stream = g_event_mem->streams[cpu_id]; + event = &stream->events[stream->cur]; + + if (g_event_mem->loop_enable == TRACE_LOG_LOOP_DISABLED && + unlikely((stream->cur + 1) >= stream->total)) { + tloge("events buffer too small\n"); + preempt_enable(); + return; + } + + event->id = id; + event->ca_pid = current->pid; +#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) + event->time = arch_timer_read_counter(); +#else + event->time = arch_counter_get_cntvct(); +#endif + event->add_info = (add_info == 0) ? current->pid : add_info; + stream->cur++; + if (unlikely(stream->cur >= stream->total)) { + stream->cur = 0; + stream->overflowed = 1; + } + preempt_enable(); +} + +struct trace_mem_cmd_t { + uint64_t trace_mem; + uint64_t trace_mem_size; + uint64_t trace_streams[NR_CPUS]; +}; + +static void *init_cmd_of_trace_mem(void) +{ + uint32_t i; + struct trace_mem_cmd_t *p = + mailbox_alloc(sizeof(struct trace_mem_cmd_t), MB_FLAG_ZERO); + + if (p == NULL) + return NULL; + + p->trace_mem = virt_to_phys(g_event_mem); + p->trace_mem_size = TRACE_MEM_SIZE; + for (i = 0; i < NR_CPUS; i++) + p->trace_streams[i] = virt_to_phys(g_event_mem->streams[i]); + + return p; +} + +static int tee_trace_event_send_cmd(uint32_t cmd) +{ + int ret = 0; + struct tc_ns_smc_cmd smc_cmd = { { 0 }, 0 }; + struct mb_cmd_pack *mb_pack = NULL; + void *cmd_buffer = NULL; + + mb_pack = mailbox_alloc_cmd_pack(); + if (mb_pack == NULL) + return -ENOMEM; + + switch (cmd) { + case GLOBAL_CMD_ID_TRACE_ENABLE: + mb_pack->operation.paramtypes = TEE_PARAM_TYPE_MEMREF_INPUT; + cmd_buffer = init_cmd_of_trace_mem(); + if (cmd_buffer == NULL) { + mailbox_free(mb_pack); + return -ENOMEM; + } + mb_pack->operation.params[0].memref.buffer = mailbox_virt_to_phys((uintptr_t)cmd_buffer); + mb_pack->operation.buffer_h_addr[0] = + mailbox_virt_to_phys((uintptr_t)cmd_buffer) >> ADDR_TRANS_NUM; + mb_pack->operation.params[0].memref.size = + ALIGN(sizeof(struct trace_mem_cmd_t), PAGE_SIZE); + break; + default: + mailbox_free(mb_pack); + return -EINVAL; + } + smc_cmd.cmd_type = CMD_TYPE_GLOBAL; + smc_cmd.cmd_id = cmd; + smc_cmd.operation_phys = mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); + smc_cmd.operation_h_phys = + (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; + + livepatch_down_read_sem(); + if (tc_ns_smc(&smc_cmd)) { + ret = -EIO; + tloge("trace cmd 0x%x failed\n", cmd); + } + livepatch_up_read_sem(); + + if (cmd_buffer != NULL) + mailbox_free(cmd_buffer); + mailbox_free(mb_pack); + + return ret; +} + +void free_event_mem(void) +{ + uint32_t i; + + (void)memset_s(g_event_mem, TRACE_MEM_SIZE, 0, TRACE_MEM_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + if (g_stream_pages[i] != NULL) { + __free_pages(g_stream_pages[i], get_order(TRACE_STREAM_SIZE)); + g_stream_pages[i] = NULL; + } + } + + if (g_event_pages != NULL) { + __free_pages(g_event_pages, get_order(TRACE_MEM_SIZE)); + g_event_mem = NULL; + } +} + +static int init_event_mem(void) +{ + uint32_t i; + int ret; + + g_event_pages = koadpt_alloc_pages(GFP_KERNEL, get_order(TRACE_MEM_SIZE)); + if (g_event_pages == NULL) { + tloge("alloc event mem (size 0x%lx) failed\n", TRACE_MEM_SIZE); + return -ENOMEM; + } + g_event_mem = page_address(g_event_pages); + (void)memset_s(g_event_mem, TRACE_MEM_SIZE, 0, TRACE_MEM_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + g_stream_pages[i] = + koadpt_alloc_pages(GFP_KERNEL, get_order(TRACE_STREAM_SIZE)); + if (!g_stream_pages[i]) { + tloge("alloc stream mem (size 0x%lx) failed\n", TRACE_STREAM_SIZE); + ret = -ENOMEM; + goto clean; + } + g_event_mem->streams[i] = page_address(g_stream_pages[i]); + } + + for (i = 0; i < TEE_EVENT_MAX; i++) + g_event_mem->enable[i] = view_state[i].enable; + + g_event_mem->trace_task = ARRAY_SIZE(trace_task); + for (i = 0; i < ARRAY_SIZE(trace_task); i++) + if (strcpy_s(g_event_mem->trace_task_name[i], TEE_TASK_NAME_LEN, + trace_task[i]) != EOK) { + tloge("task name %s too long\n", trace_task[i]); + ret = -EINVAL; + goto clean; + } + + g_event_mem->freq = arch_timer_get_cntfrq(); + for (i = 0; i < NR_CPUS; i++) + g_event_mem->streams[i]->total = TEE_TRACE_EVENT_NUM; + + return 0; + +clean: + free_event_mem(); + return ret; +} + +int tee_trace_event_enable(void) +{ + int ret; + + if (g_event_mem != NULL) + return 0; + + ret = init_event_mem(); + if (ret != 0) + return ret; + + ret = tee_trace_event_send_cmd(GLOBAL_CMD_ID_TRACE_ENABLE); + if (ret != 0) { + free_event_mem(); + tloge("register tee trace mem failed\n"); + return ret; + } + + return 0; +} + +static int tee_trace_event_start_common(uint32_t loop_enable) +{ + uint32_t cpu; + + if (g_event_mem == NULL) + return 0; + + interrupt_trace_stop(); + + g_event_mem->loop_enable = loop_enable; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + g_event_mem->streams[cpu]->cur = 0; + g_event_mem->streams[cpu]->overflowed = 0; + (void)memset_s(g_event_mem->streams[cpu]->events, + sizeof(struct tee_trace_event_t) * TEE_TRACE_EVENT_NUM, 0, + sizeof(struct tee_trace_event_t) * TEE_TRACE_EVENT_NUM); + } + g_event_mem->start = true; + +#if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE) + g_trace_start_time = arch_timer_read_counter(); +#else + g_trace_start_time = arch_counter_get_cntvct(); +#endif + + smp_mb(); + + interrupt_trace_start(); + + return 0; +} +int tee_trace_event_start_loop_record(void) +{ + return tee_trace_event_start_common(TRACE_LOG_LOOP_ENABLED); +} + +int tee_trace_event_start(void) +{ + return tee_trace_event_start_common(TRACE_LOG_LOOP_DISABLED); +} + +int tee_trace_event_stop(void) +{ + if (g_event_mem == NULL || !g_event_mem->start) + return 0; + g_event_mem->start = false; + smp_mb(); + interrupt_trace_stop(); + return 0; +} + +void get_tee_trace_start(struct tee_trace_view_t *view) +{ + uint32_t i; + + if (g_event_mem == NULL || view == NULL) + return; + + for (i = 0; i < NR_CPUS; i++) { + uint64_t time = g_event_mem->streams[i]->events[0].time; + if (g_event_mem->loop_enable != TRACE_LOG_LOOP_DISABLED) + time = g_trace_start_time; + if (time != 0 && (view->start == 0 || view->start > time)) + view->start = time; + if (g_event_mem->loop_enable != TRACE_LOG_LOOP_DISABLED && + g_event_mem->streams[i]->overflowed == 1) { + view->total += g_event_mem->streams[i]->total; + view->end[i] = g_event_mem->streams[i]->total; + view->buffer_is_full = 1; + } else { + view->total += g_event_mem->streams[i]->cur; + view->end[i] = g_event_mem->streams[i]->cur; + } + + view->at[i] = 0; + } + + view->freq = g_event_mem->freq; +} + +static int32_t get_read_idx(struct tee_trace_view_t *view, int32_t index, + bool cyclically) +{ + if (cyclically) { + if (view->at[index] == g_event_mem->streams[index]->cur) + return -1; + return view->at[index]; + } + if (view->at[index] >= view->end[index]) + return -1; + return view->at[index]; +} + +static void get_next_log_cpu_idx(struct tee_trace_view_t *view, + int32_t *index, bool cyclically) +{ + uint32_t i; + uint64_t first = 0; + *index = -1; + for (i = 0; i < NR_CPUS; i++) { + int32_t read_idx = get_read_idx(view, i, cyclically); + if (read_idx != -1) { + if (*index == -1 || + first > g_event_mem->streams[i]->events[read_idx].time) { + first = g_event_mem->streams[i]->events[read_idx].time; + *index = i; + } + } + } +} + +int get_tee_trace_next(struct tee_trace_view_t *view, struct trace_log_info *log_info, + bool cyclically) +{ + int32_t index = -1; + struct tee_trace_event_t *event = NULL; + + if (log_info == NULL) + return -1; + + if (g_event_mem == NULL || !g_event_mem->start || view == NULL) + return -1; + + if (g_event_mem->freq == 0) + return -1; + + get_next_log_cpu_idx(view, &index, cyclically); + + if (index == -1) + return -1; + + event = &g_event_mem->streams[index]->events[view->at[index]]; + log_info->event_id = event->id; + log_info->event_name = view_state[event->id].name; + log_info->cpu = (uint32_t)index; + log_info->ca_pid = event->ca_pid; + log_info->time = (event->time - view->start) * USEC_PER_SEC / g_event_mem->freq; + log_info->add_info = event->add_info; + view->at[index]++; + + if (g_event_mem->loop_enable != TRACE_LOG_LOOP_DISABLED && cyclically && + view->at[index] == g_event_mem->streams[index]->total) + view->at[index] = 0; + + return 0; +} + +const char *get_tee_trace_task_name(uint32_t task_idx) +{ + if (task_idx >= ARRAY_SIZE(trace_task)) + return NULL; + return trace_task[task_idx]; +} diff --git a/core/tee_trace_event.h b/tzdriver_internal/tee_trace_event/tee_trace_event.h similarity index 55% rename from core/tee_trace_event.h rename to tzdriver_internal/tee_trace_event/tee_trace_event.h index 3a089a10f0a628544063bc0d69fd3ea1ba095a27..9f50fabd509592b3813d48d25b620ef91648df45 100644 --- a/core/tee_trace_event.h +++ b/tzdriver_internal/tee_trace_event/tee_trace_event.h @@ -21,57 +21,48 @@ #include #include +#include "teek_client_constants.h" -/* maxium trace event per cpu stream */ -#define TEE_TRACE_EVENT_NUM 20000 +/* maximum trace event per cpu stream */ +#define TEE_TRACE_EVENT_NUM 20000 /* maxium trace task of 'sched_in/out' event */ -#define TEE_TRACE_TASK_MAX 8 +#define TEE_TRACE_TASK_MAX 8 +#define MAX_UINT64_TIME (uint64_t)(~((uint64_t)0)) -/* Add event id's name in 'view_state[]' in same order */ -enum tee_event_id { - INVOKE_CMD_START, - INVOKE_CMD_END, - SMC_SEND, - SMC_DONE, - SMC_IN, - SMC_OUT, - SMC_SLEEP, - SMC_PREEMPT, - GTASK_GET_CMD, - GTASK_PUT_CMD, - GTASK_REQ_TA, - GTASK_RESP_TA, - SPI_WAKEUP, - SCHED_IN, - SCHED_OUT, - TEE_EVENT_MAX -}; +#define TRACE_LOG_LOOP_ENABLED 1 +#define TRACE_LOG_LOOP_DISABLED 0 #ifdef CONFIG_TEE_TRACE void tee_trace_add_event(enum tee_event_id id, uint64_t add_info); int tee_trace_event_enable(void); int tee_trace_event_start(void); +int tee_trace_event_start_loop_record(void); int tee_trace_event_stop(void); struct tee_trace_view_t { - uint64_t start; - uint32_t total; - uint32_t end[NR_CPUS]; - uint32_t at[NR_CPUS]; + uint64_t start; + uint32_t total; + uint32_t freq; + uint32_t buffer_is_full; + uint32_t end[NR_CPUS]; + uint32_t at[NR_CPUS]; +}; + +struct trace_log_info { + const char *event_name; + uint32_t event_id; + uint32_t ca_pid; + uint32_t cpu; + uint64_t time; + uint64_t add_info; }; void get_tee_trace_start(struct tee_trace_view_t *view); -int get_tee_trace_next(struct tee_trace_view_t *view, uint32_t *event_id, - const char **event_name, uint32_t *cpu, uint32_t *ca_pid, - uint64_t *time, uint64_t *add_info); +int get_tee_trace_next(struct tee_trace_view_t *view, struct trace_log_info *log_info, + bool cyclically); const char *get_tee_trace_task_name(uint32_t task_idx); -#else -static inline void tee_trace_add_event(enum tee_event_id id, uint64_t add_info) -{ - (void)id; - (void)add_info; -} +void free_event_mem(void); #endif -#endif \ No newline at end of file +#endif diff --git a/tzdriver_internal/tee_trace_event/tee_trace_interrupt.c b/tzdriver_internal/tee_trace_event/tee_trace_interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..f4496f56d0acb2db42214892134c217c31874c09 --- /dev/null +++ b/tzdriver_internal/tee_trace_event/tee_trace_interrupt.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "tee_trace_interrupt.h" + +#include +#include +#include +#include +#include +#include "cmdmonitor.h" +#include "tee_trace_event.h" + +static struct delayed_work g_interrupt_trace_log_work; +static struct tee_trace_view_t g_interrupt_log_view = { 0, 0, 0, 0, { 0 }, { 0 } }; +volatile static int g_interrupt_trace_log_work_state = LOGGER_NOT_RUNNING; +volatile static bool g_trace_log_work_inited = false; +static struct file *g_int_log_fp = NULL; +static struct file *g_event_log_fp = NULL; +static loff_t g_int_log_fp_pos = 0; +static loff_t g_event_log_fp_pos = 0; +static bool is_interrupt_event(uint32_t event_id) +{ + return (event_id == INTERRUPT_HANDLE_SPI_START || event_id == INTERRUPT_HANDLE_SPI_END || + event_id == INTERRUPT_HANDLE_START || event_id == INTERRUPT_HANDLE_END || + event_id == INTERRUPT_HANDLE_SPI_REE_RESPONSE || event_id == INTERRUPT_HANDLE_SPI_REE_MISS || + event_id == INTERRUPT_HANDLE_SPI_REE_SCHEDULED); +} + +static void close_trace_log(void) +{ + if (g_int_log_fp != NULL) { + vfs_fsync(g_int_log_fp, 0); + filp_close(g_int_log_fp, 0); + g_int_log_fp = NULL; + } + + if (g_event_log_fp != NULL) { + vfs_fsync(g_event_log_fp, 0); + filp_close(g_event_log_fp, 0); + g_event_log_fp = NULL; + } +} + +static void refresh_int_trace_log(void) +{ + g_int_log_fp_pos = 0; + g_event_log_fp_pos = 0; + + g_int_log_fp = filp_open(CONFIG_INT_TRACE_LOG_PATH, O_CREAT | O_RDWR | O_TRUNC, TRACE_LOG_OPEN_FILE_MODE); + if (!g_int_log_fp || IS_ERR(g_int_log_fp)) { + tloge("create interrupt trace log file err %ld\n", PTR_ERR(g_int_log_fp)); + g_int_log_fp = NULL; + return; + } + + g_event_log_fp = filp_open(CONFIG_EVENT_TRACE_LOG_PATH, O_CREAT | O_RDWR | O_TRUNC, TRACE_LOG_OPEN_FILE_MODE); + if (!g_event_log_fp || IS_ERR(g_event_log_fp)) { + tloge("create event trace log file err %ld\n", PTR_ERR(g_event_log_fp)); + g_event_log_fp = NULL; + return; + } +} + +static void init_tee_trace_view(void) +{ + memset_s(&g_interrupt_log_view, sizeof(struct tee_trace_view_t), + 0, sizeof(struct tee_trace_view_t)); + get_tee_trace_start(&g_interrupt_log_view); + smp_mb(); +} + +static void write_interrupt_trace_log(char *log_str_buffer) +{ + struct trace_log_info log_info; + ssize_t write_len; + int len; + + if (log_str_buffer == NULL || g_interrupt_log_view.freq == 0) + return; + while (g_interrupt_trace_log_work_state == LOGGER_RUNNING && + get_tee_trace_next(&g_interrupt_log_view, &log_info, true) != -1) { + log_info.time = log_info.time + g_interrupt_log_view.start * USEC_PER_SEC / + g_interrupt_log_view.freq; + len = snprintf_s(log_str_buffer, LOG_STR_BUFFER_LEN, LOG_STR_BUFFER_LEN - 1, + "[%016lluus]cpu=%u, info=%llu, pid=%u, event=%s\n", log_info.time, log_info.cpu, log_info.add_info, + log_info.ca_pid, log_info.event_name); + if (len < 0) { + tloge("failed to write interrupt trace str to buffer\n"); + return; + } + if (is_interrupt_event(log_info.event_id) && g_int_log_fp != NULL) { + write_len = kernel_write(g_int_log_fp, log_str_buffer, len, &g_int_log_fp_pos); + if (write_len < 0) { + tloge("Failed to write interrupt trace log %zd\n", write_len); + return; + } + } + if (g_event_log_fp == NULL) + return; + write_len = kernel_write(g_event_log_fp, log_str_buffer, len, &g_event_log_fp_pos); + if (write_len < 0) { + tloge("Failed to write event trace log %zd\n", write_len); + return; + } + } +} + +static void interrupt_trace_logger(struct work_struct *work) +{ + char *log_str_buffer = NULL; + (void)(work); + log_str_buffer = kzalloc(LOG_STR_BUFFER_LEN, GFP_KERNEL); + if (!log_str_buffer) { + tloge("failed to alloc trace log str buffer\n"); + return; + } + + do { + write_interrupt_trace_log(log_str_buffer); + msleep(LOGGER_INTERVAL); + } while(g_interrupt_trace_log_work_state == LOGGER_RUNNING); + if (log_str_buffer != NULL) + kfree(log_str_buffer); +} + +void interrupt_trace_start(void) +{ + if (!g_trace_log_work_inited) { + INIT_DEFERRABLE_WORK((struct delayed_work *) + (uintptr_t)&g_interrupt_trace_log_work, interrupt_trace_logger); + g_trace_log_work_inited = true; + } + + init_tee_trace_view(); + refresh_int_trace_log(); + + if (g_interrupt_trace_log_work_state == LOGGER_NOT_RUNNING) { + g_interrupt_trace_log_work_state = LOGGER_RUNNING; + schedule_delayed_work(&g_interrupt_trace_log_work, + usecs_to_jiffies(S_TO_US)); + } +} + +void interrupt_trace_stop(void) +{ + g_interrupt_trace_log_work_state = LOGGER_NOT_RUNNING; + close_trace_log(); +} + +void free_interrupt_trace(void) +{ + if (g_trace_log_work_inited) { + cancel_delayed_work(&g_interrupt_trace_log_work); + g_trace_log_work_inited = false; + } +} diff --git a/tzdriver_internal/tee_trace_event/tee_trace_interrupt.h b/tzdriver_internal/tee_trace_event/tee_trace_interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..4332b1d9a2dff0b818f2d07b01ded5a11a96b3e9 --- /dev/null +++ b/tzdriver_internal/tee_trace_event/tee_trace_interrupt.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef TEE_TRACE_INTERRUPT_H +#define TEE_TRACE_INTERRUPT_H + +#define LOGGER_INTERVAL 2000 +#define LOGGER_RUNNING 1 +#define LOGGER_NOT_RUNNING 0 + +#ifndef CONFIG_INT_TRACE_LOG_PATH +#define CONFIG_INT_TRACE_LOG_PATH "/data/log/tee/int_trace" +#endif + +#ifndef CONFIG_EVENT_TRACE_LOG_PATH +#define CONFIG_EVENT_TRACE_LOG_PATH "/data/log/tee/event_trace" +#endif + +#define TRACE_LOG_OPEN_FILE_MODE 0640U +#define LOG_STR_BUFFER_LEN 256 + +void interrupt_trace_start(void); +void interrupt_trace_stop(void); +void free_interrupt_trace(void); +#endif diff --git a/core/agent_allowed_ca.c b/tzdriver_internal/whitelist/agent_allowed_ca.c similarity index 38% rename from core/agent_allowed_ca.c rename to tzdriver_internal/whitelist/agent_allowed_ca.c index 6e4365edb002d26993703dc4fe823530a95f3dff..d73066d9c8d28965535e9e188b0cc42cdb1fa847 100644 --- a/core/agent_allowed_ca.c +++ b/tzdriver_internal/whitelist/agent_allowed_ca.c @@ -1,67 +1,59 @@ -/* - * agent_allowed_ca.c - * - * allowed_ext_agent_ca list and functions - * - * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "agent.h" -#include -#include -#include - -static struct ca_info g_allowed_ext_agent_ca[] = {}; - -int is_allowed_agent_ca(const struct ca_info *ca, bool check_agent_id) -{ - uint32_t i; - struct ca_info *tmp_ca = g_allowed_ext_agent_ca; - const uint32_t nr = ARRAY_SIZE(g_allowed_ext_agent_ca); - - if (!ca) - return -EFAULT; - - if (!check_agent_id) { - for (i = 0; i < nr ; i++) { - if (!strncmp(ca->path, tmp_ca->path, strlen(tmp_ca->path) + 1) && - ca->uid == tmp_ca->uid) - return 0; - tmp_ca++; - } - } else { - for (i = 0; i < nr ; i++) { - if (!strncmp(ca->path, tmp_ca->path, strlen(tmp_ca->path) + 1) && - ca->uid == tmp_ca->uid && ca->agent_id == tmp_ca->agent_id) - return 0; - tmp_ca++; - } - } - tlogd("ca-uid is %u, ca_path is %s, agent id is %x\n", ca->uid, ca->path, ca->agent_id); - return -EACCES; -} - -bool is_third_party_agent(unsigned int agent_id) -{ - uint32_t i; - struct ca_info *tmp_ca = g_allowed_ext_agent_ca; - const uint32_t nr = ARRAY_SIZE(g_allowed_ext_agent_ca); - - for (i = 0; i < nr; i++) { - if (tmp_ca->agent_id == agent_id) - return true; - tmp_ca++; - } - - return false; -} +/* + * agent_allowed_ca.c + * + * allowed_ext_agent_ca list and functions + * + * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "agent.h" +#include +#include +#include + +static struct ca_info g_allowed_ext_agent_ca[] = {}; + +int is_allowed_agent_ca(const struct ca_info *ca, + bool check_agent_id) +{ + uint32_t i; + struct ca_info *tmp_ca = g_allowed_ext_agent_ca; + const uint32_t nr = ARRAY_SIZE(g_allowed_ext_agent_ca); + + if (!ca) + return -EFAULT; + + if (!check_agent_id) { + for (i = 0; i < nr; i++) { + if (!strncmp(ca->path, tmp_ca->path, + strlen(tmp_ca->path) + 1) && + ca->uid == tmp_ca->uid) + return 0; + tmp_ca++; + } + } else { + for (i = 0; i < nr; i++) { + if (!strncmp(ca->path, tmp_ca->path, + strlen(tmp_ca->path) + 1) && + ca->uid == tmp_ca->uid && + ca->agent_id == tmp_ca->agent_id) + return 0; + tmp_ca++; + } + } + tlogd("ca-uid is %u, ca_path is %s, agent id is %x\n", ca->uid, + ca->path, ca->agent_id); + + return -EACCES; +} +