]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Adjust for new eloop.
authorRoy Marples <roy@marples.name>
Thu, 30 Oct 2025 14:09:28 +0000 (14:09 +0000)
committerRoy Marples <roy@marples.name>
Thu, 30 Oct 2025 14:09:28 +0000 (14:09 +0000)
Needs more testing.

.clangd
configure
src/dhcpcd.c
src/dhcpcd.h
src/privsep-bpf.c
src/privsep-control.c
src/privsep-inet.c
src/privsep-root.c
src/privsep.c
src/privsep.h

diff --git a/.clangd b/.clangd
index 3592250e47e97118d6f879eae8983e6580e0f9c4..2b10bf3c52004c42d2eef894c3dd2752204a1610 100644 (file)
--- 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]
index 45ad4d2d868a8d43ee6b3c79b4d6d3a88b718f6d..a0243dacba5cedf168ee5a31218785f7e4e47b66 100755 (executable)
--- 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 <<EOF >_ppoll.c
-#include <poll.h>
-#include <stddef.h>
-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 <<EOF >_pollts.c
-#include <poll.h>
-#include <stddef.h>
-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 <<EOF >_pselect.c
-#include <sys/select.h>
-#include <stdlib.h>
-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 <<EOF >_be64enc.c
index 1037469c37238ff841f42afe3a5c988d5b30aa19..5fdd7c1c400557bd0d4fde56db2572c7a50f3607 100644 (file)
@@ -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;
index c8393a0d86a32e30d6cb442af84d4d1241f4600a..527399d344b3c7e364f4abcf0c7301d45c5abab4 100644 (file)
@@ -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;
index 97765dda8ac7d7507a881371d4d2aca043347084..e2b170bd790a56318938b73f801a6adf9e7d3064 100644 (file)
@@ -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);
index 0ce39e7987943ff08a1d70edf45c3766f39e61d5..b9ea7f9c5d163c30c45296a4a55abd99e94c0b78 100644 (file)
@@ -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;
index 1c0c81ac236daf22057d2b3d0abd7fc80e10d11e..5ca356a14d158acb4e57448457f0e5a56d321634 100644 (file)
@@ -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);
index 35dec006d740b2a1c5eb15e86dbdc349489ceb01..250500845e49c21cf849fa36084d58691bbb0532 100644 (file)
@@ -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;
 }
index 380a4f6231f732359e282e31fbd609bbf1a587c7..88ab11a1e85f80d54dbd61d13a25e1e9a4f51b32 100644 (file)
@@ -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__);
 
index 91d6884c5de2046c368619acd393f1a3daeac421..7d4e6e111fde502cad50484712d691cb47a702f6 100644 (file)
@@ -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 *);