Module Name: src Committed By: roy Date: Thu Jun 4 13:08:13 UTC 2020
Modified Files: src/external/bsd/dhcpcd/dist/src: dhcp.c dhcp6.c dhcpcd.8.in dhcpcd.c if-bsd.c privsep.c script.c Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.37 -r1.38 src/external/bsd/dhcpcd/dist/src/dhcp.c \ src/external/bsd/dhcpcd/dist/src/dhcpcd.c cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/src/dhcp6.c cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in \ src/external/bsd/dhcpcd/dist/src/script.c cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/src/if-bsd.c cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/src/privsep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/dhcpcd/dist/src/dhcp.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.37 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.38 --- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.37 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/dhcp.c Thu Jun 4 13:08:13 2020 @@ -1034,7 +1034,7 @@ make_message(struct bootp **bootpm, cons auth = NULL; /* appease GCC */ auth_len = 0; if (ifo->auth.options & DHCPCD_AUTH_SEND) { - ssize_t alen = dhcp_auth_encode(&ifo->auth, + ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, NULL, 0, 4, type, NULL, 0); if (alen != -1 && alen > UINT8_MAX) { @@ -1129,7 +1129,7 @@ make_message(struct bootp **bootpm, cons #ifdef AUTH if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0) - dhcp_auth_encode(&ifo->auth, state->auth.token, + dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, (uint8_t *)bootp, len, 4, type, auth, auth_len); #endif @@ -2747,6 +2747,18 @@ dhcp_drop(struct interface *ifp, const c #endif } } +#ifdef AUTH + else if (state->auth.reconf != NULL) { + /* + * Drop the lease as the token may only be present + * in the initial reply message and not subsequent + * renewals. + * If dhcpcd is restarted, the token is lost. + * XXX persist this in another file? + */ + dhcp_unlink(ifp->ctx, state->leasefile); + } +#endif eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); #ifdef AUTH @@ -4176,3 +4188,24 @@ dhcp_handleifa(int cmd, struct ipv4_addr return ia; } + +#ifndef SMALL +int +dhcp_dump(struct interface *ifp) +{ + struct dhcp_state *state; + + ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state)); + if (state == NULL) { + logerr(__func__); + return -1; + } + state->new_len = read_lease(ifp, &state->new); + if (state->new == NULL) { + logerr("read_lease"); + return -1; + } + state->reason = "DUMP"; + return script_runreason(ifp, state->reason); +} +#endif Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.37 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.38 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.37 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Thu Jun 4 13:08:13 2020 @@ -29,6 +29,7 @@ const char dhcpcd_copyright[] = "Copyright (c) 2006-2020 Roy Marples"; #include <sys/file.h> +#include <sys/ioctl.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/time.h> @@ -86,6 +87,7 @@ const int dhcpcd_signals[] = { SIGHUP, SIGUSR1, SIGUSR2, + SIGCHLD, }; const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals); @@ -1340,6 +1342,9 @@ stop_all_interfaces(struct dhcpcd_ctx *c struct interface *ifp; ctx->options |= DHCPCD_EXITING; + if (ctx->ifaces == NULL) + return; + /* Drop the last interface first */ TAILQ_FOREACH_REVERSE(ifp, ctx->ifaces, if_head, next) { if (!ifp->active) @@ -1395,7 +1400,7 @@ dhcpcd_signal_cb(int sig, void *arg) unsigned long long opts; int exit_code; - if (ctx->options & DHCPCD_FORKED) { + if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) { pid_t pid = pidfile_read(ctx->pidfile); if (pid == -1) { if (errno != ENOENT) @@ -1441,6 +1446,10 @@ dhcpcd_signal_cb(int sig, void *arg) if (logopen(ctx->logfile) == -1) logerr(__func__); return; + case SIGCHLD: + while (waitpid(-1, NULL, WNOHANG) > 0) + ; + return; default: logerrx("received signal %d but don't know what to do with it", sig); @@ -1663,20 +1672,13 @@ dumperr: return 0; } -static const char *dumpskip[] = { - "PATH=", - "pid=", - "chroot=", -}; - static int dhcpcd_readdump(struct dhcpcd_ctx *ctx) { int error = 0; - size_t nifaces, buflen = 0, dlen, i; + size_t nifaces, buflen = 0, dlen; ssize_t len; - char *buf = NULL, *dp, *de; - const char *skip; + char *buf = NULL; again1: len = read(ctx->control_fd, &nifaces, sizeof(nifaces)); @@ -1723,26 +1725,7 @@ again3: error = -1; goto out; } - dp = buf; - de = dp + dlen; - if (*(de - 1) != '\0') { - errno = EINVAL; - error = -1; - goto out; - } - while (dp < de) { - for (i = 0; i < __arraycount(dumpskip); i++) { - skip = dumpskip[i]; - if (strncmp(dp, skip, strlen(skip)) == 0) - break; - } - if (i == __arraycount(dumpskip)) { - if (strncmp(dp, "new_", 4) == 0) - dp += 4; - printf("%s\n", dp); - } - dp += strlen(dp) + 1; - } + script_dump(buf, dlen); fflush(stdout); if (nifaces != 1) putchar('\n'); @@ -2061,13 +2044,9 @@ printpidfile: signal(dhcpcd_signals_ignore[si], SIG_IGN); /* Save signal mask, block and redirect signals to our handler */ - if (eloop_signal_set_cb(ctx.eloop, + eloop_signal_set_cb(ctx.eloop, dhcpcd_signals, dhcpcd_signals_len, - dhcpcd_signal_cb, &ctx) == -1) - { - logerr("%s: eloop_signal_set_cb", __func__); - goto exit_failure; - } + dhcpcd_signal_cb, &ctx); if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) { logerr("%s: eloop_signal_mask", __func__); goto exit_failure; @@ -2107,6 +2086,45 @@ printpidfile: } #endif +#ifndef SMALL + if (ctx.options & DHCPCD_DUMPLEASE && + ioctl(fileno(stdin), FIONREAD, &i, sizeof(i)) == 0 && + i > 0) + { + ifp = calloc(1, sizeof(*ifp)); + if (ifp == NULL) { + logerr(__func__); + goto exit_failure; + } + ifp->ctx = &ctx; + ifp->options = ifo; + switch (family) { + case AF_INET: +#ifdef INET + if (dhcp_dump(ifp) == -1) + goto exit_failure; + break; +#else + logerrx("No DHCP support"); + goto exit_failure; +#endif + case AF_INET6: +#ifdef DHCP6 + if (dhcp6_dump(ifp) == -1) + goto exit_failure; + break; +#else + logerrx("No DHCP6 support"); + goto exit_failure; +#endif + default: + logerrx("Family not specified. Please use -4 or -6."); + goto exit_failure; + } + goto exit_success; + } +#endif + /* Test against siga instead of sig to avoid gcc * warning about a bogus potential signed overflow. * The end result will be the same. */ @@ -2194,7 +2212,6 @@ printpidfile: logerr("fork"); goto exit_failure; case 0: - eloop_requeue(ctx.eloop); break; default: ctx.options |= DHCPCD_FORKED; /* A lie */ @@ -2203,7 +2220,6 @@ printpidfile: } break; default: - waitpid(pid, &i, 0); ctx.options |= DHCPCD_FORKED; /* A lie */ ctx.fork_fd = sigpipe[0]; close(sigpipe[1]); Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.19 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.20 --- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.19 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Thu Jun 4 13:08:13 2020 @@ -881,7 +881,7 @@ dhcp6_makemessage(struct interface *ifp) #ifdef AUTH auth_len = 0; if (ifo->auth.options & DHCPCD_AUTH_SEND) { - ssize_t alen = dhcp_auth_encode(&ifo->auth, + ssize_t alen = dhcp_auth_encode(ifp->ctx, &ifo->auth, state->auth.token, NULL, 0, 6, type, NULL, 0); if (alen != -1 && alen > UINT16_MAX) { errno = ERANGE; @@ -1196,9 +1196,9 @@ dhcp6_update_auth(struct interface *ifp, return -1; state = D6_STATE(ifp); - return dhcp_auth_encode(&ifp->options->auth, state->auth.token, - (uint8_t *)state->send, state->send_len, - 6, state->send->type, opt, opt_len); + return dhcp_auth_encode(ifp->ctx, &ifp->options->auth, + state->auth.token, (uint8_t *)state->send, state->send_len, 6, + state->send->type, opt, opt_len); } #endif @@ -1483,7 +1483,7 @@ void dhcp6_renew(struct interface *ifp) dhcp6_startrenew(ifp); } -int +bool dhcp6_dadcompleted(const struct interface *ifp) { const struct dhcp6_state *state; @@ -1493,9 +1493,9 @@ dhcp6_dadcompleted(const struct interfac TAILQ_FOREACH(ap, &state->addrs, next) { if (ap->flags & IPV6_AF_ADDED && !(ap->flags & IPV6_AF_DADCOMPLETED)) - return 0; + return false; } - return 1; + return true; } static void @@ -3319,7 +3319,7 @@ dhcp6_recvif(struct interface *ifp, cons loginfox("%s: accepted reconfigure key", ifp->name); } else if (ifo->auth.options & DHCPCD_AUTH_SEND) { if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) { - logerr("%s: no authentication from %s", + logerrx("%s: no authentication from %s", ifp->name, sfrom); return; } @@ -3595,15 +3595,12 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, st } if (r->type == DHCP6_RECONFIGURE) { - logdebugx("%s: RECONFIGURE6 recv from %s," - " sending to all interfaces", - ifp->name, sfrom); - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - state = D6_CSTATE(ifp); - if (state != NULL && state->send != NULL) - dhcp6_recvif(ifp, sfrom, r, len); + if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { + logerrx("%s: RECONFIGURE6 recv from %s, not LL", + ifp->name, sfrom); + return; } - return; + goto recvif; } state = D6_CSTATE(ifp); @@ -3679,6 +3676,7 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, st len = (size_t)tlen; #endif +recvif: dhcp6_recvif(ifp, sfrom, r, len); } @@ -4041,6 +4039,19 @@ dhcp6_freedrop(struct interface *ifp, in } dhcp_unlink(ifp->ctx, state->leasefile); } +#ifdef AUTH + else if (state->auth.reconf != NULL) { + /* + * Drop the lease as the token may only be present + * in the initial reply message and not subsequent + * renewals. + * If dhcpcd is restarted, the token is lost. + * XXX persist this in another file? + */ + dhcp_unlink(ifp->ctx, state->leasefile); + } +#endif + dhcp6_freedrop_addrs(ifp, drop, NULL); free(state->old); state->old = state->new; @@ -4293,3 +4304,24 @@ delegated: return 1; } #endif + +#ifndef SMALL +int +dhcp6_dump(struct interface *ifp) +{ + struct dhcp6_state *state; + + ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state)); + if (state == NULL) { + logerr(__func__); + return -1; + } + TAILQ_INIT(&state->addrs); + if (dhcp6_readlease(ifp, 0) == -1) { + logerr("dhcp6_readlease"); + return -1; + } + state->reason = "DUMP6"; + return script_runreason(ifp, state->reason); +} +#endif Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.6 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.7 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.6 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in Thu Jun 4 13:08:13 2020 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 21, 2020 +.Dd May 31, 2020 .Dt DHCPCD 8 .Os .Sh NAME @@ -72,7 +72,7 @@ .Op interface .Nm .Fl U , Fl Fl dumplease -.Ar interface +.Op Ar interface .Nm .Fl Fl version .Nm @@ -685,15 +685,20 @@ option is not sent in TEST mode so that To test INFORM the interface needs to be configured with the desired address before starting .Nm . -.It Fl U , Fl Fl dumplease Ar interface +.It Fl U , Fl Fl dumplease Op Ar interface Dumps the current lease for the .Ar interface to stdout. +If no +.Ar interface +is given then all interfaces are dumped. Use the .Fl 4 or .Fl 6 flags to specify an address family. +If a lease is piped in via standard input then that is dumped. +In this case, specifying an address family is mandatory. .It Fl V , Fl Fl variables Display a list of option codes, the associated variable and encoding for use in .Xr dhcpcd-run-hooks 8 . Index: src/external/bsd/dhcpcd/dist/src/script.c diff -u src/external/bsd/dhcpcd/dist/src/script.c:1.6 src/external/bsd/dhcpcd/dist/src/script.c:1.7 --- src/external/bsd/dhcpcd/dist/src/script.c:1.6 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/script.c Thu Jun 4 13:08:13 2020 @@ -1,4 +1,4 @@ -/* stSPDX-License-Identifier: BSD-2-Clause */ +/* SPDX-License-Identifier: BSD-2-Clause */ /* * dhcpcd - DHCP client daemon * Copyright (c) 2006-2020 Roy Marples <r...@marples.name> @@ -193,6 +193,8 @@ script_buftoenv(struct dhcpcd_ctx *ctx, } } assert(*(bufp - 1) == '\0'); + if (nenv == 0) + return NULL; if (ctx->script_envlen < nenv) { env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env)); @@ -235,6 +237,7 @@ make_env(struct dhcpcd_ctx *ctx, const s #ifdef DHCP6 const struct dhcp6_state *d6_state; #endif + bool is_stdin = ifp->name[0] == '\0'; #ifdef HAVE_OPEN_MEMSTREAM if (ctx->script_fp == NULL) { @@ -264,23 +267,19 @@ make_env(struct dhcpcd_ctx *ctx, const s } #endif - /* Needed for scripts */ - path = getenv("PATH"); - if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1) - goto eexit; - if (efprintf(fp, "reason=%s", reason) == -1) - goto eexit; - if (efprintf(fp, "pid=%d", getpid()) == -1) - goto eexit; - -#ifdef PRIVSEP - if (ctx->options & DHCPCD_PRIVSEP && ctx->ps_user != NULL) { - if (efprintf(fp, "chroot=%s", ctx->ps_user->pw_dir) == -1) + if (!(ifp->ctx->options & DHCPCD_DUMPLEASE)) { + /* Needed for scripts */ + path = getenv("PATH"); + if (efprintf(fp, "PATH=%s", + path == NULL ? DEFAULT_PATH : path) == -1) + goto eexit; + if (efprintf(fp, "pid=%d", getpid()) == -1) + goto eexit; + } + if (!is_stdin) { + if (efprintf(fp, "reason=%s", reason) == -1) goto eexit; } - if (strcmp(reason, "CHROOT") == 0) - goto make; -#endif ifo = ifp->options; #ifdef INET @@ -340,9 +339,10 @@ make_env(struct dhcpcd_ctx *ctx, const s protocol = PROTO_DHCP; #endif - - if (efprintf(fp, "interface=%s", ifp->name) == -1) - goto eexit; + if (!is_stdin) { + if (efprintf(fp, "interface=%s", ifp->name) == -1) + goto eexit; + } if (ifp->ctx->options & DHCPCD_DUMPLEASE) goto dumplease; if (efprintf(fp, "ifcarrier=%s", @@ -508,9 +508,6 @@ dumplease: goto eexit; } -#ifdef PRIVSEP -make: -#endif /* Convert buffer to argv */ fflush(fp); @@ -536,6 +533,9 @@ make: fp = NULL; #endif + if (is_stdin) + return buf_pos; + if (script_buftoenv(ctx, ctx->script_buf, (size_t)buf_pos) == NULL) goto eexit; @@ -686,23 +686,48 @@ script_run(struct dhcpcd_ctx *ctx, char } int +script_dump(const char *env, size_t len) +{ + const char *ep = env + len; + + if (len == 0) + return 0; + + if (*(ep - 1) != '\0') { + errno = EINVAL; + return -1; + } + + for (; env < ep; env += strlen(env) + 1) { + if (strncmp(env, "new_", 4) == 0) + env += 4; + printf("%s\n", env); + } + return 0; +} + +int script_runreason(const struct interface *ifp, const char *reason) { struct dhcpcd_ctx *ctx = ifp->ctx; char *argv[2]; int status = 0; struct fd_list *fd; + long buflen; if (ctx->script == NULL && TAILQ_FIRST(&ifp->ctx->control_fds) == NULL) return 0; /* Make our env */ - if (make_env(ifp->ctx, ifp, reason) == -1) { + if ((buflen = make_env(ifp->ctx, ifp, reason)) == -1) { logerr(__func__); return -1; } + if (strncmp(reason, "DUMP", 4) == 0) + return script_dump(ctx->script_buf, (size_t)buflen); + if (ctx->script == NULL) goto send_listeners; Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.20 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.21 --- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.20 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Thu Jun 4 13:08:13 2020 @@ -100,10 +100,12 @@ #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) #endif -/* Ignore these interface names which look like ethernet but are virtual. */ +/* Ignore these interface names which look like ethernet but are virtual or + * just won't work without explicit configuration. */ static const char * const ifnames_ignore[] = { "bridge", "fwe", /* Firewire */ + "fwip", /* Firewire */ "tap", "xvif", /* XEN DOM0 -> guest interface */ NULL Index: src/external/bsd/dhcpcd/dist/src/privsep.c diff -u src/external/bsd/dhcpcd/dist/src/privsep.c:1.3 src/external/bsd/dhcpcd/dist/src/privsep.c:1.4 --- src/external/bsd/dhcpcd/dist/src/privsep.c:1.3 Sun May 31 12:52:11 2020 +++ src/external/bsd/dhcpcd/dist/src/privsep.c Thu Jun 4 13:08:13 2020 @@ -131,6 +131,41 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) return 0; } +static int +ps_setbuf0(int fd, int ctl, int minlen) +{ + int len; + socklen_t slen; + + slen = sizeof(len); + if (getsockopt(fd, SOL_SOCKET, ctl, &len, &slen) == -1) + return -1; + +#ifdef __linux__ + len /= 2; +#endif + if (len >= minlen) + return 0; + + return setsockopt(fd, SOL_SOCKET, ctl, &minlen, sizeof(minlen)); +} + +static int +ps_setbuf(int fd) +{ + /* Ensure we can receive a fully sized privsep message. + * Double the send buffer. */ + int minlen = (int)sizeof(struct ps_msg); + + if (ps_setbuf0(fd, SO_RCVBUF, minlen) == -1 || + ps_setbuf0(fd, SO_SNDBUF, minlen * 2) == -1) + { + logerr(__func__); + return -1; + } + return 0; +} + pid_t ps_dostart(struct dhcpcd_ctx *ctx, pid_t *priv_pid, int *priv_fd, @@ -160,11 +195,13 @@ ps_dostart(struct dhcpcd_ctx *ctx, case 0: *priv_fd = fd[1]; close(fd[0]); + ps_setbuf(*priv_fd); break; default: *priv_pid = pid; *priv_fd = fd[0]; close(fd[1]); + ps_setbuf(*priv_fd); if (recv_unpriv_msg == NULL) ; #ifdef HAVE_CAPSICUM @@ -206,12 +243,8 @@ ps_dostart(struct dhcpcd_ctx *ctx, ctx->ps_inet_fd = -1; } - if (eloop_signal_set_cb(ctx->eloop, - dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx) == -1) - { - logerr("%s: eloop_signal_set_cb", __func__); - goto errexit; - } + eloop_signal_set_cb(ctx->eloop, + dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx); /* ctx->sigset aready has the initial sigmask set in main() */ if (eloop_signal_mask(ctx->eloop, NULL) == -1) { @@ -251,67 +284,35 @@ errexit: (void)ps_sendcmd(ctx, *priv_fd, PS_STOP, 0, NULL, 0); shutdown(*priv_fd, SHUT_RDWR); *priv_fd = -1; + eloop_exit(ctx->eloop, EXIT_FAILURE); return -1; } int ps_dostop(struct dhcpcd_ctx *ctx, pid_t *pid, int *fd) { - int status; + int err = 0; #ifdef PRIVSEP_DEBUG logdebugx("%s: pid %d fd %d", __func__, *pid, *fd); #endif - if (*pid == 0) - return 0; - eloop_event_delete(ctx->eloop, *fd); - if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 && - errno != ECONNRESET) - logerr(__func__); - if (shutdown(*fd, SHUT_RDWR) == -1 && errno != ENOTCONN) - logerr(__func__); - close(*fd); - *fd = -1; - /* We won't have permission for all processes .... */ -#if 0 - if (kill(*pid, SIGTERM) == -1) - logerr(__func__); -#endif - status = 0; - -#ifdef HAVE_CAPSICUM - unsigned int cap_mode = 0; - int cap_err = cap_getmode(&cap_mode); - if (cap_err == -1) { - if (errno != ENOSYS) - logerr("%s: cap_getmode", __func__); - } else if (cap_mode != 0) - goto nowait; -#endif - - /* Wait for the process to finish */ - while (waitpid(*pid, &status, 0) == -1) { - if (errno != EINTR) { - logerr("%s: waitpid", __func__); - status = 0; - break; + if (*fd != -1) { + eloop_event_delete(ctx->eloop, *fd); + if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 || + shutdown(*fd, SHUT_RDWR) == -1) + { + logerr(__func__); + err = -1; } -#ifdef PRIVSEP_DEBUG - else - logerr("%s: waitpid ", __func__); -#endif + close(*fd); + *fd = -1; } -#ifdef HAVE_CAPSICUM -nowait: -#endif - *pid = 0; - -#ifdef PRIVSEP_DEBUG - logdebugx("%s: status %d", __func__, status); -#endif - return status; + /* Don't wait for the process as it may not respond to the shutdown + * request. We'll reap the process on receipt of SIGCHLD. */ + *pid = 0; + return err; } int @@ -507,7 +508,8 @@ ps_sendpsmmsg(struct dhcpcd_ctx *ctx, in #ifdef PRIVSEP_DEBUG logdebugx("%s: %zd", __func__, len); #endif - if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED) + if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED && + !(ctx->options & DHCPCD_PRIVSEPROOT)) eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE); return len; } @@ -650,8 +652,12 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r #ifdef PRIVSEP_DEBUG logdebugx("%s: recv fd %d, %zd bytes", __func__, rfd, len); #endif - if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED) { - eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE); + + if (len == -1 || len == 0) { + if (ctx->options & DHCPCD_FORKED && + !(ctx->options & DHCPCD_PRIVSEPROOT)) + eloop_exit(ctx->eloop, + len == 0 ? EXIT_SUCCESS : EXIT_FAILURE); return len; } @@ -660,7 +666,8 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int r #ifdef PRIVSEP_DEBUG logdebugx("%s: send fd %d, %zu bytes", __func__, wfd, len); #endif - if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED) + if ((len == -1 || len == 0) && ctx->options & DHCPCD_FORKED && + !(ctx->options & DHCPCD_PRIVSEPROOT)) eloop_exit(ctx->eloop, len == 0 ? EXIT_SUCCESS : EXIT_FAILURE); return len; } @@ -682,8 +689,6 @@ ps_recvpsmsg(struct dhcpcd_ctx *ctx, int logdebugx("%s: %zd", __func__, len); #endif - if (len == -1 && (errno == ECONNRESET || errno == EBADF)) - len = 0; if (len == -1 || len == 0) stop = true; else {