From: Roy Marples Date: Wed, 8 Nov 2023 11:09:52 +0000 (+0000) Subject: dhcpcd: Close fork_fd on hangup X-Git-Tag: v10.0.5~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c32c88b642b8c65eb68b505e0783fd46b57fc6fa;p=thirdparty%2Fdhcpcd.git dhcpcd: Close fork_fd on hangup Closing it early results in zero length reads in some situations. Logging that we forked via the launcher process also make more sense and allows us to use log* functions. While here, handle error condtions better by forcing a return rather than handling an invalid state. Fixes #260. --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 71e7d807..46c64b42 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -365,7 +365,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) return; #else int i; - unsigned int logopts = loggetopts(); if (ctx->options & DHCPCD_DAEMONISE && !(ctx->options & (DHCPCD_DAEMONISED | DHCPCD_NOWAITIP))) @@ -385,11 +384,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) !(ctx->options & DHCPCD_DAEMONISE)) return; - /* Don't use loginfo because this makes no sense in a log. */ - if (!(logopts & LOGERR_QUIET) && ctx->stderr_valid) - (void)fprintf(stderr, - "forked to background, child pid %d\n", getpid()); - #ifdef PRIVSEP ps_daemonised(ctx); #else @@ -400,9 +394,8 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) if (write(ctx->fork_fd, &i, sizeof(i)) == -1) logerr("write"); ctx->options |= DHCPCD_DAEMONISED; - eloop_event_delete(ctx->eloop, ctx->fork_fd); - close(ctx->fork_fd); - ctx->fork_fd = -1; + // dhcpcd_fork_cb will close the socket + shutdown(ctx->fork_fd, SHUT_RDWR); #endif } @@ -1822,31 +1815,6 @@ dhcpcd_readdump(struct dhcpcd_ctx *ctx) dhcpcd_readdump0, ctx); } -static void -dhcpcd_fork_cb(void *arg, unsigned short events) -{ - struct dhcpcd_ctx *ctx = arg; - int exit_code; - ssize_t len; - - if (!(events & ELE_READ)) - logerrx("%s: unexpected event 0x%04x", __func__, events); - - len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); - if (len == -1) { - logerr(__func__); - exit_code = EXIT_FAILURE; - } else if ((size_t)len < sizeof(exit_code)) { - logerrx("%s: truncated read %zd (expected %zu)", - __func__, len, sizeof(exit_code)); - exit_code = EXIT_FAILURE; - } - if (ctx->options & DHCPCD_FORKED) - eloop_exit(ctx->eloop, exit_code); - else - dhcpcd_signal_cb(exit_code, ctx); -} - static void dhcpcd_stderr_cb(void *arg, unsigned short events) { @@ -1871,6 +1839,51 @@ dhcpcd_stderr_cb(void *arg, unsigned short events) fprintf(stderr, "%s", log); } +static void +dhcpcd_fork_cb(void *arg, unsigned short events) +{ + struct dhcpcd_ctx *ctx = arg; + int exit_code; + ssize_t len; + + if (!(events & ELE_READ)) + logerrx("%s: unexpected event 0x%04x", __func__, events); + + len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); + if (len == -1) { + logerr(__func__); + eloop_exit(ctx->eloop, EXIT_FAILURE); + return; + } + if (len == 0) { + if (ctx->options & DHCPCD_FORKED) { + logerrx("%s: dhcpcd manager hungup", __func__); + eloop_exit(ctx->eloop, EXIT_FAILURE); + } else { + // Launcher exited + eloop_event_delete(ctx->eloop, ctx->fork_fd); + close(ctx->fork_fd); + ctx->fork_fd = -1; + } + return; + } + if ((size_t)len < sizeof(exit_code)) { + logerrx("%s: truncated read %zd (expected %zu)", + __func__, len, sizeof(exit_code)); + eloop_exit(ctx->eloop, EXIT_FAILURE); + return; + } + + if (ctx->options & DHCPCD_FORKED) { + if (exit_code == EXIT_SUCCESS) + logdebugx("forked to background"); + else + logerrx("exited with code %d", exit_code); + eloop_exit(ctx->eloop, exit_code); + } else + dhcpcd_signal_cb(exit_code, ctx); +} + static void dhcpcd_pidfile_timeout(void *arg) {