diff --git a/CMakeLists.txt b/CMakeLists.txt index cd588797e3d6b2eb30f70c7c36d7c4fb88773dfc..cf887c04d93a739738d874c9f2c9baad468bb3e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ set(KERNEL_DIR ${KPATH}/${KDIR}) 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 "${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} -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") diff --git a/Makefile b/Makefile index 253938d2ab6b9b60cb3e75bb4445cfad11d14a63..09f2fea2d18cc06c2ef1d65298c6e653b3b0c2a0 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ EXTRA_CFLAGS += -I$(PWD)/libboundscheck/include/ -I$(PWD) -I$(PWD)/auth -I$(PWD) EXTRA_CFLAGS += -I$(PWD)/tlogger -I$(PWD)/kthread_affinity EXTRA_CFLAGS += -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM EXTRA_CFLAGS += -DCONFIG_TEE_LOG_ACHIVE_PATH=\"/var/log/tee/last_teemsg\" -EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID +EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM all: make -C $(KDIR) M=$(PWD) modules clean: diff --git a/core/gp_ops.c b/core/gp_ops.c index f73aca0c035c4198ad5d65aca7a2ff28a4006213..881d44cc324a2282ba47aea4a7aabde8006fe97c 100644 --- a/core/gp_ops.c +++ b/core/gp_ops.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include #include #include "teek_client_constants.h" @@ -531,6 +534,133 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, return ret; } +#ifdef CONFIG_NOCOPY_SHAREDMEM +static int fill_shared_mem_info(void *start_vaddr, uint32_t pages_no, + uint32_t offset, uint32_t buffer_size, void *buff) +{ + struct pagelist_info *page_info = NULL; + struct page **pages = NULL; + uint64_t *phys_addr = NULL; + uint32_t page_num; + uint32_t i; + + if (pages_no == 0) + return -EFAULT; + + pages = (struct page **)vmalloc(pages_no * sizeof(uint64_t)); + if (pages == NULL) + return -EFAULT; + + down_read(&(current->mm->mmap_sem)); + page_num = get_user_pages((uintptr_t)start_vaddr, pages_no, FOLL_WRITE, pages, NULL); + up_read(&(current->mm->mmap_sem)); + if (page_num != pages_no) { + tloge("get page phy addr failed\n"); + if (page_num > 0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + release_pages(pages, page_num, 0); +#else + release_pages(pages, page_num); +#endif + vfree(pages); + return -EFAULT; + } + + page_info = buff; + page_info->page_num = pages_no; + page_info->page_size = PAGE_SIZE; + page_info->sharedmem_offset = offset; + page_info->sharedmem_size = buffer_size; + + 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) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + release_pages(pages, page_num, 0); +#else + release_pages(pages, page_num); +#endif + vfree(pages); + return -EFAULT; + } + phys_addr[i] = (uintptr_t)page_to_phys(page); + } + + vfree(pages); + return 0; +} + +static int check_buffer_for_sharedmem(uint32_t *buffer_size, + const union tc_ns_client_param *client_param, uint8_t kernel_params) +{ + if (read_from_client(buffer_size, sizeof(*buffer_size), + (uint32_t __user *)(uintptr_t)client_param->memref.size_addr, + sizeof(uint32_t), kernel_params)) { + tloge("copy sharedmem.size_addr failed\n"); + return -EFAULT; + } + + if (*buffer_size == 0 || *buffer_size > SZ_256M) { + tloge("invalid buffer size\n"); + return -ENOMEM; + } + + return 0; +} + +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) +{ + void *buff = NULL; + void *start_vaddr = NULL; + union tc_ns_client_param *client_param = NULL; + uint32_t buffer_size; + uint32_t pages_no; + uint32_t offset; + uint32_t buff_len; + + 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); + 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; + + buff_len = sizeof(struct pagelist_info) + (sizeof(uint64_t) * pages_no); + 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; + } + + 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.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) +{ + tloge("invalid shared mem type\n"); + return -1; +} +#endif + static int transfer_client_value(const struct tc_call_params *call_params, struct tc_op_params *op_params, uint8_t kernel_params, uint32_t param_type, unsigned int index) @@ -619,6 +749,9 @@ 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) + ret = transfer_shared_mem(call_params, op_params, + kernel_params, param_type, index); else tlogd("param type = TEEC_NONE\n"); @@ -797,6 +930,27 @@ static int update_client_operation(const struct tc_call_params *call_params, return ret; } + +#ifdef CONFIG_NOCOPY_SHAREDMEM +static void release_page(void *buf) +{ + uint32_t i; + uint64_t *phys_addr = NULL; + struct pagelist_info *page_info = NULL; + struct page *page = NULL; + + page_info = buf; + phys_addr = (uint64_t *)buf + (sizeof(*page_info) / sizeof(uint64_t)); + for (i = 0; i < page_info->page_num; i++) { + page = (struct page *)(uintptr_t)phys_to_page(phys_addr[i]); + if (page == NULL) + continue; + 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) { @@ -833,6 +987,14 @@ static void free_operation(const struct tc_call_params *call_params, mailbox_free(temp_buf); temp_buf = NULL; } + } else if (param_type == TEEC_MEMREF_SHARED_INOUT) { +#ifdef CONFIG_NOCOPY_SHAREDMEM + temp_buf = local_tmpbuf[index].temp_buffer; + if (temp_buf != NULL) { + release_page(temp_buf); + mailbox_free(temp_buf); + } +#endif } } } diff --git a/core/gp_ops.h b/core/gp_ops.h index 9a1926988811104c86bb30f33e65656f29d89094..c730e7be2a6e57b96d7b6d914de198a8cc35a2dc 100644 --- a/core/gp_ops.h +++ b/core/gp_ops.h @@ -35,6 +35,13 @@ struct tc_op_params { bool op_inited; }; +struct pagelist_info { + uint64_t page_num; + uint64_t page_size; + uint64_t sharedmem_offset; + uint64_t sharedmem_size; +}; + 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, diff --git a/libboundscheck b/libboundscheck new file mode 160000 index 0000000000000000000000000000000000000000..5701ca210dfb71037f3cb3340166d150917e8a4d --- /dev/null +++ b/libboundscheck @@ -0,0 +1 @@ +Subproject commit 5701ca210dfb71037f3cb3340166d150917e8a4d diff --git a/teek_client_constants.h b/teek_client_constants.h index 6e48e22793228bd36d2947e22ae4fdaaebe3a1ae..cecf27c396424bab12e66e80eb4cc18422ad29f5 100644 --- a/teek_client_constants.h +++ b/teek_client_constants.h @@ -131,6 +131,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_WHOLE = 0xc, TEEC_MEMREF_PARTIAL_INPUT = 0xd, TEEC_MEMREF_PARTIAL_OUTPUT = 0xe, @@ -147,6 +148,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, }; enum TEEC_LoginMethod {