PR_SET_PDEATHSIG is not fully reliable, so instead maintain a pair of

AF_UNIX SOCK_STREAM sockets between the master processes and each subprocess,
and poll for the HUP event.

At the same time, be specific about the events that are checked in epoll
when dispatching on an event.
This commit is contained in:
Nicholas J. Kain 2014-04-15 23:19:24 -04:00
parent e526adce19
commit 0884d96d1e
4 changed files with 61 additions and 32 deletions

View File

@ -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();

View File

@ -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));
}

View File

@ -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];

View File

@ -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);