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:
parent
e526adce19
commit
0884d96d1e
21
src/ifchd.c
21
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();
|
||||
|
||||
|
47
src/ndhc.c
47
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));
|
||||
}
|
||||
|
@ -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];
|
||||
|
21
src/sockd.c
21
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);
|
||||
|
Loading…
Reference in New Issue
Block a user