]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
sun: Enable building for privsep
authorRoy Marples <roy@marples.name>
Tue, 16 Jun 2026 22:13:45 +0000 (23:13 +0100)
committerGitHub <noreply@github.com>
Tue, 16 Jun 2026 22:13:45 +0000 (23:13 +0100)
privsep has never worked on Sun.
To be fair, it's not any better because all processes
run as root, outside a chroot and without limits.

So why do this?

So we can eventually remove all non privsep code from dhcpcd, to
reduce complexity and provide a more secure platform for other OS.

configure
src/if-sun.c
src/ipv6nd.c
src/ipv6nd.h
src/privsep-bpf.c
src/privsep-inet.c
src/privsep-root.c
src/privsep-root.h
src/privsep-sun.c
src/privsep.c

index 88654c589400904f0809adcd9da7081cb6a64641..3fbb73540568111335cf139f0fc8f477dae877fc 100755 (executable)
--- a/configure
+++ b/configure
@@ -578,15 +578,7 @@ if [ -z "$AUTH" ] || [ "$AUTH" = yes ]; then
        echo "SRCS+=            auth.c" >>$CONFIG_MK
 fi
 
-if [ -z "$PRIVSEP" ]; then
-       # privilege separation works fine .... except on Solaris
-       case "$OS" in
-       solaris*|sunos*)        PRIVSEP=no;;
-       *)                      PRIVSEP=yes;;
-       esac
-fi
-
-if [ "$PRIVSEP" = yes ]; then
+if [ -z "$PRIVSEP" ] || [ "$PRIVSEP" = yes ]; then
        echo "Enabling Privilege Separation"
 
        # Try and work out system user
index 818331cfb268b010a827f923f973f21796fa2f3d..15c716f9d841f6cd12a007bf2b15a50e3411da00 100644 (file)
  */
 
 /* Stop sunos headers including the system queue ... */
+#if 1
+#include "queue.h"
+#endif
+
 #include <sys/ioctl.h>
 #include <sys/mac.h>
 #include <sys/pfmod.h>
@@ -53,8 +57,6 @@
 #include <stropts.h>
 #include <unistd.h>
 
-#include "queue.h"
-
 /* Private libsocket interface we can hook into to get
  * a better getifaddrs(3).
  * From libsocket_priv.h, which is not always distributed so is here. */
index 68edf7ad0aed45335bb5371cb156c1b5275acf68..d8171f94073b3a238048a87347629d6902b9a2ab 100644 (file)
@@ -274,43 +274,31 @@ eexit:
 
 #ifdef __sun
 int
-ipv6nd_openif(struct interface *ifp)
+ipv6nd_openif(unsigned int ifindex)
 {
        int fd;
        struct ipv6_mreq mreq = {
                .ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
-               .ipv6mr_interface = ifp->index
+               .ipv6mr_interface = ifindex,
        };
-       struct rs_state *state = RS_STATE(ifp);
-       uint_t ifindex = ifp->index;
-
-       if (state->nd_fd != -1)
-               return state->nd_fd;
 
        fd = ipv6nd_open(true);
        if (fd == -1)
                return -1;
 
        if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &ifindex,
-               sizeof(ifindex)) == -1) {
-               close(fd);
-               return -1;
-       }
+               sizeof(ifindex)) == -1)
+               goto err;
 
        if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
-               sizeof(mreq)) == -1) {
-               close(fd);
-               return -1;
-       }
+               sizeof(mreq)) == -1)
+               goto err;
 
-       if (eloop_event_add(ifp->ctx->eloop, fd, ELE_READ, ipv6nd_handledata,
-               ifp) == -1) {
-               close(fd);
-               return -1;
-       }
-
-       state->nd_fd = fd;
        return fd;
+
+err:
+       close(fd);
+       return -1;
 }
 #endif
 
