diff --git a/Makefile b/Makefile index b6d490ab9054419b5c4abd9e79511d9acc507aaf..89593470ff1d2516e6ef01e5da44e2578b71efee 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ EXTRA_CFLAGS += -I$(PWD)/libboundscheck/include/ -I$(PWD) -I$(PWD)/auth -I$(PWD) 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=100 -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 -DCONFIG_TA_AFFINITY=y -DCONFIG_TA_AFFINITY_CPU_NUMS=128 +EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM -DCONFIG_REGISTER_SHAREDMEM -DCONFIG_TA_AFFINITY=y -DCONFIG_TA_AFFINITY_CPU_NUMS=128 EXTRA_CFLAGS += -DTEECD_PATH_UID_AUTH_CTX=\"/usr/bin/teecd:0\" EXTRA_CFLAGS += -DCONFIG_AUTH_SUPPORT_UNAME -DCONFIG_AUTH_HASH -std=gnu99 EXTRA_CFLAGS += -DCONFIG_TEE_UPGRADE -DCONFIG_TEE_REBOOT -DCONFIG_CONFIDENTIAL_TEE diff --git a/core/cmdmonitor.c b/core/cmdmonitor.c index 431e3796dd68b76253638a6f5ea36786447a7dfa..4b19f7bc335c3b8a5e010299d9604106c5c4157d 100644 --- a/core/cmdmonitor.c +++ b/core/cmdmonitor.c @@ -333,6 +333,14 @@ struct cmd_monitor *cmd_monitor_log(const struct tc_ns_smc_cmd *cmd) pid = current->tgid; tid = current->pid; +/* It is normal for portal applications to be stuck for a long time. +* We do not need to add them to monitor list for checking. For example, if it starts a server, +* it will wait for a long time until the client connects. */ +#ifdef CONFIG_TEE_TELEPORT_SUPPORT + if (cmd->cmd_id == GLOBAL_CMD_ID_PORTAL_WORK) + return NULL; +#endif + mutex_lock(&g_cmd_monitor_lock); do { list_for_each_entry(monitor, &g_cmd_monitor_list, list) { @@ -368,8 +376,7 @@ struct cmd_monitor *cmd_monitor_log(const struct tc_ns_smc_cmd *cmd) monitor->lastcmdid = cmd->cmd_id; /* the first cmd will cause timer */ if (g_cmd_monitor_list_size == 1) - schedule_cmd_monitor_work(&g_cmd_monitor_work, - usecs_to_jiffies(S_TO_US)); + schedule_cmd_monitor_work(&g_cmd_monitor_work, usecs_to_jiffies(S_TO_US)); } } while (0); mutex_unlock(&g_cmd_monitor_lock); diff --git a/core/gp_ops.c b/core/gp_ops.c index 3889ad0866df21ed44806d6e714a8cba0b6ae852..7b0e181e024ee565d935edfdec54839030bb81df 100644 --- a/core/gp_ops.c +++ b/core/gp_ops.c @@ -120,6 +120,20 @@ bool is_tmp_mem(uint32_t param_type) return false; } +bool is_shared_mem(uint32_t param_type) +{ + (void)param_type; +#ifdef CONFIG_NOCOPY_SHAREDMEM + if (param_type == TEEC_MEMREF_SHARED_INOUT) + return true; +#endif +#ifdef CONFIG_REGISTER_SHAREDMEM + if (param_type == TEEC_MEMREF_REGISTER_INOUT) + return true; +#endif + return false; +} + bool is_ref_mem(uint32_t param_type) { if (param_type == TEEC_MEMREF_PARTIAL_INPUT || @@ -142,101 +156,6 @@ bool is_val_param(uint32_t param_type) return false; } -static bool is_mem_param(uint32_t param_type) -{ - if (is_tmp_mem(param_type) || is_ref_mem(param_type)) - return true; - - return false; -} - -/* Check the size and buffer addresses have valid userspace addresses */ -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)size_addr, sizeof(uint32_t)) == 0) -#else - if (access_ok((void *)(uintptr_t)size_addr, sizeof(uint32_t)) == 0) -#endif - return false; - - 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)buffer_addr, size) == 0) -#else - if (access_ok((void *)(uintptr_t)buffer_addr, size) == 0) -#endif - return false; - - return true; -} - -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)a_addr, sizeof(uint32_t)) == 0) -#else - 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)b_addr, sizeof(uint32_t)) == 0) -#else - if (access_ok((void *)(uintptr_t)b_addr, sizeof(uint32_t)) == 0) -#endif - return false; - - return true; -} - -bool tc_user_param_valid(struct tc_ns_client_context *client_context, - unsigned int index) -{ - union tc_ns_client_param *client_param = NULL; - unsigned int param_type; - - if (check_user_param(client_context, index) != 0) - return false; - - client_param = &(client_context->params[index]); - param_type = teec_param_type_get(client_context->param_types, index); - tlogd("param %u type is %x\n", index, param_type); - if (param_type == TEEC_NONE) { - tlogd("param type is TEEC_NONE\n"); - return true; - } - - if (is_mem_param(param_type)) { - if (!is_usr_refmem_valid(client_param)) - return false; - } else if (is_val_param(param_type)) { - if (!is_usr_valmem_valid(client_param)) - return false; - } else { - tloge("param types is not supported\n"); - return false; - } - - return true; -} - /* * These function handle read from client. Because client here can be * kernel client or user space client, we must use the proper function @@ -678,10 +597,9 @@ static int alloc_operation(const struct tc_call_params *call_params, { int ret = 0; uint32_t index; - uint8_t kernel_params; + uint8_t kernel_params = call_params->dev->kernel_api; uint32_t param_type; - kernel_params = call_params->dev->kernel_api; for (index = 0; index < TEE_PARAM_NUM; index++) { /* * Normally kernel_params = kernel_api @@ -694,8 +612,6 @@ static int alloc_operation(const struct tc_call_params *call_params, kernel_params = TEE_REQ_FROM_KERNEL_MODE; param_type = teec_param_type_get( call_params->context->param_types, index); - - tlogd("param %u type is %x\n", index, param_type); if (teec_tmpmem_type(param_type, INOUT)) ret = alloc_for_tmp_mem(call_params, op_params, kernel_params, param_type, index); @@ -711,7 +627,11 @@ static int alloc_operation(const struct tc_call_params *call_params, else if (param_type == TEEC_ION_SGLIST_INPUT) ret = alloc_for_ion_sglist(call_params, op_params, kernel_params, param_type, index); - else if (param_type == TEEC_MEMREF_SHARED_INOUT) + else if (param_type == TEEC_MEMREF_SHARED_INOUT +#ifdef CONFIG_REGISTER_SHAREDMEM + || param_type == TEEC_MEMREF_REGISTER_INOUT +#endif + ) ret = transfer_shared_mem(call_params, op_params, kernel_params, param_type, index); else @@ -921,11 +841,11 @@ static void free_operation_params(const struct tc_call_params *call_params, stru for (index = 0; index < TEE_PARAM_NUM; index++) { param_type = teec_param_type_get(call_params->context->param_types, index); - if (is_tmp_mem(param_type)) { + if (is_tmp_mem(param_type) || param_type == TEEC_ION_SGLIST_INPUT) { /* free temp buffer */ temp_buf = local_tmpbuf[index].temp_buffer; tlogd("free temp buf, i = %u\n", index); -#ifndef CONFIG_SHARED_MEM_RESERVED +#if (!defined(CONFIG_LIBLINUX)) && (!defined(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; @@ -943,20 +863,13 @@ static void free_operation_params(const struct tc_call_params *call_params, stru put_sharemem_struct(operation->sharemem[index]); if (operation->mb_buffer[index]) mailbox_free(operation->mb_buffer[index]); - } else if (param_type == TEEC_ION_SGLIST_INPUT) { - temp_buf = local_tmpbuf[index].temp_buffer; - tlogd("free ion sglist buf, i = %u\n", index); -#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; + } else if (param_type == TEEC_MEMREF_SHARED_INOUT +#ifdef CONFIG_REGISTER_SHAREDMEM + || param_type == TEEC_MEMREF_REGISTER_INOUT #endif - if (!ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)temp_buf)) { - mailbox_free(temp_buf); - temp_buf = NULL; - } - } else if (param_type == TEEC_MEMREF_SHARED_INOUT) { + ) { #ifdef CONFIG_NOCOPY_SHAREDMEM + tlogd("free_operation_params release nocopy or register shm\n"); temp_buf = local_tmpbuf[index].temp_buffer; if (temp_buf != NULL) { release_shared_mem_page(temp_buf, local_tmpbuf[index].size); diff --git a/core/gp_ops.h b/core/gp_ops.h index 7ecb59119671ce8458e926b9f74a2d976017e587..bc2446e024caad81218759cb09a7e26d476e8c2a 100644 --- a/core/gp_ops.h +++ b/core/gp_ops.h @@ -24,8 +24,6 @@ int write_to_client(void __user *dest, size_t dest_size, const void *src, size_t size, uint8_t kernel_api); int read_from_client(void *dest, size_t dest_size, const void __user *src, size_t size, uint8_t kernel_api); -bool tc_user_param_valid(struct tc_ns_client_context *client_context, - unsigned int index); 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); diff --git a/core/session_manager.c b/core/session_manager.c index d7da21545a7ed4d7c10a5b3b8b718276984a9de8..647cd7925fd68bc95cbd6035bb33371898300a0f 100644 --- a/core/session_manager.c +++ b/core/session_manager.c @@ -556,12 +556,6 @@ static int check_login_method(struct tc_ns_dev_file *dev_file, } tlogd("login method is IDENTIFY\n"); - /* check if usr params 0 and 1 are valid */ - if (dev_file->kernel_api == TEE_REQ_FROM_USER_MODE && - (!tc_user_param_valid(context, (unsigned int)0) || - !tc_user_param_valid(context, (unsigned int)1))) - return -EINVAL; - ret = set_login_information(dev_file, context); if (ret != 0) { tloge("set login information failed ret =%d\n", ret); @@ -1333,6 +1327,20 @@ int tc_ns_close_session(struct tc_ns_dev_file *dev_file, return ret; } +static int check_param_types(struct tc_ns_client_context *context) +{ + int index; + for (index = 0; index < TEE_PARAM_NUM; index++) { + uint32_t param_type = teec_param_type_get(context->param_types, index); + if (param_type == TEEC_MEMREF_REGISTER_INOUT) { + tloge("invoke should not with register shm\n"); + return -EINVAL; + } + } + + return 0; +} + int tc_ns_send_cmd(struct tc_ns_dev_file *dev_file, struct tc_ns_client_context *context) { @@ -1343,8 +1351,8 @@ int tc_ns_send_cmd(struct tc_ns_dev_file *dev_file, dev_file, context, NULL, 0 }; - if (!dev_file || !context) { - tloge("invalid dev_file or context\n"); + if (!dev_file || !context || (check_param_types(context) != 0)) { + tloge("invalid dev_file or context or param_types\n"); return ret; } diff --git a/core/smc_smp.c b/core/smc_smp.c index 8284d3f3948e49c911643a3ae9adb4d8181efd8f..890dfb364b6dd27e1f95ecbfe18d2dbf1acfb6bd 100644 --- a/core/smc_smp.c +++ b/core/smc_smp.c @@ -674,10 +674,19 @@ static void restore_cpu(struct cpumask *old_mask) } #endif -static bool is_ready_to_kill(bool need_kill) +static bool is_ready_to_kill(bool need_kill, uint32_t cmd_id) { - return (need_kill && sigkill_pending(current) && - is_thread_reported(current->pid)); +#ifdef CONFIG_TEE_TELEPORT_SUPPORT + if (cmd_id == GLOBAL_CMD_ID_PORTAL_WORK) { + return (need_kill && sigkill_pending(current)); + } else { + return (need_kill && sigkill_pending(current) && is_thread_reported(current->pid)); + } + +#else + (void)cmd_id; + return (need_kill && sigkill_pending(current) && is_thread_reported(current->pid)); +#endif } static void set_smc_send_arg(struct smc_in_params *in_param, @@ -769,10 +778,16 @@ int send_smc_cmd_rebooting(uint32_t cmd_id, const struct tc_ns_smc_cmd *in_cmd) } #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_send_param { + uint32_t cmd; + unsigned long ops; + unsigned long ca; +}; + +static noinline int smp_smc_send(struct smc_send_param param, + struct smc_cmd_ret *secret, bool need_kill, uint32_t cmd_id) { - struct smc_in_params in_param = { cmd, ops, ca, 0, 0 }; + struct smc_in_params in_param = { param.cmd, param.ops, param.ca, 0, 0 }; struct smc_out_params out_param = {0}; #if (CONFIG_CPU_AFF_NR != 0) struct cpumask old_mask; @@ -782,7 +797,7 @@ static noinline int smp_smc_send(uint32_t cmd, unsigned long ops, unsigned long set_cpu_strategy(&old_mask); #endif retry: - set_smc_send_arg(&in_param, secret, ops); + set_smc_send_arg(&in_param, secret, param.ops); tee_trace_add_event(SMC_SEND, 0); send_smc_cmd(&in_param, &out_param, 0); tee_trace_add_event(SMC_DONE, 0); @@ -802,7 +817,7 @@ retry: * is send but not process, the original cmd has finished. * So we send the terminate cmd in current context. */ - if (is_ready_to_kill(need_kill)) { + if (is_ready_to_kill(need_kill, cmd_id)) { secret->exit = SMC_EXIT_ABORT; tloge("receive kill signal\n"); } else { @@ -1244,8 +1259,9 @@ void fiq_shadow_work_func(uint64_t target) } livepatch_down_read_sem(); - smp_smc_send(TSP_REQUEST, (unsigned long)SMC_OPS_START_FIQSHD, - (unsigned long)(uint32_t)(current->pid), &secret, false); + struct smc_send_param param = {.cmd = TSP_REQUEST, .ops = (unsigned long)SMC_OPS_START_FIQSHD, + .ca = (unsigned long)(uint32_t)(current->pid)}; + smp_smc_send(param, &secret, false, 0); livepatch_up_read_sem(); if (power_down_cc() != 0) @@ -1438,9 +1454,8 @@ static int smp_smc_send_process(struct tc_ns_smc_cmd *cmd, u64 ops, } ca = is_ccos() ? (cmd_index) : ((unsigned long)(uint32_t)(current->pid)); - - ret = smp_smc_send(TSP_REQUEST, (unsigned long)ops, - ca, cmd_ret, ops != SMC_OPS_ABORT_TASK); + struct smc_send_param param = {.cmd = TSP_REQUEST, .ops = (unsigned long)ops, ca}; + ret = smp_smc_send(param, cmd_ret, ops != SMC_OPS_ABORT_TASK, cmd->cmd_id); if (power_down_cc() != 0) { tloge("power down cc failed\n"); diff --git a/teek_client_constants.h b/teek_client_constants.h index e408cd800ad9286d9b0f1bb0be2efb810c2236d5..6919c82ccb362cb62081cfc1c6ae78b5123ef15d 100644 --- a/teek_client_constants.h +++ b/teek_client_constants.h @@ -146,6 +146,7 @@ enum TEEC_ParamType { TEEC_ION_INPUT = 0x08, TEEC_ION_SGLIST_INPUT = 0x09, TEEC_MEMREF_SHARED_INOUT = 0x0a, + TEEC_MEMREF_REGISTER_INOUT = 0x0b, TEEC_MEMREF_WHOLE = 0xc, TEEC_MEMREF_PARTIAL_INPUT = 0xd, TEEC_MEMREF_PARTIAL_OUTPUT = 0xe, @@ -163,6 +164,7 @@ enum TEE_ParamType { TEE_PARAM_TYPE_ION_INPUT = 0x8, TEE_PARAM_TYPE_ION_SGLIST_INPUT = 0x9, TEE_PARAM_TYPE_MEMREF_SHARED_INOUT = 0x0a, + TEE_PARAM_TYPE_MEMREF_REGISTER_INOUT = 0x0b, TEE_PARAM_TYPE_RESMEM_INPUT = 0xc, TEE_PARAM_TYPE_RESMEM_OUTPUT = 0xd, TEE_PARAM_TYPE_RESMEM_INOUT = 0xe diff --git a/tlogger/tlogger.c b/tlogger/tlogger.c index fa5bdda2c62e897e4107602d94b1d1f8b5c49dd2..bf1251c9b4bc6070eb24284e2ac06a32cf51007f 100644 --- a/tlogger/tlogger.c +++ b/tlogger/tlogger.c @@ -791,33 +791,13 @@ static int get_tlogcat_f_stat(const struct file *file) return tlogf_stat; } -static int check_user_arg(unsigned long arg, size_t arg_len) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 18) || \ - LINUX_VERSION_CODE == KERNEL_VERSION(4, 19, 71)) - return (int)access_ok(VERIFY_READ, - (void __user *)(uintptr_t)arg, arg_len); -#else - return (int)access_ok((void __user *)(uintptr_t)arg, arg_len); -#endif -} - static int get_teeos_version(uint32_t cmd, unsigned long arg) { - int ret; - 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 == 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)) != 0) {