From 60594cd12aa5fc6168052aaded3b499b4bc9edec Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 30 Oct 2025 14:09:28 +0000 Subject: [PATCH] Adjust for new eloop. Needs more testing. --- .clangd | 10 +++++- configure | 83 ------------------------------------------- src/dhcpcd.c | 40 +++++++++++++-------- src/dhcpcd.h | 3 -- src/privsep-bpf.c | 3 +- src/privsep-control.c | 2 +- src/privsep-inet.c | 4 +-- src/privsep-root.c | 61 ++++++++++++++++++++----------- src/privsep.c | 43 ++++++++++------------ src/privsep.h | 3 +- 10 files changed, 100 insertions(+), 152 deletions(-) diff --git a/.clangd b/.clangd index 3592250e..2b10bf3c 100644 --- a/.clangd +++ b/.clangd @@ -1,4 +1,12 @@ +If: + PathMatch: src/dev/.*\.c +CompileFlags: + Add: [-I.., -I../.., -I../../compat] +--- If: PathMatch: src/.*\.c CompileFlags: - Add: [-I., -I.., -I../compat] + Add: [-I.., -I../compat] +--- +CompileFlags: + Add: [-DINET, -DARP, -DARPING, -DIPV4LL, -DINET6, -DDHCP6, -DPLUGIN_DEV, -DAUTH, -DPRIVSEP] diff --git a/configure b/configure index 45ad4d2d..a0243dac 100755 --- a/configure +++ b/configure @@ -1249,89 +1249,6 @@ fi # Set this for eloop echo "#define HAVE_REALLOCARRAY" >>$CONFIG_H -# Detect a polling mechanism. -# See src/eloop.c as to why we only detect ppoll, pollts and pselect and -# not others like epoll or kqueue. -if [ -z "$POLL" ]; then - printf "Testing for ppoll ... " - cat <_ppoll.c -#include -#include -int main(void) { - struct pollfd fds; - return ppoll(&fds, 1, NULL, NULL); -} -EOF - if $XCC _ppoll.c -o _ppoll 2>&3; then - POLL=ppoll - echo "yes" - else - echo "no" - fi - rm -f _ppoll.c _ppoll -fi -if [ -z "$POLL" ]; then - printf "Testing for pollts ... " - cat <_pollts.c -#include -#include -int main(void) { - struct pollfd fds; - return pollts(&fds, 1, NULL, NULL); -} -EOF - if $XCC _pollts.c -o _pollts 2>&3; then - POLL=pollts - echo "yes" - else - echo "no" - fi - rm -f _pollts.c _pollts -fi -if [ -z "$POLL" ]; then - printf "Testing for pselect ... " - cat <_pselect.c -#include -#include -int main(void) { - return pselect(0, NULL, NULL, NULL, NULL, NULL); -} -EOF - if $XCC _pselect.c -o _pselect 2>&3; then - POLL=pselect - echo "yes" - else - echo "no" - fi - rm -f _pselect.c _pselect -fi -case "$POLL" in -kqueue1) - echo "#define HAVE_KQUEUE" >>$CONFIG_H - echo "#define HAVE_KQUEUE1" >>$CONFIG_H - POLL=kqueue - ;; -kqueue) - echo "#define HAVE_KQUEUE" >>$CONFIG_H - ;; -epoll) - echo "#define HAVE_EPOLL" >>$CONFIG_H - ;; -ppoll) - echo "#define HAVE_PPOLL" >>$CONFIG_H - ;; -pollts) - echo "#define HAVE_POLLTS" >>$CONFIG_H - ;; -pselect) - echo "#define HAVE_PSELECT" >>$CONFIG_H - ;; -*) - echo "No suitable polling function is available, not even pselect" >&2 - exit 1 - ;; -esac - if [ -z "$BE64ENC" ]; then printf "Testing for be64enc ... " cat <_be64enc.c diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 1037469c..5fdd7c1c 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1450,8 +1450,9 @@ dhcpcd_signal_cb(int sig, void *arg) return; } - if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) { - if (sig != SIGHUP && + if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) + { + if (ctx->fork_fd != -1 && sig != SIGHUP && send(ctx->fork_fd, &sig, sizeof(sig), MSG_EOR) == -1) logerr("%s: send", __func__); return; @@ -2243,7 +2244,7 @@ printpidfile: eloop_signal_set_cb(ctx.eloop, dhcpcd_signals, dhcpcd_signals_len, dhcpcd_signal_cb, &ctx); - if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) { + if (eloop_signal_mask(ctx.eloop) == -1) { logerr("%s: eloop_signal_mask", __func__); goto exit_failure; } @@ -2408,6 +2409,7 @@ printpidfile: logerr("socketpair"); goto exit_failure; } + switch (pid = fork()) { case -1: logerr("fork"); @@ -2421,23 +2423,33 @@ printpidfile: goto exit_failure; } #endif - if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ, - dhcpcd_fork_cb, &ctx) == -1) - logerr("%s: eloop_event_add", __func__); - if (setsid() == -1) { logerr("%s: setsid", __func__); goto exit_failure; } /* Ensure we can never get a controlling terminal */ - switch (pid = fork()) { - case -1: + pid = fork(); + if (pid == -1) { logerr("fork"); goto exit_failure; - case 0: - eloop_forked(ctx.eloop); - break; - default: + } + /* setsid again to ensure our child processes have the + * correct ppid */ + if (pid == 0 && setsid() == -1) { + logerr("%s: setsid", __func__); + goto exit_failure; + } + if (eloop_forked(ctx.eloop, ELF_KEEP_ALL) == -1) { + logerr("%s: eloop_forked", __func__); + goto exit_failure; + } + if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ, + dhcpcd_fork_cb, &ctx) == -1) + { + logerr("%s: eloop_event_add", __func__); + goto exit_failure; + } + if (pid != 0) { ctx.options |= DHCPCD_FORKED; /* A lie */ i = EXIT_SUCCESS; goto exit1; @@ -2651,7 +2663,7 @@ start_manager: } run_loop: - i = eloop_start(ctx.eloop, &ctx.sigset); + i = eloop_start(ctx.eloop); if (i < 0) { logerr("%s: eloop_start", __func__); goto exit_failure; diff --git a/src/dhcpcd.h b/src/dhcpcd.h index c8393a0d..527399d3 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -156,9 +156,6 @@ struct dhcpcd_ctx { int seq; /* route message sequence no */ int sseq; /* successful seq no sent */ -#ifdef USE_SIGNALS - sigset_t sigset; -#endif struct eloop *eloop; char *script; diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c index 97765dda..e2b170bd 100644 --- a/src/privsep-bpf.c +++ b/src/privsep-bpf.c @@ -259,7 +259,8 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) addr != NULL ? " " : "", addr != NULL ? addr : ""); start = ps_startprocess(psp, ps_bpf_recvmsg, NULL, - ps_bpf_start_bpf, NULL, PSF_DROPPRIVS); + ps_bpf_start_bpf, PSF_DROPPRIVS); + switch (start) { case -1: ps_freeprocess(psp); diff --git a/src/privsep-control.c b/src/privsep-control.c index 0ce39e79..b9ea7f9c 100644 --- a/src/privsep-control.c +++ b/src/privsep-control.c @@ -236,7 +236,7 @@ ps_ctl_start(struct dhcpcd_ctx *ctx) psp = ctx->ps_ctl = ps_newprocess(ctx, &id); strlcpy(psp->psp_name, "control proxy", sizeof(psp->psp_name)); pid = ps_startprocess(psp, ps_ctl_recvmsg, ps_ctl_dodispatch, - ps_ctl_startcb, NULL, PSF_DROPPRIVS); + ps_ctl_startcb, PSF_DROPPRIVS); if (pid == -1) return -1; diff --git a/src/privsep-inet.c b/src/privsep-inet.c index 1c0c81ac..5ca356a1 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -370,7 +370,7 @@ ps_inet_start(struct dhcpcd_ctx *ctx) strlcpy(psp->psp_name, "network proxy", sizeof(psp->psp_name)); pid = ps_startprocess(psp, ps_inet_recvmsg, ps_inet_dodispatch, - ps_inet_startcb, NULL, PSF_DROPPRIVS); + ps_inet_startcb, PSF_DROPPRIVS); if (pid == 0) ps_entersandbox("stdio", NULL); @@ -594,7 +594,7 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) "%s proxy %s", psp->psp_protostr, inet_ntop(psa->psa_family, ia, buf, sizeof(buf))); start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL, - start_func, NULL, PSF_DROPPRIVS); + start_func, PSF_DROPPRIVS); switch (start) { case -1: ps_freeprocess(psp); diff --git a/src/privsep-root.c b/src/privsep-root.c index 35dec006..25050084 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -87,6 +87,9 @@ ps_root_readerrorcb(void *arg, unsigned short events) ssize_t len; int exit_code = EXIT_FAILURE; + if (events & ELE_HANGUP) + goto out; + if (events != ELE_READ) logerrx("%s: unexpected event 0x%04x", __func__, events); @@ -111,22 +114,17 @@ out: ssize_t ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len) { - struct psr_ctx psr_ctx = { - .psr_ctx = ctx, - .psr_data = data, .psr_datalen = len, - }; - int fd = PS_ROOT_FD(ctx); + struct psr_ctx *pc = ctx->ps_root->psp_data; + int err; - if (eloop_event_add(ctx->ps_eloop, fd, ELE_READ, - ps_root_readerrorcb, &psr_ctx) == -1) - return -1; - - eloop_enter(ctx->ps_eloop); - eloop_start(ctx->ps_eloop, &ctx->sigset); - eloop_event_delete(ctx->ps_eloop, fd); + pc->psr_data = data; + pc->psr_datalen = len; + err = eloop_start(ctx->ps_eloop); + if (err < 0) + return err; - errno = psr_ctx.psr_error.psr_errno; - return psr_ctx.psr_error.psr_result; + errno = pc->psr_error.psr_errno; + return pc->psr_error.psr_result; } #ifdef PRIVSEP_GETIFADDRS @@ -180,15 +178,15 @@ ps_root_mreaderror(struct dhcpcd_ctx *ctx, void **data, size_t *len) struct psr_ctx psr_ctx = { .psr_ctx = ctx, }; - int fd = PS_ROOT_FD(ctx); + int fd = PS_ROOT_FD(ctx), err; if (eloop_event_add(ctx->ps_eloop, fd, ELE_READ, ps_root_mreaderrorcb, &psr_ctx) == -1) return -1; - eloop_enter(ctx->ps_eloop); - eloop_start(ctx->ps_eloop, &ctx->sigset); - eloop_event_delete(ctx->ps_eloop, fd); + err = eloop_start(ctx->ps_eloop, &ctx->sigset); + if (err < 0) + return err; errno = psr_ctx.psr_error.psr_errno; *data = psr_ctx.psr_data; @@ -873,8 +871,9 @@ ps_root_start(struct dhcpcd_ctx *ctx) .psi_cmd = PS_ROOT, }; struct ps_process *psp; - int logfd[2], datafd[2]; + int logfd[2] = { -1, -1}, datafd[2] = { -1, -1}; pid_t pid; + struct psr_ctx *pc; if (xsocketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, logfd) == -1) return -1; @@ -892,10 +891,30 @@ ps_root_start(struct dhcpcd_ctx *ctx) return -1; #endif + + pc = malloc(sizeof(*pc)); + if (pc == NULL) + return -1; + pc->psr_ctx = ctx; + psp = ctx->ps_root = ps_newprocess(ctx, &id); + if (psp == NULL) + { + free(pc); + return -1; + } strlcpy(psp->psp_name, "privileged proxy", sizeof(psp->psp_name)); pid = ps_startprocess(psp, ps_root_recvmsg, NULL, - ps_root_startcb, ps_root_signalcb, PSF_ELOOP); + ps_root_startcb, PSF_ELOOP); + if (pid == -1) { + free(pc); + return -1; + } + + psp->psp_data = pc; + if (eloop_event_add(ctx->ps_eloop, psp->psp_fd, ELE_READ, + ps_root_readerrorcb, pc) == -1) + return -1; if (pid == 0) { ctx->ps_log_fd = logfd[0]; /* Keep open to pass to processes */ @@ -916,7 +935,7 @@ ps_root_start(struct dhcpcd_ctx *ctx) close(datafd[1]); if (eloop_event_add(ctx->eloop, ctx->ps_data_fd, ELE_READ, ps_root_dispatch, ctx) == -1) - return 1; + return -1; return pid; } diff --git a/src/privsep.c b/src/privsep.c index 380a4f62..88ab11a1 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -350,7 +350,7 @@ pid_t ps_startprocess(struct ps_process *psp, void (*recv_msg)(void *, unsigned short), void (*recv_unpriv_msg)(void *, unsigned short), - int (*callback)(struct ps_process *), void (*signal_cb)(int, void *), + int (*callback)(struct ps_process *), unsigned int flags) { struct dhcpcd_ctx *ctx = psp->psp_ctx; @@ -433,28 +433,25 @@ ps_startprocess(struct ps_process *psp, getpid(), ctx->ps_log_fd, ctx->ps_data_fd, psp->psp_fd); #endif - eloop_clear(ctx->eloop, -1); - eloop_forked(ctx->eloop); - 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) { - logerr("%s: eloop_signal_mask", __func__); - goto errexit; - } - if (ctx->fork_fd != -1) { - /* Already removed from eloop thanks to above clear. */ close(ctx->fork_fd); ctx->fork_fd = -1; } - /* This process has no need of the blocking inner eloop. */ - if (!(flags & PSF_ELOOP)) { - eloop_free(ctx->ps_eloop); - ctx->ps_eloop = NULL; - } else - eloop_forked(ctx->ps_eloop); + if (eloop_forked(ctx->eloop, ELF_KEEP_SIGNALS) == -1) { + logerr("%s: eloop_forked", __func__); + goto errexit; + } + if (ctx->ps_eloop != NULL) { + if (eloop_forked(ctx->ps_eloop, ELF_KEEP_SIGNALS) == -1) { + logerr("%s: eloop_forked", __func__); + goto errexit; + } + if (!(flags & PSF_ELOOP)) { + eloop_free(ctx->ps_eloop); + ctx->ps_eloop = NULL; + } + } pidfile_clean(); ps_freeprocesses(ctx, psp); @@ -478,7 +475,7 @@ ps_startprocess(struct ps_process *psp, if (eloop_event_add(ctx->eloop, psp->psp_fd, ELE_READ, recv_msg, psp) == -1) { - logerr("%d %s: eloop_event_add XX fd %d", getpid(), __func__, psp->psp_fd); + logerr("%s: eloop_event_add", __func__); goto errexit; } @@ -556,11 +553,8 @@ ps_start(struct dhcpcd_ctx *ctx) TAILQ_INIT(&ctx->ps_processes); /* We need an inner eloop to block with. */ - if ((ctx->ps_eloop = eloop_new()) == NULL) + if ((ctx->ps_eloop = eloop_new_with_signals(ctx->eloop)) == NULL) return -1; - eloop_signal_set_cb(ctx->ps_eloop, - dhcpcd_signals, dhcpcd_signals_len, - dhcpcd_signal_cb, ctx); switch (pid = ps_root_start(ctx)) { case -1: @@ -751,7 +745,6 @@ ps_stopwait(struct dhcpcd_ctx *ctx) if (eloop_timeout_add_sec(ctx->ps_eloop, PS_PROCESS_TIMEOUT, ps_process_timeout, ctx) == -1) logerr("%s: eloop_timeout_add_sec", __func__); - eloop_enter(ctx->ps_eloop); #ifdef HAVE_CAPSICUM struct ps_process *psp; @@ -766,7 +759,7 @@ ps_stopwait(struct dhcpcd_ctx *ctx) } #endif - error = eloop_start(ctx->ps_eloop, &ctx->sigset); + error = eloop_start(ctx->ps_eloop); if (error != EXIT_SUCCESS) logerr("%s: eloop_start", __func__); diff --git a/src/privsep.h b/src/privsep.h index 91d6884c..7d4e6e11 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -184,6 +184,7 @@ struct ps_process { char psp_name[PSP_NAMESIZE]; uint16_t psp_proto; const char *psp_protostr; + void *psp_data; bool psp_started; #ifdef INET @@ -245,7 +246,7 @@ int ps_seccomp_enter(void); pid_t ps_startprocess(struct ps_process *, void (*recv_msg)(void *, unsigned short), void (*recv_unpriv_msg)(void *, unsigned short), - int (*callback)(struct ps_process *), void (*)(int, void *), + int (*callback)(struct ps_process *), unsigned int); int ps_stopprocess(struct ps_process *); struct ps_process *ps_findprocess(struct dhcpcd_ctx *, struct ps_id *); -- 2.47.3