@@ -405,8 +393,16 @@ ipv6nd_sendrsprobe(void *arg)
 #endif
 #ifdef __sun
        if (state->nd_fd == -1) {
-               if (ipv6nd_openif(ifp) == -1) {
+               state->nd_fd = ipv6nd_openif(ifp->index);
+               if (state->nd_fd == -1) {
+                       logerr(__func__);
+                       return;
+               }
+               if (eloop_event_add(ifp->ctx->eloop, state->nd_fd, ELE_READ,
+                       ipv6nd_handledata, ifp) == -1) {
                        logerr(__func__);
+                       close(state->nd_fd);
+                       state->nd_fd = -1;
                        return;
                }
        }
@@ -2009,6 +2005,12 @@ ipv6nd_startrs2(void *arg)
                }
 #ifdef __sun
                state->nd_fd = -1;
+#ifdef PRIVSEP
+               if (IN_PRIVSEP(ifp->ctx) && ps_inet_opennd(ifp) == -1) {
+                       logerr("%s: ps_inet_opennd", ifp->name);
+                       return;
+               }
+#endif
 #endif
        }
 
index a87b57e681e8bd3f3cef165bf8ed1ee3ceeb2d2f..637994111d35d59543fb280aed29aa1499882530 100644 (file)
@@ -115,7 +115,7 @@ struct rs_state {
 
 int ipv6nd_open(bool);
 #ifdef __sun
-int ipv6nd_openif(struct interface *);
+int ipv6nd_openif(unsigned int);
 #endif
 void ipv6nd_recvmsg(struct dhcpcd_ctx *, struct msghdr *);
 int ipv6nd_rtpref(uint8_t);
index 86da7e47f4ae0b3066b04e0b87d518ef469c86d2..8dbb859e268139a7d7eac8c2237c92b0bcd03f71 100644 (file)
@@ -167,7 +167,7 @@ ps_bpf_start_bpf(struct ps_process *psp)
 
        psp->psp_bpf = bpf_open(&psp->psp_ifp, psp->psp_filter, ia);
 #ifdef DEBUG_FD
-       logdebugx("pid %d bpf_fd=%d", getpid(), psp->psp_bpf->bpf_fd);
+       logdebugx("pid %ld bpf_fd=%d", (long)getpid(), psp->psp_bpf->bpf_fd);
 #endif
        if (psp->psp_bpf == NULL)
                logerr("%s: bpf_open", __func__);
@@ -273,8 +273,8 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
                ps_entersandbox("stdio", NULL);
                break;
        default:
-               logdebugx("%s: spawned %s on PID %d", psp->psp_ifname,
-                   psp->psp_name, psp->psp_pid);
+               logdebugx("%s: spawned %s on PID %ld", psp->psp_ifname,
+                   psp->psp_name, (long)psp->psp_pid);
                break;
        }
        return start;
index fe283359e83c2c676e9443a743760bbddbedb133..8fa0b04c93d672b3d07e2c34cef1eba5cfa0d4a9 100644 (file)
@@ -66,11 +66,10 @@ static void
 ps_inet_recvra(void *arg, unsigned short events)
 {
 #ifdef __sun
-       struct interface *ifp = arg;
-       struct rs_state *state = RS_STATE(ifp);
-       struct dhcpcd_ctx *ctx = ifp->ctx;
+       struct ps_process *psp = arg;
 
-       if (ps_recvmsg(state->nd_fd, events, PS_ND, ctx->ps_inet->psp_fd) == -1)
+       if (ps_recvmsg(psp->psp_work_fd, events, PS_ND,
+               psp->psp_ctx->ps_data_fd) == -1)
                logerr(__func__);
 #else
        struct dhcpcd_ctx *ctx = arg;
@@ -424,23 +423,14 @@ ps_inet_listenin(struct ps_process *psp)
 #endif
 
 #if defined(INET6) && defined(__sun)
-static void
-ps_inet_recvin6nd(void *arg)
-{
-       struct ps_process *psp = arg;
-
-       if (ps_recvmsg(psp->psp_work_fd, PS_ND, psp->psp_ctx->ps_data_fd) == -1)
-               logerr(__func__);
-}
-
 static int
 ps_inet_listennd(struct ps_process *psp)
 {
 #ifdef HAVE_SETPROCTITLE
-       setproctitle("[ND network proxy]");
+       setproctitle("[%s proxy] %s", psp->psp_protostr, psp->psp_ifname);
 #endif
 
-       psp->psp_work_fd = ipv6nd_open(&psp->psp_ifp);
+       psp->psp_work_fd = ipv6nd_openif(psp->psp_ifindex);
        if (psp->psp_work_fd == -1) {
                logerr(__func__);
                return -1;
@@ -453,8 +443,8 @@ ps_inet_listennd(struct ps_process *psp)
        }
 #endif
 
-       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
-               ps_inet_recvin6nd, psp) == -1) {
+       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
+               ps_inet_recvra, psp) == -1) {
                logerr(__func__);
                return -1;
        }
