Module Name: src Committed By: roy Date: Thu Oct 19 11:26:52 UTC 2023
Modified Files: src/external/bsd/dhcpcd/dist/src: dhcpcd.c privsep.c script.c Log Message: Sync with dhcpcd-10.0.4 To generate a diff of this commit: cvs rdiff -u -r1.52 -r1.53 src/external/bsd/dhcpcd/dist/src/dhcpcd.c cvs rdiff -u -r1.16 -r1.17 src/external/bsd/dhcpcd/dist/src/privsep.c \ src/external/bsd/dhcpcd/dist/src/script.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/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.52 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.53 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.52 Fri Oct 6 08:49:42 2023 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Thu Oct 19 11:26:52 2023 @@ -329,6 +329,36 @@ dhcpcd_ipwaited(struct dhcpcd_ctx *ctx) return 1; } +#ifndef THERE_IS_NO_FORK +void +dhcpcd_daemonised(struct dhcpcd_ctx *ctx) +{ + unsigned int logopts = loggetopts(); + + /* + * Stop writing to stderr. + * On the happy path, only the manager process writes to stderr, + * so this just stops wasting fprintf calls to nowhere. + * All other calls - ie errors in privsep processes or script output, + * will error when printing. + * If we *really* want to fix that, then we need to suck + * stderr/stdout in the manager process and either discard it or pass + * it to the launcher process and then to stderr. + */ + logopts &= ~LOGERR_ERR; + logsetopts(logopts); + + /* + * We need to do something with stdout/stderr to avoid SIGPIPE + * We know that stdin is already mapped to /dev/null + */ + dup2(STDIN_FILENO, STDOUT_FILENO); + dup2(STDIN_FILENO, STDERR_FILENO); + + ctx->options |= DHCPCD_DAEMONISED; +} +#endif + /* Returns the pid of the child, otherwise 0. */ void dhcpcd_daemonise(struct dhcpcd_ctx *ctx) @@ -363,6 +393,13 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) if (!(logopts & LOGERR_QUIET) && ctx->stderr_valid) (void)fprintf(stderr, "forked to background, child pid %d\n", getpid()); + +#ifdef PRIVSEP + ps_daemonised(ctx); +#else + dhcpcd_daemonised(ctx); +#endif + i = EXIT_SUCCESS; if (write(ctx->fork_fd, &i, sizeof(i)) == -1) logerr("write"); @@ -370,19 +407,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx) eloop_event_delete(ctx->eloop, ctx->fork_fd); close(ctx->fork_fd); ctx->fork_fd = -1; - - /* - * Stop writing to stderr. - * On the happy path, only the manager process writes to stderr, - * so this just stops wasting fprintf calls to nowhere. - * All other calls - ie errors in privsep processes or script output, - * will error when printing. - * If we *really* want to fix that, then we need to suck - * stderr/stdout in the manager process and either disacrd it or pass - * it to the launcher process and then to stderr. - */ - logopts &= ~LOGERR_ERR; - logsetopts(logopts); #endif } @@ -1869,6 +1893,22 @@ dhcpcd_pidfile_timeout(void *arg) dhcpcd_pidfile_timeout, ctx); } +static int dup_null(int fd) +{ + int fd_null = open(_PATH_DEVNULL, O_WRONLY); + int err; + + if (fd_null == -1) { + logwarn("open %s", _PATH_DEVNULL); + return -1; + } + + if ((err = dup2(fd_null, fd)) == -1) + logwarn("dup2 %d", fd); + close(fd_null); + return err; +} + int main(int argc, char **argv, char **envp) { @@ -1972,6 +2012,15 @@ main(int argc, char **argv, char **envp) ctx.stdout_valid = fcntl(STDOUT_FILENO, F_GETFD) != -1; ctx.stderr_valid = fcntl(STDERR_FILENO, F_GETFD) != -1; + /* Even we if we don't have input/outputs, we need to + * ensure they are setup for shells. */ + if (!ctx.stdin_valid) + dup_null(STDIN_FILENO); + if (!ctx.stdout_valid) + dup_null(STDOUT_FILENO); + if (!ctx.stderr_valid) + dup_null(STDERR_FILENO); + logopts = LOGERR_LOG | LOGERR_LOG_DATE | LOGERR_LOG_PID; if (ctx.stderr_valid) logopts |= LOGERR_ERR; @@ -2341,8 +2390,10 @@ printpidfile: } loginfox(PACKAGE "-" VERSION " starting"); - if (ctx.stdin_valid && freopen(_PATH_DEVNULL, "w", stdin) == NULL) - logwarn("freopen stdin"); + + // We don't need stdin past this point + if (ctx.stdin_valid) + dup_null(STDIN_FILENO); #if defined(USE_SIGNALS) && !defined(THERE_IS_NO_FORK) if (!(ctx.options & DHCPCD_DAEMONISE)) @@ -2385,10 +2436,9 @@ printpidfile: logerr("dup2"); close(stderr_fd[0]); close(stderr_fd[1]); - } else if (ctx.stdout_valid) { - if (freopen(_PATH_DEVNULL, "w", stdout) == NULL) - logerr("freopen stdout"); - } + } else if (ctx.stdout_valid) + dup_null(STDOUT_FILENO); + if (setsid() == -1) { logerr("%s: setsid", __func__); goto exit_failure; Index: src/external/bsd/dhcpcd/dist/src/privsep.c diff -u src/external/bsd/dhcpcd/dist/src/privsep.c:1.16 src/external/bsd/dhcpcd/dist/src/privsep.c:1.17 --- src/external/bsd/dhcpcd/dist/src/privsep.c:1.16 Fri Oct 6 08:49:42 2023 +++ src/external/bsd/dhcpcd/dist/src/privsep.c Thu Oct 19 11:26:52 2023 @@ -1100,6 +1100,26 @@ ps_recvmsg(int rfd, unsigned short event } ssize_t +ps_daemonised(struct dhcpcd_ctx *ctx) +{ + struct ps_process *psp; + ssize_t err = 0; + + dhcpcd_daemonised(ctx); + + /* Echo the message to all processes */ + TAILQ_FOREACH(psp, &ctx->ps_processes, next) { + if (psp->psp_pid == getpid()) + continue; + if (ps_sendcmd(psp->psp_ctx, psp->psp_fd, PS_DAEMONISED, + 0, NULL, 0) == -1) + err = -1; + } + + return err; +} + +ssize_t ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd, unsigned short events, ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *), void *cbctx) @@ -1131,6 +1151,9 @@ ps_recvpsmsg(struct dhcpcd_ctx *ctx, int if (psm.psm_hdr.ps_cmd == PS_STOP) { stop = true; len = 0; + } else if (psm.psm_hdr.ps_cmd == PS_DAEMONISED) { + ps_daemonised(ctx); + return 0; } } Index: src/external/bsd/dhcpcd/dist/src/script.c diff -u src/external/bsd/dhcpcd/dist/src/script.c:1.16 src/external/bsd/dhcpcd/dist/src/script.c:1.17 --- src/external/bsd/dhcpcd/dist/src/script.c:1.16 Wed Jul 19 13:53:03 2023 +++ src/external/bsd/dhcpcd/dist/src/script.c Thu Oct 19 11:26:52 2023 @@ -682,33 +682,42 @@ send_interface(struct fd_list *fd, const } static int +script_status(const char *script, int status) +{ + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) + logerrx("%s: %s: WEXITSTATUS %d", + __func__, script, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) + logerrx("%s: %s: %s", + __func__, script, strsignal(WTERMSIG(status))); + + return WEXITSTATUS(status); +} + +static int script_run(struct dhcpcd_ctx *ctx, char **argv) { pid_t pid; - int status = 0; + int status; pid = script_exec(argv, ctx->script_env); - if (pid == -1) + if (pid == -1) { logerr("%s: %s", __func__, argv[0]); - else if (pid != 0) { - /* Wait for the script to finish */ - while (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) { - logerr("%s: waitpid", __func__); - status = 0; - break; - } + return -1; + } else if (pid == 0) + return 0; + + /* Wait for the script to finish */ + while (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { + logerr("%s: waitpid", __func__); + status = 0; + break; } - if (WIFEXITED(status)) { - if (WEXITSTATUS(status)) - logerrx("%s: %s: WEXITSTATUS %d", - __func__, argv[0], WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) - logerrx("%s: %s: %s", - __func__, argv[0], strsignal(WTERMSIG(status))); } - - return WEXITSTATUS(status); + return script_status(argv[0], status); } int @@ -762,10 +771,14 @@ script_runreason(const struct interface logdebugx("%s: executing: %s %s", ifp->name, argv[0], reason); #ifdef PRIVSEP - if (ctx->options & DHCPCD_PRIVSEP) { - if (ps_root_script(ctx, - ctx->script_buf, (size_t)buflen) == -1) + if (IN_PRIVSEP(ctx)) { + ssize_t err; + + err = ps_root_script(ctx, ctx->script_buf, (size_t)buflen); + if (err == -1) logerr(__func__); + else + script_status(ctx->script, (int)err); goto send_listeners; } #endif