From b00444ab8b672264a4a4a8b6a3bab2d44c1e816b Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Tue, 15 Apr 2014 18:01:01 -0400 Subject: [PATCH] Bound the subprocess lifetime using prctl(PR_SET_PDEATHSIG, ...). The pipes wouldn't do this job anymore because they were unused and thus never performed writes that would generate SIGPIPEs, so the pipes are removed, too. --- src/ifchange.c | 6 +++--- src/ifchd.c | 19 +++++++------------ src/ndhc.c | 25 +++++-------------------- src/sockd.c | 21 ++++++++++----------- 4 files changed, 25 insertions(+), 46 deletions(-) diff --git a/src/ifchange.c b/src/ifchange.c index 4b277c3..a1d7f03 100644 --- a/src/ifchange.c +++ b/src/ifchange.c @@ -184,7 +184,7 @@ static int ifchd_cmd(char *b, size_t bl, uint8_t *od, ssize_t ol, uint8_t code) return -1; } -static void pipewrite(struct client_state_t *cs, const char *buf, size_t count) +static void ifchwrite(struct client_state_t *cs, const char *buf, size_t count) { cs->ifchWorking = 1; ssize_t r = safe_write(ifchSock[0], buf, count); @@ -205,7 +205,7 @@ void ifchange_deconfig(struct client_state_t *cs) snprintf(buf, sizeof buf, "ip4:0.0.0.0,255.255.255.255;"); log_line("%s: Resetting IP configuration.", client_config.interface); - pipewrite(cs, buf, strlen(buf)); + ifchwrite(cs, buf, strlen(buf)); memset(&cfg_packet, 0, sizeof cfg_packet); } @@ -307,7 +307,7 @@ void ifchange_bind(struct client_state_t *cs, struct dhcpmsg *packet) bo += send_cmd(buf + bo, sizeof buf - bo, packet, DCODE_MTU); bo += send_cmd(buf + bo, sizeof buf - bo, packet, DCODE_WINS); if (bo) - pipewrite(cs, buf, bo); + ifchwrite(cs, buf, bo); cs->ifDeconfig = 0; memcpy(&cfg_packet, packet, sizeof cfg_packet); diff --git a/src/ifchd.c b/src/ifchd.c index 19c3f2a..36d6043 100644 --- a/src/ifchd.c +++ b/src/ifchd.c @@ -57,7 +57,7 @@ struct ifchd_client cl; static int epollfd, signalFd; -/* Slots are for signalFd and the ndhc -> ifchd pipe. */ +/* Slots are for signalFd and the ndhc -> ifchd socket. */ static struct epoll_event events[2]; static int resolv_conf_fd = -1; @@ -260,7 +260,6 @@ static void setup_signals_ifch(void) { sigset_t mask; sigemptyset(&mask); - sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGTSTP); @@ -294,10 +293,7 @@ static void signal_dispatch(void) switch (si.ssi_signo) { case SIGINT: case SIGTERM: - exit(EXIT_SUCCESS); - break; - case SIGPIPE: - log_line("ndhc-ifch: IPC pipe closed. Exiting."); + case SIGHUP: exit(EXIT_SUCCESS); break; default: @@ -312,11 +308,11 @@ static void inform_execute(char c) // Remote end hung up. exit(EXIT_SUCCESS); } else if (r < 0) - suicide("%s: (%s) error writing to ifch -> ndhc pipe: %s", + suicide("%s: (%s) error writing to ifch -> ndhc socket: %s", client_config.interface, __func__, strerror(errno)); } -static void process_client_pipe(void) +static void process_client_socket(void) { char buf[MAX_BUF]; @@ -328,7 +324,7 @@ static void process_client_pipe(void) } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return; - suicide("%s: (%s) error reading from ndhc -> ifch pipe: %s", + suicide("%s: (%s) error reading from ndhc -> ifch socket: %s", client_config.interface, __func__, strerror(errno)); } @@ -368,7 +364,7 @@ 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_pipe(); + process_client_socket(); else if (fd == signalFd) signal_dispatch(); else @@ -380,7 +376,7 @@ static void do_ifch_work(void) void ifch_main(void) { prctl(PR_SET_NAME, "ndhc: ifch"); - + prctl(PR_SET_PDEATHSIG, SIGHUP); umask(077); setup_signals_ifch(); @@ -401,7 +397,6 @@ void ifch_main(void) memset(chroot_dir, '\0', sizeof chroot_dir); unsigned char keepcaps[] = { CAP_NET_ADMIN }; nk_set_uidgid(ifch_uid, ifch_gid, keepcaps, sizeof keepcaps); - do_ifch_work(); } diff --git a/src/ndhc.c b/src/ndhc.c index 28dc6e7..25b523d 100644 --- a/src/ndhc.c +++ b/src/ndhc.c @@ -169,7 +169,6 @@ static void setup_signals_ndhc(void) sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGCHLD); - sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGTERM); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) suicide("sigprocmask failed"); @@ -205,10 +204,6 @@ static void signal_dispatch(void) case SIGUSR2: force_release_action(&cs); break; - case SIGPIPE: - log_line("ndhc-master: IPC pipe closed. Exiting."); - exit(EXIT_SUCCESS); - break; case SIGCHLD: suicide("ndhc-master: Subprocess terminated unexpectedly. Exiting."); break; @@ -278,7 +273,7 @@ static void handle_ifch_message(void) } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return; - suicide("%s: (%s) error reading from ifch -> ndhc pipe: %s", + suicide("%s: (%s) error reading from ifch -> ndhc socket: %s", client_config.interface, __func__, strerror(errno)); } @@ -367,54 +362,44 @@ char pidfile[PATH_MAX] = PID_FILE_DEFAULT; uid_t ndhc_uid = 0; gid_t ndhc_gid = 0; int ifchSock[2]; -int ifchPipe[2]; int sockdSock[2]; -int sockdPipe[2]; -static void create_ifch_ipc_pipes(void) { - if (pipe(ifchPipe)) - suicide("FATAL - can't create ndhc/ifch pipe: %s", strerror(errno)); +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)); } -static void create_sockd_ipc_pipes(void) { - if (pipe(sockdPipe)) - suicide("FATAL - can't create ndhc/sockd pipe: %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)); } static void spawn_ifch(void) { - create_ifch_ipc_pipes(); + create_ifch_ipc_sockets(); pid_t ifch_pid = fork(); if (ifch_pid == 0) { close(ifchSock[0]); - close(ifchPipe[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(ifchPipe[1]); } else suicide("failed to fork ndhc-ifch: %s", strerror(errno)); } static void spawn_sockd(void) { - create_sockd_ipc_pipes(); + create_sockd_ipc_sockets(); pid_t sockd_pid = fork(); if (sockd_pid == 0) { close(sockdSock[0]); - close(sockdPipe[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(sockdPipe[1]); } else suicide("failed to fork ndhc-sockd: %s", strerror(errno)); } diff --git a/src/sockd.c b/src/sockd.c index 960c2f6..2602791 100644 --- a/src/sockd.c +++ b/src/sockd.c @@ -61,7 +61,7 @@ #include "seccomp.h" static int epollfd, signalFd; -/* Slots are for signalFd and the ndhc -> ifchd pipe. */ +/* Slots are for signalFd and the ndhc -> ifchd socket. */ static struct epoll_event events[2]; uid_t sockd_uid = 0; @@ -439,7 +439,6 @@ static void setup_signals_sockd(void) { sigset_t mask; sigemptyset(&mask); - sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGTSTP); @@ -474,10 +473,7 @@ static void signal_dispatch(void) switch (si.ssi_signo) { case SIGINT: case SIGTERM: - exit(EXIT_SUCCESS); - break; - case SIGPIPE: - log_line("ndhc-sockd: IPC pipe closed. Exiting."); + case SIGHUP: exit(EXIT_SUCCESS); break; default: @@ -538,7 +534,8 @@ static size_t execute_sockd(char *buf, size_t buflen) uint8_t client_mac[6]; bool using_bpf; if (buflen < 1 + sizeof client_addr + 6) - return 0; + suicide("%s: (%s) 'd' does not have necessary arguments: %zu", + client_config.interface, __func__, buflen); memcpy(&client_addr, buf + 1, sizeof client_addr); memcpy(client_mac, buf + 1 + sizeof client_addr, 6); int fd = create_arp_defense_socket(client_addr, client_mac, @@ -550,7 +547,8 @@ static size_t execute_sockd(char *buf, size_t buflen) case 'u': { uint32_t client_addr; if (buflen < 1 + sizeof client_addr) - return 0; + suicide("%s: (%s) 'u' does not have necessary arguments: %zu", + client_config.interface, __func__, buflen); memcpy(&client_addr, buf + 1, sizeof client_addr); xfer_fd(create_udp_send_socket(client_addr), 'u'); return 5; @@ -560,7 +558,7 @@ static size_t execute_sockd(char *buf, size_t buflen) } } -static void process_client_pipe(void) +static void process_client_socket(void) { static char buf[MAX_BUF]; static size_t buflen; @@ -577,7 +575,7 @@ static void process_client_pipe(void) } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return; - suicide("%s: (%s) error reading from ndhc -> sockd pipe: %s", + suicide("%s: (%s) error reading from ndhc -> sockd socket: %s", client_config.interface, __func__, strerror(errno)); } buflen += (size_t)r; @@ -607,7 +605,7 @@ 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_pipe(); + process_client_socket(); else if (fd == signalFd) signal_dispatch(); else @@ -619,6 +617,7 @@ static void do_sockd_work(void) void sockd_main(void) { prctl(PR_SET_NAME, "ndhc: sockd"); + prctl(PR_SET_PDEATHSIG, SIGHUP); umask(077); setup_signals_sockd(); nk_set_chroot(chroot_dir);