@@ -506,13 +496,36 @@ ps_inet_listenin6(struct ps_process *psp)
 }
 #endif
 
+static ssize_t
+ps_inet_recvmsgpspcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
+{
+       struct ps_process *psp = arg;
+
+#ifdef PRIVSEP_DEBUG
+       logerrx("%s: IN cmd %x, psp %p", __func__, psm->ps_cmd, psp);
+#endif
+
+       switch (psm->ps_cmd) {
+       case PS_ND:
+               if (!ps_inet_validnd(msg))
+                       return -1;
+               break;
+       default:
+               errno = EINVAL;
+               return -1;
+       }
+
+       return sendmsg(psp->psp_work_fd, msg, 0);
+}
+
 static void
 ps_inet_recvmsgpsp(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
        /* Receive shutdown. */
-       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
+       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events,
+               ps_inet_recvmsgpspcb, psp) == -1)
                logerr(__func__);
 }
 
@@ -524,7 +537,7 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
        int (*start_func)(struct ps_process *);
        pid_t start;
        struct ps_addr *psa = &psm->ps_id.psi_addr;
-       void *ia;
+       void *ia = NULL;
        char buf[INET_MAX_ADDRSTRLEN];
 
        cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP));
@@ -567,7 +580,6 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
        case PS_ND:
                start_func = ps_inet_listennd;
                psp->psp_protostr = "ND";
-               ia = &psa->psa_in6_addr;
                break;
 #endif
 #ifdef DHCP6
@@ -584,9 +596,9 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
                return -1;
        }
 
-       snprintf(psp->psp_name, sizeof(psp->psp_name), "%s proxy %s",
-           psp->psp_protostr,
-           inet_ntop(psa->psa_family, ia, buf, sizeof(buf)));
+       snprintf(psp->psp_name, sizeof(psp->psp_name), "%s proxy%s%s",
+           psp->psp_protostr, ia != NULL ? " " : "",
+           ia != NULL ? inet_ntop(psa->psa_family, ia, buf, sizeof(buf)) : "");
        start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL, start_func,
            PSF_DROPPRIVS);
        switch (start) {
@@ -597,8 +609,8 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg)
                ps_entersandbox("stdio", NULL);
                break;
        default:
-               logdebugx("%s: spawned %s on PID %d", psp->psp_ifname,
-                   psp->psp_name, psp->psp_pid);
+               logdebugx("%s: spawned %s on PID %ld", psp->psp_ifname,
+                   psp->psp_name, (long)psp->psp_pid);
                break;
        }
        return start;
index 7d816cf642e0c914155ec80dad78fda7485fc984..558fad92f789f96388b5c4462b147bee53b9a11d 100644 (file)
@@ -455,17 +455,17 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
                        return ps_stopprocess(psp);
                } else if (psm->ps_cmd & PS_START) {
                        /* Process has already started .... */
-                       logdebugx("%s%sprocess %s already started on pid %d",
+                       logdebugx("%s%sprocess %s already started on pid %ld",
                            psp->psp_ifname,
                            psp->psp_ifname[0] != '\0' ? ": " : "",
-                           psp->psp_name, psp->psp_pid);
+                           psp->psp_name, (long)psp->psp_pid);
                        return 0;
                }
 
                err = ps_sendpsmmsg(ctx, psp->psp_fd, psm, msg);
                if (err == -1) {
-                       logerr("%s: failed to send message to pid %d", __func__,
-                           psp->psp_pid);
+                       logerr("%s: failed to send message to pid %ld",
+                           __func__, (long)psp->psp_pid);
                        ps_freeprocess(psp);
                }
                return 0;
@@ -672,7 +672,7 @@ ps_root_startcb(struct ps_process *psp)
                        logerr("%s: setsockopt SO_RCVBUF DHCP", __func__);
        }
 #endif
