int lib_main_loop(struct core_control *ctl_params) { int sockfd[2]; pid_t new_proc_pid; struct com_msg_open_session *recv_open_msg = NULL; struct com_msg_ta_created new_ta_info; int ret, event_count, i; sigset_t sig_empty_set, sig_block_set; struct epoll_event cur_events[MAX_CURR_EVENTS]; struct ta_loop_arg ta_loop_args = {0}; int shm_fds[4]; int shm_fd_count; memset(&new_ta_info, 0, sizeof(struct com_msg_ta_created)); child_stack = calloc(1, CHILD_STACK_SIZE); if (!child_stack) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (sigemptyset(&sig_empty_set)) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (sigfillset(&sig_block_set)) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (init_epoll()) { OT_LOG(LOG_ERR, "Epoll init failure"); exit(EXIT_FAILURE); } /* listen to inbound connections from the manager */ if (epoll_reg_fd(ctl_params->comm_sock_fd, EPOLLIN)) { OT_LOG(LOG_ERR, "Failed reg manager socket"); exit(EXIT_FAILURE); } if (epoll_reg_fd(ctl_params->self_pipe_fd, EPOLLIN)) { OT_LOG(LOG_ERR, "Failed reg self pipe socket"); exit(EXIT_FAILURE); } #ifdef GRACEFUL_TERMINATION /* Cleanup function if process need to be cleaned gracefully */ ctl_params->fn_cleanup_launher = cleanup_launcher; #endif OT_LOG(LOG_ERR, "Entering the launcher mainloop"); for (;;) { if (pthread_sigmask(SIG_SETMASK, &sig_empty_set, NULL)) { OT_LOG(LOG_ERR, "Problem with signal mask setting"); continue; } event_count = wrap_epoll_wait(cur_events, MAX_CURR_EVENTS); if (event_count == -1) { if (errno == EINTR) { check_signal_status(ctl_params); continue; } /* Log error and hope the error clears itself */ OT_LOG(LOG_ERR, "Failed return from epoll_wait"); continue; } if (pthread_sigmask(SIG_SETMASK, &sig_block_set, NULL)) { OT_LOG(LOG_ERR, "Problem with signal mask setting"); continue; } /* Note: All signals are blocked */ for (i = 0; i < event_count; i++) { if (cur_events[i].data.fd == ctl_params->self_pipe_fd) { if (cur_events[i].events & EPOLLERR) { OT_LOG(LOG_ERR, "Something wrong with self pipe"); exit(EXIT_FAILURE); } check_signal_status(ctl_params); continue; } /* Launcher is monitoring only two socket and second one is manager fd */ if (cur_events[i].events & EPOLLERR || cur_events[i].events & EPOLLHUP) { OT_LOG(LOG_ERR, "Manager socket error"); exit(EXIT_FAILURE); } ret = com_recv_msg(ctl_params->comm_sock_fd, (void **)&recv_open_msg, NULL, shm_fds, &shm_fd_count); if (ret == -1) { free(recv_open_msg); /* TODO: Figur out why -1, but for now lets * hope the error clears itself*/ continue; } else if (ret > 0) { /* ignore message */ free(recv_open_msg); continue; } recv_open_msg->msg_hdr.shareable_fd_count = 0; if (shm_fd_count > 0 && shm_fd_count <= 4) { recv_open_msg->msg_hdr.shareable_fd_count = shm_fd_count; memcpy(recv_open_msg->msg_hdr.shareable_fd, shm_fds, sizeof(int)*shm_fd_count); } /* Extrac info from message */ if (recv_open_msg->msg_hdr.msg_name != COM_MSG_NAME_OPEN_SESSION || recv_open_msg->msg_hdr.msg_type != COM_TYPE_QUERY) { OT_LOG(LOG_ERR, "Invalid message"); goto close_fd; } /* Received correct mesage from manager. Prepare response message. * PID is filled later */ new_ta_info.msg_hdr.msg_name = COM_MSG_NAME_CREATED_TA; new_ta_info.msg_hdr.msg_type = COM_TYPE_RESPONSE; new_ta_info.msg_hdr.sess_id = recv_open_msg->msg_hdr.sess_id; /* create a socket pair so the manager and TA can communicate */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1) { OT_LOG(LOG_ERR, "failed to create a socket pair"); send_err_msg_to_manager(ctl_params->comm_sock_fd, &new_ta_info); goto close_fd; } /* * Clone now to create the TA subprocess */ /* Fill ta loop arguments */ ta_loop_args.com_sock = sockfd[1]; ta_loop_args.ctl_params = ctl_params; ta_loop_args.recv_open_msg = recv_open_msg; new_proc_pid = clone(ta_process_loop, child_stack + CHILD_STACK_SIZE, SIGCHLD | CLONE_PARENT, &ta_loop_args); if (new_proc_pid == -1) { send_err_msg_to_manager(ctl_params->comm_sock_fd, &new_ta_info); goto close_pair; } new_ta_info.pid = new_proc_pid; ret = com_send_msg(ctl_params->comm_sock_fd, &new_ta_info, sizeof(struct com_msg_ta_created), NULL, 0); if (ret == sizeof(struct com_msg_ta_created)) { if (send_fd(ctl_params->comm_sock_fd, &sockfd[0], 1, NULL, 0) == -1) { OT_LOG(LOG_ERR, "Failed to send TA sock"); kill(new_proc_pid, SIGKILL); /* TODO: Check what is causing error, but for now * lets hope the error clears itself*/ } } else { OT_LOG(LOG_ERR, "Failed to send response msg"); kill(new_proc_pid, SIGKILL); /* TODO: Check what is causing error, but for now lets * hope the error clears itself*/ } close_pair: /* parent process will stay as the launcher */ close(sockfd[0]); close(sockfd[1]); close_fd: /* close possibly forwarded file descriptors */ while (recv_open_msg->msg_hdr.shareable_fd_count > 0) { recv_open_msg->msg_hdr.shareable_fd_count--; close(recv_open_msg->msg_hdr.shareable_fd [recv_open_msg->msg_hdr.shareable_fd_count]); } free(recv_open_msg); } } }
int ta_process_loop(int man_sockfd, struct com_msg_open_session *open_msg) { int ret; pthread_t ta_logic_thread; pthread_attr_t attr; struct epoll_event cur_events[MAX_CURR_EVENTS]; int event_count, i; char proc_name[MAX_PR_NAME]; /* For now */ sigset_t sig_empty_set; /* Set new ta process name */ strncpy(proc_name, open_msg->ta_so_name, MAX_PR_NAME); prctl(PR_SET_NAME, (unsigned long)proc_name); strncpy(argv0, proc_name, argv0_len); /* Load TA to this process */ ret = load_ta(open_msg->ta_so_name, &interface); if (ret != TEE_SUCCESS || interface == NULL) { OT_LOG(LOG_ERR, "Failed to load the TA"); exit(EXIT_FAILURE); } /* Note: All signal are blocked. Prepare allow set when we can accept signals */ if (sigemptyset(&sig_empty_set)) { OT_LOG(LOG_ERR, "Sigempty set failed: %s", strerror(errno)) exit(EXIT_FAILURE); } /* create an eventfd, that will allow the writer to increment the count by 1 * for each new event, and the reader to decrement by 1 each time, this will allow the * reader to be notified for each new event, as opposed to being notified just once that * there are "event(s)" pending*/ event_fd = eventfd(0, EFD_SEMAPHORE); if (event_fd == -1) { OT_LOG(LOG_ERR, "Failed to initialize eventfd"); exit(EXIT_FAILURE); } /* Initializations of TODO and DONE queues*/ INIT_LIST(&tasks_todo.list); INIT_LIST(&tasks_done.list); /* Init epoll and register FD/data */ if (init_epoll()) exit(EXIT_FAILURE); /* listen to inbound connections from the manager */ if (epoll_reg_fd(man_sockfd, EPOLLIN)) exit(EXIT_FAILURE); /* listen for communications from the TA thread process */ if (epoll_reg_fd(event_fd, EPOLLIN)) exit(EXIT_FAILURE); /* Signal handling */ if (epoll_reg_fd(self_pipe_fd, EPOLLIN)) exit(EXIT_FAILURE); /* Init worker thread */ ret = pthread_attr_init(&attr); if (ret) { OT_LOG(LOG_ERR, "Failed to create attr for thread: %s", strerror(errno)) exit(EXIT_FAILURE); } /* TODO: Should we reserver space for thread stack? */ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (ret) { OT_LOG(LOG_ERR, "Failed set DETACHED: %s", strerror(errno)) exit(EXIT_FAILURE); } /* Known error: CA can not determ if TA is launched or not, because framework is calling * create entry point and open session function. Those functions return values is mapped * into one return value. */ if (interface->create() != TEE_SUCCESS) { OT_LOG(LOG_ERR, "TA create entry point failed"); exit(EXIT_SUCCESS); } /* Launch worker thread and pass open session message as a parameter */ ret = pthread_create(&ta_logic_thread, &attr, ta_internal_thread, open_msg); if (ret) { OT_LOG(LOG_ERR, "Failed launch thread: %s", strerror(errno)) interface->destroy(); exit(EXIT_FAILURE); } pthread_attr_destroy(&attr); /* Not needed any more */ /* Allow signal delivery */ if (pthread_sigmask(SIG_SETMASK, &sig_empty_set, NULL)) { OT_LOG(LOG_ERR, "failed to allow signals: %s", strerror(errno)) exit(EXIT_FAILURE); } /* Enter into the main part of this io_thread */ for (;;) { event_count = wrap_epoll_wait(cur_events, MAX_CURR_EVENTS); if (event_count == -1) { if (errno == EINTR) { continue; } /* Log error and hope the error clears itself */ OT_LOG(LOG_ERR, "Failed return from epoll_wait"); continue; } for (i = 0; i < event_count; i++) { if (cur_events[i].data.fd == man_sockfd) { receive_from_manager(&cur_events[i], man_sockfd); } else if (cur_events[i].data.fd == event_fd) { reply_to_manager(&cur_events[i], man_sockfd); } else if (cur_events[i].data.fd == self_pipe_fd) { } else { OT_LOG(LOG_ERR, "unknown event source"); } } } /* Should never reach here */ exit(EXIT_FAILURE); }