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.
This commit is contained in:
Nicholas J. Kain 2014-04-15 18:01:01 -04:00
parent b3ce601f20
commit b00444ab8b
4 changed files with 25 additions and 46 deletions

View File

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

View File

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

View File

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

View File

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