-#ifdef INET6
+#if defined(INET6) && !defined(__sun)
        if (ctx->options & DHCPCD_IPV6) {
                int buflen = 1;
 
@@ -734,18 +734,18 @@ ps_root_signalcb(int sig, void *arg)
                }
 
                if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
-                       logerrx("%s%s%s exited unexpectedly from PID %d,"
+                       logerrx("%s%s%s exited unexpectedly from PID %ld,"
                                " code=%d",
-                           ifname, ifname[0] != '\0' ? ": " : "", name, pid,
-                           WEXITSTATUS(status));
+                           ifname, ifname[0] != '\0' ? ": " : "", name,
+                           (long)pid, WEXITSTATUS(status));
                else if (WIFSIGNALED(status))
-                       logerrx("%s%s%s exited unexpectedly from PID %d,"
+                       logerrx("%s%s%s exited unexpectedly from PID %ld,"
                                " signal=%s",
-                           ifname, ifname[0] != '\0' ? ": " : "", name, pid,
-                           strsignal(WTERMSIG(status)));
+                           ifname, ifname[0] != '\0' ? ": " : "", name,
+                           (long)pid, strsignal(WTERMSIG(status)));
                else
-                       logdebugx("%s%s%s exited from PID %d", ifname,
-                           ifname[0] != '\0' ? ": " : "", name, pid);
+                       logdebugx("%s%s%s exited from PID %ld", ifname,
+                           ifname[0] != '\0' ? ": " : "", name, (long)pid);
 
                if (psp != NULL)
                        ps_freeprocess(psp);
@@ -910,7 +910,7 @@ ps_root_close(struct dhcpcd_ctx *ctx)
                ctx->udp_wfd = -1;
        }
 #endif
