diff --git a/src/ifchd.c b/src/ifchd.c index f6637ee..eed33f5 100644 --- a/src/ifchd.c +++ b/src/ifchd.c @@ -304,10 +304,11 @@ static void do_ifch_work(void) memset(cl.domains, 0, sizeof cl.domains); epoll_add(epollfd, ifchSock[1]); + epoll_add(epollfd, ifchStream[1]); epoll_add(epollfd, signalFd); for (;;) { - int r = epoll_wait(epollfd, events, 2, -1); + int r = epoll_wait(epollfd, events, 3, -1); if (r < 0) { if (errno == EINTR) continue; @@ -316,11 +317,16 @@ static void do_ifch_work(void) } for (int i = 0; i < r; ++i) { int fd = events[i].data.fd; - if (fd == ifchSock[1]) - process_client_socket(); - else if (fd == signalFd) - signal_dispatch_subprocess(signalFd, "ifch"); - else + if (fd == ifchSock[1]) { + if (events[i].events & EPOLLIN) + process_client_socket(); + } else if (fd == ifchStream[1]) { + if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP)) + exit(EXIT_SUCCESS); + } else if (fd == signalFd) { + if (events[i].events & EPOLLIN) + signal_dispatch_subprocess(signalFd, "ifch"); + } else suicide("ifch: unexpected fd while performing epoll"); } } @@ -329,9 +335,6 @@ static void do_ifch_work(void) void ifch_main(void) { prctl(PR_SET_NAME, "ndhc: ifch"); - if (prctl(PR_SET_PDEATHSIG, SIGHUP) < 0) - suicide("%s: (%s) prctl(PR_SET_PDEATHSIG) failed: %s", - client_config.interface, __func__, strerror(errno)); umask(077); signalFd = setup_signals_subprocess(); diff --git a/src/ndhc.c b/src/ndhc.c index b58f331..b95790e 100644 --- a/src/ndhc.c +++ b/src/ndhc.c @@ -275,7 +275,7 @@ static void handle_ifch_message(void) cs.ifchWorking = 0; } -#define NDHC_NUM_EP_FDS 4 +#define NDHC_NUM_EP_FDS 7 static void do_ndhc_work(void) { struct epoll_event events[NDHC_NUM_EP_FDS]; @@ -293,6 +293,8 @@ static void do_ndhc_work(void) epoll_add(cs.epollFd, cs.nlFd); epoll_add(cs.epollFd, ifchSock[0]); + epoll_add(cs.epollFd, ifchStream[0]); + epoll_add(cs.epollFd, sockdStream[0]); set_listen_raw(&cs); nowts = curms(); goto jumpstart; @@ -307,17 +309,28 @@ static void do_ndhc_work(void) } for (int i = 0; i < r; ++i) { int fd = events[i].data.fd; - if (fd == cs.signalFd) - signal_dispatch(); - else if (fd == cs.listenFd) - handle_packet(&cs); - else if (fd == cs.arpFd) - handle_arp_response(&cs); - else if (fd == cs.nlFd) - handle_nl_message(&cs); - else if (fd == ifchSock[0]) - handle_ifch_message(); - else + if (fd == cs.signalFd) { + if (events[i].events & EPOLLIN) + signal_dispatch(); + } else if (fd == cs.listenFd) { + if (events[i].events & EPOLLIN) + handle_packet(&cs); + } else if (fd == cs.arpFd) { + if (events[i].events & EPOLLIN) + handle_arp_response(&cs); + } else if (fd == cs.nlFd) { + if (events[i].events & EPOLLIN) + handle_nl_message(&cs); + } else if (fd == ifchSock[0]) { + if (events[i].events & EPOLLIN) + handle_ifch_message(); + } else if (fd == ifchStream[0]) { + if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP)) + exit(EXIT_FAILURE); + } else if (fd == sockdStream[0]) { + if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP)) + exit(EXIT_FAILURE); + } else suicide("epoll_wait: unknown fd"); } @@ -357,15 +370,21 @@ uid_t ndhc_uid = 0; gid_t ndhc_gid = 0; int ifchSock[2]; int sockdSock[2]; +int ifchStream[2]; +int sockdStream[2]; static void create_ifch_ipc_sockets(void) { if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ifchSock) < 0) suicide("FATAL - can't create ndhc/ifch socket: %s", strerror(errno)); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, ifchStream) < 0) + suicide("FATAL - can't create ndhc/ifch socket: %s", strerror(errno)); } static void create_sockd_ipc_sockets(void) { if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockdSock) < 0) suicide("FATAL - can't create ndhc/sockd socket: %s", strerror(errno)); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockdStream) < 0) + suicide("FATAL - can't create ndhc/ifch socket: %s", strerror(errno)); } static void spawn_ifch(void) @@ -374,11 +393,13 @@ static void spawn_ifch(void) pid_t ifch_pid = fork(); if (ifch_pid == 0) { close(ifchSock[0]); + close(ifchStream[0]); // Don't share the RNG state with the master process. nk_random_u32_init(&cs.rnd32_state); ifch_main(); } else if (ifch_pid > 0) { close(ifchSock[1]); + close(ifchStream[1]); } else suicide("failed to fork ndhc-ifch: %s", strerror(errno)); } @@ -389,11 +410,13 @@ static void spawn_sockd(void) pid_t sockd_pid = fork(); if (sockd_pid == 0) { close(sockdSock[0]); + close(sockdStream[0]); // Don't share the RNG state with the master process. nk_random_u32_init(&cs.rnd32_state); sockd_main(); } else if (sockd_pid > 0) { close(sockdSock[1]); + close(sockdStream[1]); } else suicide("failed to fork ndhc-sockd: %s", strerror(errno)); } diff --git a/src/ndhc.h b/src/ndhc.h index 2d989d2..f1cdde4 100644 --- a/src/ndhc.h +++ b/src/ndhc.h @@ -68,9 +68,9 @@ struct client_config_t { extern struct client_config_t client_config; extern int ifchSock[2]; -extern int ifchPipe[2]; +extern int ifchStream[2]; extern int sockdSock[2]; -extern int sockdPipe[2]; +extern int sockdStream[2]; extern char state_dir[PATH_MAX]; extern char chroot_dir[PATH_MAX]; extern char resolv_conf_d[PATH_MAX]; diff --git a/src/sockd.c b/src/sockd.c index 5446aa8..0f2413d 100644 --- a/src/sockd.c +++ b/src/sockd.c @@ -544,10 +544,11 @@ static void do_sockd_work(void) log_line("sockd seccomp filter cannot be installed"); epoll_add(epollfd, sockdSock[1]); + epoll_add(epollfd, sockdStream[1]); epoll_add(epollfd, signalFd); for (;;) { - int r = epoll_wait(epollfd, events, 2, -1); + int r = epoll_wait(epollfd, events, 3, -1); if (r < 0) { if (errno == EINTR) continue; @@ -556,11 +557,16 @@ static void do_sockd_work(void) } for (int i = 0; i < r; ++i) { int fd = events[i].data.fd; - if (fd == sockdSock[1]) - process_client_socket(); - else if (fd == signalFd) - signal_dispatch_subprocess(signalFd, "sockd"); - else + if (fd == sockdSock[1]) { + if (events[i].events & EPOLLIN) + process_client_socket(); + } else if (fd == sockdStream[1]) { + if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP)) + exit(EXIT_SUCCESS); + } else if (fd == signalFd) { + if (events[i].events & EPOLLIN) + signal_dispatch_subprocess(signalFd, "sockd"); + } else suicide("sockd: unexpected fd while performing epoll"); } } @@ -569,9 +575,6 @@ static void do_sockd_work(void) void sockd_main(void) { prctl(PR_SET_NAME, "ndhc: sockd"); - if (prctl(PR_SET_PDEATHSIG, SIGHUP) < 0) - suicide("%s: (%s) prctl(PR_SET_PDEATHSIG) failed: %s", - client_config.interface, __func__, strerror(errno)); umask(077); signalFd = setup_signals_subprocess(); nk_set_chroot(chroot_dir);