int child_handle_noninteractive(int fd, wshd_t *w, msg_request_t *req) { int i, j; int p[4][2]; int p_[4]; int rv; msg_response_t res; msg_response_init(&res); /* Initialize so that the error handler can do its job */ for (i = 0; i < 4; i++) { p[i][0] = -1; p[i][1] = -1; p_[i] = -1; } for (i = 0; i < 4; i++) { rv = pipe(p[i]); if (rv == -1) { perror("pipe"); abort(); } fcntl_mix_cloexec(p[i][0]); fcntl_mix_cloexec(p[i][1]); } /* Descriptors to send to client */ p_[0] = p[0][1]; p_[1] = p[1][0]; p_[2] = p[2][0]; p_[3] = p[3][0]; rv = un_send_fds(fd, (char *)&res, sizeof(res), p_, 4); if (rv == -1) { goto err; } rv = child_fork(req, p[0][0], p[1][1], p[2][1]); assert(rv > 0); child_pid_to_fd_add(w, rv, p[3][1]); err: for (i = 0; i < 4; i++) { for (j = 0; j < 2; j++) { if (p[i][j] > -1) { close(p[i][j]); p[i][j] = -1; } } } if (fd > -1) { close(fd); fd = -1; } return 0; }
int un_listen(const char *path) { int fd; struct sockaddr_un sa; fd = un__socket(); sa.sun_family = AF_UNIX; assert(strlen(path) < sizeof(sa.sun_path)); strcpy(sa.sun_path, path); unlink(sa.sun_path); fcntl_mix_cloexec(fd); if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { perror("bind"); exit(1); } if (listen(fd, 5) == -1) { perror("listen"); exit(1); } return fd; }
int child_continue(int argc, char **argv) { wshd_t *w; int rv; w = child_load_from_shm(); /* Process MUST not leak file descriptors to children */ barrier_mix_cloexec(&w->barrier_child); fcntl_mix_cloexec(w->fd); if (strlen(w->title) > 0) { setproctitle(argv, w->title); } rv = mount_umount_pivoted_root("/mnt"); if (rv == -1) { exit(1); } /* Detach this process from its original group */ rv = setsid(); assert(rv > 0 && rv == getpid()); /* Signal parent */ rv = barrier_signal(&w->barrier_child); assert(rv == 0); return child_loop(w); }
int barrier_open(barrier_t *bar) { int rv; int aux[2] = { -1, -1 }; rv = pipe(aux); if (rv == -1) { perror("pipe"); goto err; } fcntl_mix_cloexec(aux[0]); fcntl_mix_cloexec(aux[1]); bar->fd[0] = aux[0]; bar->fd[1] = aux[1]; return 0; err: if (aux[0] >= 0) close(aux[0]); if (aux[1] >= 0) close(aux[1]); return -1; }
int child_accept(wshd_t *w) { int rv, fd; char buf[MSG_MAX_SIZE]; size_t buflen = sizeof(buf); msg_request_t req; rv = accept(w->fd, NULL, NULL); if (rv == -1) { perror("accept"); abort(); } fd = rv; fcntl_mix_cloexec(fd); rv = un_recv_fds(fd, buf, buflen, NULL, 0); if (rv < 0) { perror("recvmsg"); exit(255); } if (rv == 0) { close(fd); return 0; } assert(rv == sizeof(req)); memcpy(&req, buf, sizeof(req)); if (req.tty) { return child_handle_interactive(fd, w, &req); } else { return child_handle_noninteractive(fd, w, &req); } }