-#ifdef INET6
+#if defined(INET6) && !defined(__sun)
        if (ctx->nd_fd != -1) {
                close(ctx->nd_fd);
                ctx->nd_fd = -1;
@@ -980,9 +980,9 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
         * So we just log the intent to exit.
         * Even sending this will be a race to exit. */
        if (psp) {
-               logdebugx("%s%s%s will exit from PID %d", psp->psp_ifname,
+               logdebugx("%s%s%s will exit from PID %ld", psp->psp_ifname,
                    psp->psp_ifname[0] != '\0' ? ": " : "", psp->psp_name,
-                   psp->psp_pid);
+                   (long)psp->psp_pid);
 
                if (ps_stopprocess(psp) == -1)
                        return -1;
index 0857f0a4a7f527d094011a369aecb754c3989cd1..3901ef4f4a4404e3d419ac9426e8ba013032ad65 100644 (file)
@@ -31,7 +31,8 @@
 
 #include "if.h"
 
-#if defined(PRIVSEP) && (defined(HAVE_CAPSICUM) || defined(__linux__))
+#if defined(PRIVSEP) && \
+    (defined(HAVE_CAPSICUM) || defined(__linux__) || defined(__sun))
 #define PRIVSEP_GETIFADDRS
 #endif
 
index 333070bf8a54909c3c0ffd9081671cafa9df9889..e19a4de87c78b9a1f32ed7ae861905a695b93871 100644 (file)
@@ -35,8 +35,9 @@
 #include "logerr.h"
 #include "privsep.h"
 
-#warning Solaris privsep should compile but wont work,
-#warning no DLPI support, ioctl support need rework
+#warning Solaris privsep should compile and work, but there is no
+#warning chroot support, dropping to dhcpcd user support,
+#warning no DLPI support, no ioctl validation, etc
 /* We should implement privileges(5) as well.
  * https://illumos.org/man/5/privileges */
 
@@ -76,8 +77,8 @@ ps_root_doroute(void *data, size_t len)
 }
 
 ssize_t
-ps_root_os(struct ps_msghdr *psm, struct msghdr *msg, void **rdata,
-    size_t *rlen, __unused bool *free_rdata)
+ps_root_os(__unused struct dhcpcd_ctx *ctx, struct ps_msghdr *psm,
+    struct msghdr *msg, void **rdata, size_t *rlen, __unused bool *free_rdata)
 {
        struct iovec *iov = msg->msg_iov;
        void *data = iov->iov_base;
@@ -87,6 +88,7 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg, void **rdata,
        switch (psm->ps_cmd) {
        case PS_IOCTL6:
                err = ps_root_doioctl6(psm->ps_flags, data, len);
+               break;
        case PS_ROUTE:
                return ps_root_doroute(data, len);
        default:
index 25ef53dd375125b72fba375dd8dd7d252cbd8bee..4ecad2d9481c61e88c67ed78ab898ec4005329b2 100644 (file)
@@ -131,6 +131,9 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
        if (ctx->options & DHCPCD_LAUNCHER)
 #ifdef ASAN
                logwarnx("not chrooting as compiled for ASAN");
+#elif defined(__sun)
+               /* libdpli complains */
+               logwarnx("not chrooting on sun");
 #else
                logdebugx("chrooting as %s to %s", pw->pw_name, pw->pw_dir);
 
@@ -142,21 +145,27 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
        if (chdir("/") == -1)
                logerr("%s: chdir: /", __func__);
 
+#ifdef __sun
+#warning not dropping any privileges on this platform .... eek!
+#else
        if ((setgroups(1, &pw->pw_gid) == -1 || setgid(pw->pw_gid) == -1 ||
                setuid(pw->pw_uid) == -1) &&
            (errno != EPERM || ctx->options & DHCPCD_FORKED)) {
                logerr("failed to drop privileges");
                return -1;
        }
+#endif
 
        struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 };
 
+#ifndef __sun /* RLIMIT_NOFILE and ppoll don't mix */
        /* Prohibit new files, sockets, etc
         * The control proxy *does* need to create new fd's via accept(2). */
        if (ctx->ps_ctl == NULL || ctx->ps_ctl->psp_pid != getpid()) {
                if (setrlimit(RLIMIT_NOFILE, &rzero) == -1)
                        logerr("setrlimit RLIMIT_NOFILE");
        }
+#endif
 
 #define DHC_NOCHKIO (DHCPCD_STARTED | DHCPCD_DAEMONISE)
        /* Prohibit writing to files.
@@ -528,7 +537,7 @@ ps_start(struct dhcpcd_ctx *ctx)
        case 0:
                return 0;
        default:
-               logdebugx("spawned privileged proxy on PID %d", pid);
+               logdebugx("spawned privileged proxy on PID %ld", (long)pid);
        }
 
        /* No point in spawning the generic network listener if we're
@@ -542,7 +551,7 @@ ps_start(struct dhcpcd_ctx *ctx)
        case 0:
                return 0;
        default:
-               logdebugx("spawned network proxy on PID %d", pid);
+               logdebugx("spawned network proxy on PID %ld", (long)pid);
        }
 
 started_net:
@@ -553,7 +562,8 @@ started_net:
                case 0:
                        return 0;
                default:
-                       logdebugx("spawned controller proxy on PID %d", pid);
+                       logdebugx("spawned controller proxy on PID %ld",
+                           (long)pid);
                }
        }
 
@@ -589,7 +599,11 @@ ps_entersandbox(const char *_pledge, const char **sandbox)
        return ps_seccomp_enter();
 #else
        if (sandbox != NULL)
+#ifdef __sun
+               *sandbox = "none";
+#else
                *sandbox = "posix resource limited";
+#endif
        return 0;
 #endif
 }
@@ -1177,8 +1191,14 @@ ps_newprocess(struct dhcpcd_ctx *ctx, struct ps_id *psid)
        psp->psp_pfd = -1;
 #endif
 
-       if (!(ctx->options & DHCPCD_MANAGER))
-               strlcpy(psp->psp_ifname, ctx->ifv[0], sizeof(psp->psp_ifname));
+       if (psid->psi_ifindex != 0) {
+               psp->psp_ifindex = psid->psi_ifindex;
+               if_indextoname(psid->psi_ifindex, psp->psp_ifname);
+       } else {
+               if (!(ctx->options & DHCPCD_MANAGER) && ctx->ifc != 0)
+                       strlcpy(psp->psp_ifname, ctx->ifv[0],
+                           sizeof(psp->psp_ifname));
+       }
        TAILQ_INSERT_TAIL(&ctx->ps_processes, psp, next);
        return psp;
 }