diff --git a/Makefile b/Makefile index f9f1e165eac9b9fd0a96e4b0a3559a086a2c8eb7..839d8d6120f7949e32b1e88647d7ff3c37e7cbe7 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ obj-m := tzdriver.o CONFIG_FFA_SUPPORT := 0 CONFIG_TEE_TELEPORT_SUPPORT := y CONFIG_CONFIDENTIAL_CONTAINER ?= y +CROSS_DOMAIN_PERF := y 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/tzdebug.o core/tz_spi_notify.o core/tz_pm.o core/tee_compat_check.o @@ -15,6 +16,9 @@ tzdriver-objs += tzdriver_internal/tee_reboot/reboot.o ifeq ($(CONFIG_TEE_TELEPORT_SUPPORT), y) tzdriver-objs += core/tee_portal.o +ifeq ($(CROSS_DOMAIN_PERF), y) +tzdriver-objs += core/tee_posix_proxy.o +endif EXTRA_CFLAGS += -DCONFIG_TEE_TELEPORT_SUPPORT -DCONFIG_TEE_TELEPORT_AUTH EXTRA_CFLAGS += -DTEE_TELEPORT_PATH_UID_AUTH_CTX=\"/usr/bin/tee_teleport:0\" tzdriver-objs += core/tc_cvm_driver.o @@ -53,6 +57,9 @@ EXTRA_CFLAGS += -DCONFIG_AUTH_SUPPORT_UNAME -DCONFIG_AUTH_HASH -std=gnu99 EXTRA_CFLAGS += -DCONFIG_TEE_UPGRADE -DCONFIG_TEE_REBOOT -DCONFIG_CONFIDENTIAL_TEE EXTRA_CFLAGS += -I$(PWD)/tzdriver_internal/tee_reboot EXTRA_CFLAGS += -DMAILBOX_POOL_COUNT=32 +ifeq ($(CROSS_DOMAIN_PERF), y) +EXTRA_CFLAGS += -DCROSS_DOMAIN_PERF +endif all: make -C $(KDIR) M=$(PWD) modules clean: diff --git a/auth/auth_base_impl.c b/auth/auth_base_impl.c index f3479e0fbbc768da426bd160dfa2045330e8aab7..5b366fcd1e76190410f1e205ddf2d983301b14bd 100644 --- a/auth/auth_base_impl.c +++ b/auth/auth_base_impl.c @@ -342,11 +342,13 @@ int check_teecd_auth(void) #ifdef CONFIG_TEE_TELEPORT_AUTH int check_tee_teleport_auth(void) { - int ret = check_proc_uid_path(TEE_TELEPORT_PATH_UID_AUTH_CTX); +#if defined(CONFIG_SELINUX_AUTH_ENABLE) && defined(CONFIG_SECURITY_SELINUX) + int ret = check_proc_selinux_access(SELINUX_TEE_TELEPORT_LABEL); if (ret != 0) { - tlogd("check tee_teleport path failed, ret %d\n", ret); - return ret; + tloge("check tee_teleport selinux label failed, ret %d\n", ret) + return -EACCES; } +#endif return CHECK_ACCESS_SUCC; } #endif diff --git a/core/shared_mem.c b/core/shared_mem.c index dd169bead5437f5ed95ce368dc6603633c10e8aa..fa50e7f292643224147c0bdcfa494ade1d9e7c7d 100644 --- a/core/shared_mem.c +++ b/core/shared_mem.c @@ -116,6 +116,26 @@ void release_shared_mem_page(uint64_t buf, uint32_t buf_size) put_page(page); } } +#else + +int fill_shared_mem_info(uint64_t start_vaddr, uint32_t pages_no, + uint32_t offset, uint32_t buffer_size, uint64_t info_addr) +{ + (void)start_vaddr; + (void)pages_no; + (void)offset; + (void)buffer_size; + (void)info_addr; + tloge("shared memory is unsupported\n"); + return -EINVAL; +} + +void release_shared_mem_page(uint64_t buf, uint32_t buf_size) +{ + (void)buf; + (void)buf_size; + tloge("shared memory is unsupported\n"); +} #endif #ifdef CONFIG_SHARED_MEM_RESERVED diff --git a/core/shared_mem.h b/core/shared_mem.h index ab3bc43cfc68601637b6c96049530b6ec27965e7..aece31e5480dc137199eba31eb81e64a4c7f137b 100644 --- a/core/shared_mem.h +++ b/core/shared_mem.h @@ -61,9 +61,8 @@ 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); -#ifdef CONFIG_NOCOPY_SHAREDMEM int fill_shared_mem_info(uint64_t start_vaddr, uint32_t pages_no, uint32_t offset, uint32_t buffer_size, uint64_t info_addr); void release_shared_mem_page(uint64_t buf, uint32_t buf_size); -#endif + #endif diff --git a/core/tc_client_driver.c b/core/tc_client_driver.c index 9cb052c09e60d09b389b728a7cd59aa381d9d0aa..ccc46517df02a0aaefc120274d8331ff77a2b6c5 100644 --- a/core/tc_client_driver.c +++ b/core/tc_client_driver.c @@ -89,6 +89,9 @@ #ifdef CONFIG_TEE_TELEPORT_SUPPORT #include "tee_portal.h" +#ifdef CROSS_DOMAIN_PERF +#include "tee_posix_proxy.h" +#endif #endif #include "tee_info.h" @@ -98,9 +101,6 @@ static struct device_node *g_dev_node; struct dev_node g_tc_client; struct dev_node g_tc_private; -#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) -struct dev_node g_tc_cvm; -#endif #ifdef CONFIG_ACPI static int g_acpi_irq; @@ -115,6 +115,11 @@ struct tc_ns_dev_list g_tc_ns_dev_list; static bool g_init_succ = false; +struct class *get_driver_class(void) +{ + return g_driver_class; +} + static void set_tz_init_flag(void) { g_init_succ = true; @@ -1128,7 +1133,7 @@ static int create_dev_node(struct dev_node *node) return ret; } node->class_dev = device_create(node->driver_class, NULL, node->devt, - NULL, node->node_name); + NULL, "%s", node->node_name); if (IS_ERR_OR_NULL(node->class_dev)) { tloge("class device create failed"); ret = -ENOMEM; @@ -1146,7 +1151,7 @@ chrdev_region_unregister: return ret; } -static int init_dev_node(struct dev_node *node, char *node_name, +int init_dev_node(struct dev_node *node, const char *node_name, struct class *driver_class, const struct file_operations *fops) { int ret = -1; @@ -1162,8 +1167,12 @@ static int init_dev_node(struct dev_node *node, char *node_name, return ret; } -static void destory_dev_node(struct dev_node *node, struct class *driver_class) +void destory_dev_node(struct dev_node *node, struct class *driver_class) { + if (!node || !driver_class) { + tloge("node/driver is NULL\n"); + return; + } device_destroy(driver_class, node->devt); unregister_chrdev_region(node->devt, 1); return; @@ -1189,18 +1198,26 @@ static int enable_dev_nodes(void) } #if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) - ret = cdev_add(&(g_tc_cvm.char_dev), - MKDEV(MAJOR(g_tc_cvm.devt), 0), 1); - if (ret < 0) { - tloge("cdev add failed %d", ret); - cdev_del(&(g_tc_client.char_dev)); - cdev_del(&(g_tc_private.char_dev)); - return ret; + if (is_ccos()) { + ret = init_cvm_node_file(); + if (ret != 0) { + tloge("cdev add failed %d", ret); + cdev_del(&(g_tc_client.char_dev)); + cdev_del(&(g_tc_private.char_dev)); + return ret; + } } #endif return 0; } +static char *tee_devnode(struct device *dev, umode_t *mode) +{ + if (strcmp(dev_name(dev), TC_NS_CVM_DEV) == 0) + *mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + return NULL; +} + static int tc_ns_client_init(void) { int ret; @@ -1225,7 +1242,7 @@ static int tc_ns_client_init(void) ret = -ENOMEM; goto unmap_res_mem; } - + g_driver_class->devnode = tee_devnode; 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); @@ -1238,16 +1255,6 @@ static int tc_ns_client_init(void) goto unmap_res_mem; } -#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) - ret = init_dev_node(&g_tc_cvm, TC_NS_CVM_DEV, g_driver_class, get_cvm_fops()); - if (ret != 0) { - destory_dev_node(&g_tc_private, g_driver_class); - destory_dev_node(&g_tc_client, g_driver_class); - class_destroy(g_driver_class); - goto unmap_res_mem; - } -#endif - INIT_LIST_HEAD(&g_tc_ns_dev_list.dev_file_list); mutex_init(&g_tc_ns_dev_list.dev_lock); init_crypto_hash_lock(); @@ -1268,10 +1275,20 @@ static int tc_teeos_init(struct device *class_dev) return ret; } +#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) + if (is_ccos()) { + ret = init_cvm_node(); + if (ret != 0) { + tloge("init cvm node failed\n"); + goto smc_data_free; + } + } +#endif + ret = tee_init_reboot_thread(); if (ret != 0) { tloge("init reboot thread failed\n"); - goto smc_data_free; + goto cvm_node_free; } ret = reserved_mempool_init(); @@ -1305,7 +1322,12 @@ release_resmem: free_reserved_mempool(); reboot_thread_free: free_reboot_thread(); +cvm_node_free: +#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) + if (is_ccos()) + destroy_cvm_node(); smc_data_free: +#endif free_smc_data(); return ret; } @@ -1370,6 +1392,9 @@ static __init int tc_init(void) #ifdef CONFIG_TEE_TELEPORT_SUPPORT tee_portal_init(); +#ifdef CROSS_DOMAIN_PERF + tee_posix_proxy_init(); +#endif #endif /* @@ -1389,9 +1414,6 @@ static __init int tc_init(void) return 0; class_device_destroy: -#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) - destory_dev_node(&g_tc_cvm, g_driver_class); -#endif destory_dev_node(&g_tc_client, g_driver_class); destory_dev_node(&g_tc_private, g_driver_class); class_destroy(g_driver_class); @@ -1420,7 +1442,7 @@ static void tc_exit(void) * prevent access to the device node when uninstalling "tzdriver". */ #if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) - cdev_del(&(g_tc_cvm.char_dev)); + destroy_cvm_node_file(); #endif cdev_del(&(g_tc_private.char_dev)); cdev_del(&(g_tc_client.char_dev)); @@ -1430,7 +1452,7 @@ static void tc_exit(void) free_tz_spi(g_tc_client.class_dev); /* run-time environment exit should before teeos exit */ #if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) - destory_dev_node(&g_tc_cvm, g_driver_class); + destroy_cvm_node(); #endif destory_dev_node(&g_tc_client, g_driver_class); diff --git a/core/tc_client_driver.h b/core/tc_client_driver.h index 45f758a0ad036ad7f76493d378a84a008ec9bdb2..774fbd30d409e280d0e1f46f9617bcf1695a55a7 100644 --- a/core/tc_client_driver.h +++ b/core/tc_client_driver.h @@ -28,9 +28,18 @@ struct dev_node { dev_t devt; struct device *class_dev; const struct file_operations *fops; - char *node_name; + const char *node_name; }; +struct dev_ops { + bool dev_node_inited; + bool dev_file_inited; + int (*init_dev_node)(struct dev_node *node, const char *node_name, + struct class *driver_class, const struct file_operations *fops); + void (*destroy_dev_node)(struct dev_node *node, struct class *driver_class); +}; + +struct class *get_driver_class(void); bool get_tz_init_flag(void); struct tc_ns_dev_list *get_dev_list(void); struct tc_ns_dev_file *tc_find_dev_file(unsigned int dev_file_id); @@ -38,9 +47,15 @@ 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); int is_agent_alive(unsigned int agent_id, unsigned int nsid); int tc_ns_register_host_nsid(void); +int init_dev_node(struct dev_node *node, const char *node_name, + struct class *driver_class, const struct file_operations *fops); +void destory_dev_node(struct dev_node *node, struct class *driver_class); #if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) -const struct file_operations *get_cvm_fops(void); +int init_cvm_node(void); +int init_cvm_node_file(void); +void destroy_cvm_node_file(void); +void destroy_cvm_node(void); #endif void handle_cmd_prepare(unsigned int cmd); diff --git a/core/tc_cvm_driver.c b/core/tc_cvm_driver.c index fa125b421e1226a5d24284cca37813586587480b..076aab1e3b373e0d84ae98365d123b9b5f9e9fc8 100644 --- a/core/tc_cvm_driver.c +++ b/core/tc_cvm_driver.c @@ -20,8 +20,15 @@ #include #include "auth_base_impl.h" #include "agent.h" +#ifdef CONFIG_CONFIDENTIAL_CONTAINER +#include +#include +#endif #ifdef CONFIG_TEE_TELEPORT_SUPPORT #include "tee_portal.h" +#ifdef CROSS_DOMAIN_PERF +#include "tee_posix_proxy.h" +#endif #endif #include "tee_info.h" @@ -47,8 +54,48 @@ static int tc_cvm_open(struct inode *inode, struct file *file) file->private_data = NULL; ret = tc_ns_client_open(&dev, TEE_REQ_FROM_USER_MODE); - if (ret == 0) + if (ret == 0) { +#ifdef CONFIG_CONFIDENTIAL_CONTAINER + dev->nsid = task_active_pid_ns(current)->ns.inum; +#endif file->private_data = dev; + } + return ret; +} + +static int teleport_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = -EFAULT; + void *argp = (void __user *)(uintptr_t)arg; + uint32_t nsid; + +#ifdef CONFIG_CONFIDENTIAL_CONTAINER + nsid = task_active_pid_ns(current)->ns.inum; + if (file->private_data != NULL) + ((struct tc_ns_dev_file *)file->private_data)->nsid = nsid; + else + return ret; +#else + nsid = PROC_PID_INIT_INO; +#endif + + switch (cmd) { +#ifdef CONFIG_TEE_TELEPORT_SUPPORT + case TC_NS_CLIENT_IOCTL_PORTAL_REGISTER: + ret = tee_portal_register(file->private_data, argp); + break; + case TC_NS_CLIENT_IOCTL_PORTAL_WORK: + ret = tee_portal_work(file->private_data); + break; +#ifdef CROSS_DOMAIN_PERF + case TC_NS_CLIENT_IOCTL_POSIX_PROXY_REGISTER_TASKLET: + ret = tee_posix_proxy_register_tasklet(argp, nsid); + break; +#endif +#endif + default: + tloge("invalid cmd!\n"); + } return ret; } @@ -66,21 +113,32 @@ static long tc_cvm_ioctl(struct file *file, unsigned int cmd, #ifdef CONFIG_TEE_TELEPORT_SUPPORT case TC_NS_CLIENT_IOCTL_PORTAL_REGISTER: + case TC_NS_CLIENT_IOCTL_PORTAL_WORK: +#ifdef CROSS_DOMAIN_PERF + case TC_NS_CLIENT_IOCTL_POSIX_PROXY_REGISTER_TASKLET: +#endif if (check_tee_teleport_auth() == 0) - ret = tee_portal_register(file->private_data, argp); + ret = teleport_ioctl(file, cmd, arg); else tloge("check tee_teleport path failed\n"); break; - case TC_NS_CLIENT_IOCTL_PORTAL_WORK: - if (check_tee_teleport_auth() == 0) - ret = tee_portal_work(file->private_data); +#endif + +#ifdef CONFIG_TEE_AGENTD_AUTH + case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: + case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: + case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: + case TC_NS_CLIENT_IOCTL_WAIT_EVENT: + case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ: + case TC_NS_CLIENT_IOCTL_CHECK_CCOS: + if (check_tee_agentd_auth() == 0) + ret = public_ioctl(file, cmd, arg, false); else - tloge("check tee_teleport path failed\n"); + tloge("check agentd path failed\n"); break; #endif default: - ret = public_ioctl(file, cmd, arg, false); - break; + tloge("invalid cmd!\n"); } handle_cmd_finish(cmd); @@ -109,8 +167,10 @@ static int tc_cvm_close(struct inode *inode, struct file *file) #ifdef CONFIG_TEE_TELEPORT_SUPPORT if (dev->portal_enabled) tee_portal_unregister(file->private_data); +#ifdef CROSS_DOMAIN_PERF + (void)tee_posix_proxy_unregister_all_tasklet(file->private_data); +#endif #endif - if (is_system_agent(dev)) { send_crashed_event_response_single(dev); free_dev(dev); @@ -132,8 +192,78 @@ static const struct file_operations g_cvm_fops = { #endif }; -const struct file_operations *get_cvm_fops(void) +static struct dev_node g_tc_cvm; +static struct dev_ops g_tc_cvm_ops = { + .dev_node_inited = false, + .dev_file_inited = false, + .init_dev_node = init_dev_node, + .destroy_dev_node = destory_dev_node +}; + +int init_cvm_node(void) +{ + int ret = 0; + struct class *driver_class = NULL; + if (g_tc_cvm_ops.dev_node_inited) + return 0; + + driver_class = get_driver_class(); + if (g_tc_cvm_ops.init_dev_node != NULL && g_tc_cvm_ops.destroy_dev_node != NULL && + driver_class != NULL) { + ret = g_tc_cvm_ops.init_dev_node(&g_tc_cvm, TC_NS_CVM_DEV, driver_class, &g_cvm_fops); + if (ret != 0) { + tloge("create tc_ns_cvm device node failed\n"); + return -1; + } + g_tc_cvm_ops.dev_node_inited = true; + return 0; + } + + return -1; +} + +int init_cvm_node_file(void) +{ + int ret = 0; + struct class *driver_class = NULL; + if (!g_tc_cvm_ops.dev_node_inited) + return -1; + + if (g_tc_cvm_ops.dev_file_inited) + return 0; + + ret = cdev_add(&(g_tc_cvm.char_dev), + MKDEV(MAJOR(g_tc_cvm.devt), 0), 1); + if (ret < 0) { + tloge("create /dev/tc_ns_cvm device node file failed\n"); + driver_class = get_driver_class(); + if (g_tc_cvm_ops.destroy_dev_node != NULL && driver_class != NULL) + g_tc_cvm_ops.destroy_dev_node(&g_tc_cvm, driver_class); + g_tc_cvm_ops.dev_node_inited = false; + return ret; + } + g_tc_cvm_ops.dev_file_inited = true; + return 0; +} + +void destroy_cvm_node_file(void) +{ + if (!g_tc_cvm_ops.dev_file_inited) + return; + + cdev_del(&(g_tc_cvm.char_dev)); + g_tc_cvm_ops.dev_file_inited = false; +} + +void destroy_cvm_node(void) { - return &g_cvm_fops; + struct class *driver_class = NULL; + if (!g_tc_cvm_ops.dev_node_inited) + return; + + driver_class = get_driver_class(); + if (g_tc_cvm_ops.destroy_dev_node != NULL && driver_class != NULL) + g_tc_cvm_ops.destroy_dev_node(&g_tc_cvm, driver_class); + g_tc_cvm_ops.dev_node_inited = false; } #endif diff --git a/core/tee_portal.c b/core/tee_portal.c index 7d6418b6c56da48e02bc1d6f70468b8b93e60957..81bd67f8694236d51d809a01ae131eef83857972 100644 --- a/core/tee_portal.c +++ b/core/tee_portal.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #define TEE_PORTAL_EVENT_REGISTER_SHM 0 #define TEE_PORTAL_EVENT_UNREGISTER_SHM 1 @@ -65,10 +67,11 @@ static int send_portal_smc(const struct portal_t *param) smc_cmd.login_data_h_addr = param->mb_h_addr; smc_cmd.login_data_len = param->size; smc_cmd.uid = kuid.val; + smc_cmd.pid = current->tgid; ret = tc_ns_smc(&smc_cmd); if (ret != 0) { - tloge("smc call returns error ret 0x%x\n", smc_cmd.ret_val); + tloge("portal smc call returns error 0x%x\n", smc_cmd.ret_val); if (smc_cmd.ret_val == TEEC_ERROR_SERVICE_NOT_EXIST) return -EOPNOTSUPP; else if (smc_cmd.ret_val == TEEC_ERROR_OUT_OF_MEMORY) @@ -78,27 +81,6 @@ static int send_portal_smc(const struct portal_t *param) return ret; } -#ifndef CONFIG_NOCOPY_SHAREDMEM -static int fill_shared_mem_info(uint64_t start_vaddr, uint32_t pages_no, - uint32_t offset, uint32_t buffer_size, uint64_t info_addr) -{ - (void)start_vaddr; - (void)pages_no; - (void)offset; - (void)buffer_size; - (void)info_addr; - tloge("shared memory is unsupported\n"); - return -EINVAL; -} - -static void release_shared_mem_page(uint64_t buf, uint32_t buf_size) -{ - (void)buf; - (void)buf_size; - tloge("shared memory is unsupported\n"); -} -#endif - static int init_portal_node(struct portal_t *portal, struct agent_ioctl_args *args, void* owner) { int ret = 0; @@ -115,7 +97,7 @@ static int init_portal_node(struct portal_t *portal, struct agent_ioctl_args *ar return -ENOMEM; } - if (fill_shared_mem_info(start_vaddr, page_num, 0, args->buffer_size, (uint64_t)mb_buff)) { + if (fill_shared_mem_info(start_vaddr, page_num, 0, args->buffer_size, (uint64_t)mb_buff) != 0) { tloge("cannot fill shared memory info\n"); mailbox_free(mb_buff); return -EFAULT; @@ -145,6 +127,7 @@ int tee_portal_register(void *owner, void __user *arg) { int ret; struct agent_ioctl_args args; + struct portal_t *portal = NULL; if (owner == NULL || arg == NULL) return -EFAULT; @@ -160,7 +143,6 @@ int tee_portal_register(void *owner, void __user *arg) return -EFAULT; } - struct portal_t *portal; portal = (struct portal_t *)kmalloc(sizeof(struct portal_t), GFP_KERNEL); if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(portal))) { tloge("failed to alloc mem for portal node!\n"); @@ -171,7 +153,8 @@ int tee_portal_register(void *owner, void __user *arg) if (check_portal_exist(owner)) { mutex_unlock(&g_portal_lock); tloge("illegal register request!\n"); - return -EFAULT; + ret = -EFAULT; + goto clean; } ret = init_portal_node(portal, &args, owner); @@ -186,7 +169,7 @@ int tee_portal_register(void *owner, void __user *arg) ret = send_portal_smc(portal); if (ret != 0) { - release_shared_mem_page(portal->buf, portal->size); + release_shared_mem_page((uint64_t)(uintptr_t)portal->buf, portal->size); mailbox_free(portal->buf); mutex_lock(&g_portal_lock); list_del(&portal->list); @@ -206,11 +189,20 @@ clean: int tee_portal_unregister(const void *owner) { int ret; + struct portal_t *pos = NULL; + bool found = false; + uint32_t nsid; + if (!owner) return -EFAULT; - struct portal_t *pos; - bool found = false; +#ifdef CONFIG_CONFIDENTIAL_CONTAINER + struct tc_ns_dev_file *dev = (struct tc_ns_dev_file *)owner; + nsid = dev->nsid; +#else + nsid = PROC_PID_INIT_INO; +#endif + mutex_lock(&g_portal_lock); list_for_each_entry(pos, &g_portal_head.list, list) { if (pos->owner == owner) { @@ -228,7 +220,7 @@ int tee_portal_unregister(const void *owner) pos->event = TEE_PORTAL_EVENT_UNREGISTER_SHM; ret = send_portal_smc(pos); - release_shared_mem_page(pos->buf, pos->size); + release_shared_mem_page((uint64_t)(uintptr_t)pos->buf, pos->size); mailbox_free(pos->buf); list_del(&pos->list); @@ -243,6 +235,9 @@ int tee_portal_work(const void *owner) int ret = -EFAULT; bool found = false; + if (owner == NULL) + return ret; + mutex_lock(&g_portal_lock); list_for_each_entry(pos, &g_portal_head.list, list) { if (pos->owner == owner) { diff --git a/core/tee_portal.h b/core/tee_portal.h index 10c392fa8b8d85e80f18841879a828bdbb5dc56d..d715030f8e46b3f5516f4a9e0f7a6a1f7600ac3b 100644 --- a/core/tee_portal.h +++ b/core/tee_portal.h @@ -11,8 +11,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#ifndef TEE_PORTAL_H -#define TEE_PORTAL_H +#ifndef TEE_PORTAL +#define TEE_PORTAL int tee_portal_register(void *owner, void __user *arg); int tee_portal_unregister(const void *owner); diff --git a/core/tee_posix_proxy.c b/core/tee_posix_proxy.c new file mode 100644 index 0000000000000000000000000000000000000000..698c206641bc65f0493df9792a535ddaec4ebc9e --- /dev/null +++ b/core/tee_posix_proxy.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2023-2023 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 + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define TEE_POSIX_PROXY_EVENT_REGISTER_CTRL_TASKLET 4 + #define TEE_POSIX_PROXY_EVENT_REGISTER_DATA_TASKLET 5 + #define TEE_POSIX_PROXY_EVENT_UNREGISTER_ALL_TASKLET 6 + + struct posix_proxy_shm { + void *buffer; + uint32_t size; + }; + +struct posix_proxy_node { + struct list_head head; + unsigned int nsid; /* namesapce id */ + pid_t tp_pid; /* teleport pid, owner of posix_proxy_node with nsid */ + pid_t tp_ppid; /* teleport parent pid */ + struct posix_proxy_shm *ctrl_shm; + struct posix_proxy_shm *data_shm; + uint32_t event; + atomic_t ref_cnt; +}; + +struct mailbox_info { + void *buf; /* mailbox vaddr */ + uint32_t size; /* mailbox buffer size */ + uint32_t mb_l_addr; /* low of mailbox buffer pyhs addr */ + uint32_t mb_h_addr; /* low of mailbox buffer pyhs addr */ +}; + +struct posix_proxy_control { + struct mutex lock; + struct list_head list; +}; + +static struct posix_proxy_control g_posix_proxy_control; + +static pid_t get_pid_compatible_namespace(struct task_struct *task) +{ + /* Obtain tgid in namespace */ + pid_t namespace_tgid = task_tgid_vnr(task); + + return namespace_tgid; +} + +static int alloc_and_fill_mailbox_info(struct posix_proxy_ioctl_args *args, struct mailbox_info *mb_info) +{ + uint32_t len; + uint32_t page_num; + int ret = 0; + void *mb_buff = NULL; + + page_num = args->buffer_size / PAGE_SIZE; + len = sizeof(struct pagelist_info) + (sizeof(uint64_t) * page_num); + mb_buff = mailbox_alloc(len, MB_FLAG_ZERO); + if (mb_buff == NULL) { + tloge("alloc mailbox mem failed\n"); + return -ENOMEM; + } + + mb_info->mb_l_addr = mailbox_virt_to_phys((uintptr_t)mb_buff); + mb_info->mb_h_addr = (uint64_t)mailbox_virt_to_phys((uintptr_t)mb_buff) >> ADDR_TRANS_NUM; + mb_info->buf = mb_buff; + mb_info->size = len; + + if (fill_shared_mem_info(args->addr, page_num, 0, args->buffer_size, (uint64_t)(uintptr_t)mb_info->buf) != 0) { + tloge("fill shared mem info failed\n"); + mailbox_free(mb_buff); + ret = -EFAULT; + } + + return ret; +} + +static void release_mailbox_info(const struct mailbox_info *mb_info) +{ + if (mb_info->buf != NULL) + mailbox_free(mb_info->buf); +} + +static void destroy_posix_proxy_shm(struct posix_proxy_shm *shm) +{ + if (shm == NULL) + return; + + if (shm->buffer != NULL) { + release_shared_mem_page((uint64_t)(uintptr_t)shm->buffer, shm->size); + kfree(shm->buffer); + } + kfree(shm); +} + +#ifdef DEF_ENG +static void __attribute__((unused)) dump_posix_proxy_list(void) +{ + tloge("==== dump posix_proxy_list start ====\n"); + struct posix_proxy_node *posix_proxy = NULL; + uint32_t i = 0; + list_for_each_entry(posix_proxy, &g_posix_proxy_control.list, head) { + tloge("posix_proxy_node[%d] nsid %d, tp_pid %d\n", i, posix_proxy->nsid, posix_proxy->tp_pid); + i++; + } + tloge("==== dump posix_proxy_list end ====\n"); +} +#endif + +/* Important: must in lock protect */ +static int ref_posix_proxy(struct posix_proxy_node *posix_proxy) +{ + if (posix_proxy == NULL) + return -EINVAL; + + if (atomic_read(&posix_proxy->ref_cnt) == INT_MAX) { + tloge("posix proxy ref_cnt is out of limit\n"); + return -EBADFD; + } + + (void)atomic_inc(&posix_proxy->ref_cnt); + return 0; +} + +static void deref_posix_proxy(struct posix_proxy_node *posix_proxy) +{ + if (posix_proxy == NULL) + return; + + mutex_lock(&g_posix_proxy_control.lock); + /* unreachable branch */ + if (atomic_read(&posix_proxy->ref_cnt) == 0) { + tloge("deref failed due to posix proxy's ref_cnt is zero\n"); + mutex_unlock(&g_posix_proxy_control.lock); + return; + } + + if (atomic_dec_and_test(&posix_proxy->ref_cnt)) { + if (list_empty(&posix_proxy->head) == 0) + list_del(&posix_proxy->head); + if (posix_proxy->ctrl_shm != NULL) + destroy_posix_proxy_shm(posix_proxy->ctrl_shm); + if (posix_proxy->data_shm != NULL) + destroy_posix_proxy_shm(posix_proxy->data_shm); + + kfree(posix_proxy); + } + + mutex_unlock(&g_posix_proxy_control.lock); +} + +static int send_posix_proxy_smc(const struct posix_proxy_node *posix_proxy, const struct mailbox_info *mb_info) +{ + struct tc_ns_smc_cmd smc_cmd = { { 0 }, 0 }; + int ret = 0; + struct tc_uuid appmgr_uuid = TEE_SERVICE_APPMGR; + + if (posix_proxy == NULL || posix_proxy->event < TEE_POSIX_PROXY_EVENT_REGISTER_CTRL_TASKLET || + posix_proxy->event > TEE_POSIX_PROXY_EVENT_UNREGISTER_ALL_TASKLET) { + tloge("bad params for posix proxy\n"); + return -EINVAL; + } + + (void)memcpy_s(&smc_cmd.uuid, sizeof(struct tc_uuid), &appmgr_uuid, sizeof(struct tc_uuid)); + smc_cmd.cmd_type = CMD_TYPE_GLOBAL; + smc_cmd.cmd_id = GLOBAL_CMD_ID_PORTAL_WORK; + smc_cmd.eventindex = posix_proxy->event; + smc_cmd.pid = posix_proxy->tp_pid; + /* temporilay use agent_id store teleport's parent pid */ + smc_cmd.agent_id = posix_proxy->tp_ppid; + + if (posix_proxy->event == TEE_POSIX_PROXY_EVENT_REGISTER_CTRL_TASKLET || + posix_proxy->event == TEE_POSIX_PROXY_EVENT_REGISTER_DATA_TASKLET) { + smc_cmd.login_data_phy = mb_info->mb_l_addr; + smc_cmd.login_data_h_addr = mb_info->mb_h_addr; + smc_cmd.login_data_len = mb_info->size; + } + /* smc_cmd.ca_pid and smc_cmd.nsid will set in tc_ns_smc() */ + + ret = tc_ns_smc(&smc_cmd); + if (ret != 0) { + tloge("smc calll return error, ret 0x%x\n", smc_cmd.ret_val); + if (smc_cmd.ret_val == TEEC_ERROR_SERVICE_NOT_EXIST) + return -EOPNOTSUPP; + else if (smc_cmd.ret_val == TEEC_ERROR_OUT_OF_MEMORY) + return -ENOMEM; + } + + return ret; +} + +/* find_posix_proxy_node_by_tgid will add ref_cnt */ +static struct posix_proxy_node *find_posix_proxy_node_by_tgid(unsigned int nsid, pid_t tgid) +{ + struct posix_proxy_node *posix_proxy = NULL; + mutex_lock(&g_posix_proxy_control.lock); + list_for_each_entry(posix_proxy, &g_posix_proxy_control.list, head) { + if (posix_proxy->nsid == nsid && posix_proxy->tp_pid == tgid) { + if (ref_posix_proxy(posix_proxy) != 0) + break; + mutex_unlock(&g_posix_proxy_control.lock); + return posix_proxy; + } + } + mutex_unlock(&g_posix_proxy_control.lock); + return NULL; +} + +static void add_posix_proxy_node_to_list(struct posix_proxy_node *posix_proxy) +{ + mutex_lock(&g_posix_proxy_control.lock); + list_add_tail(&posix_proxy->head, &g_posix_proxy_control.list); + mutex_unlock(&g_posix_proxy_control.lock); +} + +static int alloc_posix_proxy_node(unsigned int nsid, struct posix_proxy_node **posix_proxy) +{ + *posix_proxy = (struct posix_proxy_node *)kzalloc(sizeof(struct posix_proxy_node), GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*posix_proxy))) { + tloge("alloc mem for posix proxy node failed\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&(*posix_proxy)->head); + (*posix_proxy)->nsid = nsid; + (*posix_proxy)->tp_pid = get_pid_compatible_namespace(current); + (*posix_proxy)->tp_ppid = get_pid_compatible_namespace(current->parent); + (*posix_proxy)->event = -1; + (*posix_proxy)->ctrl_shm = NULL; + (*posix_proxy)->data_shm = NULL; + atomic_set(&(*posix_proxy)->ref_cnt, 1); + return 0; +} + +static int add_shm_to_posix_proxy(struct posix_proxy_node *posix_proxy, struct mailbox_info *mb_info, + enum posix_proxy_shm_type shm_type) +{ + struct posix_proxy_shm *shm = NULL; + int ret = 0; + + shm = kzalloc(sizeof(struct posix_proxy_shm), GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)shm)) { + tloge("alloc shm buff failed\n"); + return -ENOMEM; + } + + shm->buffer = kzalloc(mb_info->size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)shm->buffer)) { + tloge("kzalloc failed\n"); + ret = -ENOMEM; + goto clear; + } + + (void)memcpy_s(shm->buffer, mb_info->size, mb_info->buf, mb_info->size); + shm->size = mb_info->size; + + if (shm_type == CTRL_TASKLET_BUFF) + posix_proxy->ctrl_shm = shm; + else + posix_proxy->data_shm = shm; + goto end; + +clear: + kfree(shm); +end: + return ret; +} + +static int send_ctrl_tasklet_register(unsigned int nsid, struct posix_proxy_ioctl_args *args) +{ + int ret = 0; + struct mailbox_info mb_info = { 0 }; + struct posix_proxy_node *posix_proxy = NULL; + + posix_proxy = find_posix_proxy_node_by_tgid(nsid, get_pid_compatible_namespace(current)); + if (posix_proxy != NULL) { + tloge("find a duplicate node with the same teleport pid when register ctrl tasklet\n"); + deref_posix_proxy(posix_proxy); + return -EEXIST; + } + + ret = alloc_and_fill_mailbox_info(args, &mb_info); + if (ret != 0) { + tloge("cannot fill ctrl tasklet info to mailbox\n"); + return ret; + } + + ret = alloc_posix_proxy_node(nsid, &posix_proxy); + if (ret != 0) { + tloge("alloc posix_proxy node for ctrl tasklet failed\n"); + release_shared_mem_page((uint64_t)(uintptr_t)mb_info.buf, mb_info.size); + goto end; + } + + ret = add_shm_to_posix_proxy(posix_proxy, &mb_info, CTRL_TASKLET_BUFF); + if (ret != 0) { + tloge("add shm buff info to posix_proxy failed\n"); + release_shared_mem_page((uint64_t)(uintptr_t)mb_info.buf, mb_info.size); + goto destroy_posix_proxy; + } + + posix_proxy->event = TEE_POSIX_PROXY_EVENT_REGISTER_CTRL_TASKLET; + + ret = send_posix_proxy_smc(posix_proxy, &mb_info); + if (ret != 0) { + tloge("send register tasklet request to gtask failed, shm_type %d, ret = %d\n", args->shm_type, ret); + goto destroy_posix_proxy; + } else { + add_posix_proxy_node_to_list(posix_proxy); + } + + goto end; + +destroy_posix_proxy: + /* destroy_posix_proxy_shm func will release shm buf page */ + destroy_posix_proxy_shm(posix_proxy->ctrl_shm); + kfree(posix_proxy); +end: + release_mailbox_info(&mb_info); + return ret; +} + +static int send_data_tasklet_register(unsigned int nsid, struct posix_proxy_ioctl_args *args) +{ + int ret = 0; + struct mailbox_info mb_info = { 0 }; + struct posix_proxy_node *posix_proxy = NULL; + + posix_proxy = find_posix_proxy_node_by_tgid(nsid, get_pid_compatible_namespace(current)); + if (posix_proxy == NULL) { + tloge("expected posix proxy node is NULL when register data tasklet\n"); + return -ENOENT; + } + + ret = alloc_and_fill_mailbox_info(args, &mb_info); + if (ret != 0) { + tloge("cannot fill ctrl tasklet info to mailbox\n"); + goto end; + } + struct posix_proxy_shm *old_shm = posix_proxy->data_shm; + + ret = add_shm_to_posix_proxy(posix_proxy, &mb_info, DATA_TASKLET_BUFF); + if (ret != 0) { + tloge("add shm buffer info to posix proxy failed\n"); + release_shared_mem_page((uint64_t)(uintptr_t)mb_info.buf, mb_info.size); + goto end; + } + + posix_proxy->event = TEE_POSIX_PROXY_EVENT_REGISTER_DATA_TASKLET; + + ret = send_posix_proxy_smc(posix_proxy, &mb_info); + if (ret != 0) { + tloge("send register tasklet request to gtask failed, shm_type %d, ret = %d\n", args->shm_type, ret); + goto free_data_shm; + } + destroy_posix_proxy_shm(old_shm); + goto end; + +free_data_shm: + /* destroy_posix_proxy_shm func will release shm buff page */ + destroy_posix_proxy_shm(posix_proxy->data_shm); + /* restore old data shm */ + posix_proxy->data_shm = old_shm; +end: + deref_posix_proxy(posix_proxy); + release_mailbox_info(&mb_info); + return ret; +} + +/* 256MB, the configuration is the same as that in teleport */ +#define MAX_TASKLET_BUFF_SIZE (256 * 1024 * 1024) + +static bool posix_proxy_user_args_check(struct posix_proxy_ioctl_args *args) +{ + bool invalid = true; + if (args->shm_type == CTRL_TASKLET_BUFF) + invalid = args->addr == 0 || args->addr % PAGE_SIZE != 0 || args->buffer_size != PAGE_SIZE; + else if (args->shm_type == DATA_TASKLET_BUFF) + invalid = args->addr == 0 || args->addr % PAGE_SIZE != 0 || args->buffer_size % PAGE_SIZE != 0 || + args->buffer_size > MAX_TASKLET_BUFF_SIZE || args->buffer_size == 0; + else + tloge("bad type for shm\n"); + + return invalid; +} + +/* send create crtl or data tasklet request to gtask */ +int tee_posix_proxy_register_tasklet(void __user *arg, unsigned int nsid) +{ + int ret = 0; + struct posix_proxy_ioctl_args args = { 0 }; + if (arg == NULL || copy_from_user(&args, (void *)(uintptr_t)arg, sizeof(args)) != 0) { + tloge("arg is NULL or copy posix proxy args failed\n"); + return -EINVAL; + } + + if (posix_proxy_user_args_check(&args)) { + tloge("bad memory addr or size or shm_type\n"); + return -EINVAL; + } + + if (args.shm_type == CTRL_TASKLET_BUFF) { + ret = send_ctrl_tasklet_register(nsid, &args); + } else if (args.shm_type == DATA_TASKLET_BUFF) { + ret = send_data_tasklet_register(nsid, &args); + } else { + tloge("invalid register cmd\n"); + ret = -EINVAL; + } + + return ret; +} + +/* send destroy all tasket request to gtask */ +int tee_posix_proxy_unregister_all_tasklet(const void *owner) +{ + if (owner == NULL) { + tloge("bad param\n"); + return -EINVAL; + } + + int ret = 0; + uint32_t nsid; +#ifdef CONFIG_CONFIDENTIAL_CONTAINER + struct tc_ns_dev_file *dev = (struct tc_ns_dev_file *)owner; + nsid = dev->nsid; +#else + nsid = PROC_ID_INIT_INO; +#endif + pid_t tp_pid = get_pid_compatible_namespace(current); + struct posix_proxy_node *posix_proxy = find_posix_proxy_node_by_tgid(nsid, tp_pid); + if (posix_proxy == NULL) { + tlogd("cannot find posix proxy node, unregister failed\n"); + return -ENOENT; + } + + posix_proxy->event = TEE_POSIX_PROXY_EVENT_UNREGISTER_ALL_TASKLET; + + ret = send_posix_proxy_smc(posix_proxy, NULL); + if (ret < 0) { + tloge("send unregister all tasklet request to gtask failed, ret = %d\n", ret); + deref_posix_proxy(posix_proxy); + return ret; + } + + tlogd("destroy_posix_proxy node nsid %u, tp_pid %d, host tp_pid %d\n", nsid, tp_pid, current->tgid); + /* sub ref_cnt for previous find_posix_proxy_node_by_tgid */ + deref_posix_proxy(posix_proxy); + /* sub to zero to destroy posix proxy */ + deref_posix_proxy(posix_proxy); + return ret; +} + +void tee_posix_proxy_init(void) +{ + mutex_init(&g_posix_proxy_control.lock); + INIT_LIST_HEAD(&g_posix_proxy_control.list); +} diff --git a/core/tee_posix_proxy.h b/core/tee_posix_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..3a629657c043bb97503dde71c471fa59c7fd92b8 --- /dev/null +++ b/core/tee_posix_proxy.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023-2023 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_POSIX_PROXY_H +#define TEE_POSIX_PROXY_H + +int tee_posix_proxy_register_tasklet(void __user *arg, unsigned int nsid); +int tee_posix_proxy_unregister_all_tasklet(const void *owner); + +void tee_posix_proxy_init(void); + +#endif \ No newline at end of file diff --git a/tc_ns_client.h b/tc_ns_client.h index 1152a3285f3b5a7eac0a8191ff95d843e221ea4d..fc329f078610da68a80aa42fd51eb53a97276afe 100644 --- a/tc_ns_client.h +++ b/tc_ns_client.h @@ -128,6 +128,22 @@ struct load_secfile_ioctl_struct { }; }__attribute__((packed)); +#ifdef CROSS_DOMAIN_PERF +enum posix_proxy_shm_type { + CTRL_TASKLET_BUFF = 1, + DATA_TASKLET_BUFF +}; + +struct posix_proxy_ioctl_args { + enum posix_proxy_shm_type shm_type; + uint32_t buffer_size; + union { + void *buffer; + unsigned long long addr; + }; +}; +#endif + struct agent_ioctl_args { uint32_t id; uint32_t buffer_size; @@ -206,6 +222,10 @@ struct tc_ns_log_pool { _IOWR(TC_NS_CLIENT_IOC_MAGIC, 24, struct agent_ioctl_args) #define TC_NS_CLIENT_IOCTL_PORTAL_WORK \ _IOWR(TC_NS_CLIENT_IOC_MAGIC, 25, struct agent_ioctl_args) +#ifdef CROSS_DOMAIN_PERF +#define TC_NS_CLIENT_IOCTL_POSIX_PROXY_REGISTER_TASKLET \ + _IOWR(TC_NS_CLIENT_IOC_MAGIC, 27, struct posix_proxy_ioctl_args) +#endif #endif #define TC_NS_CLIENT_IOCTL_GET_TEE_INFO \ _IOWR(TC_NS_CLIENT_IOC_MAGIC, 26, struct tc_ns_tee_info) diff --git a/tzdriver_internal/tee_reboot/reboot.c b/tzdriver_internal/tee_reboot/reboot.c index 520e7ccb87bb24b3da7345da9a4553966ac32dc6..e539825dd7a8474b12cea2b418de704d63c2a5c9 100644 --- a/tzdriver_internal/tee_reboot/reboot.c +++ b/tzdriver_internal/tee_reboot/reboot.c @@ -29,6 +29,7 @@ #include "ko_adapt.h" #include "tz_kthread_affinity.h" #include "tc_client_driver.h" +#include "tee_compat_check.h" #include #include @@ -333,6 +334,13 @@ int tee_reboot(void) tee_alarm_clear(TEE_CRASH); kill_teecd_and_tlogcat(); +#if defined(CONFIG_CONFIDENTIAL_CONTAINER) || defined(CONFIG_TEE_TELEPORT_SUPPORT) + if (is_ccos()) { + (void)init_cvm_node(); + (void)init_cvm_node_file(); + } +#endif + return 0; err: