Ejemplo n.º 1
0
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);

		}
	}
}
Ejemplo n.º 2
0
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);
}