From: Roy Marples Date: Tue, 16 Jun 2026 22:13:45 +0000 (+0100) Subject: sun: Enable building for privsep X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2d2d28e7c3f99aee1a3e919dc97a366aca4e6936;p=thirdparty%2Fdhcpcd.git sun: Enable building for privsep 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. --- diff --git a/configure b/configure index 88654c58..3fbb7354 100755 --- 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 diff --git a/src/if-sun.c b/src/if-sun.c index 818331cf..15c716f9 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -27,6 +27,10 @@ */ /* Stop sunos headers including the system queue ... */ +#if 1 +#include "queue.h" +#endif + #include #include #include @@ -53,8 +57,6 @@ #include #include -#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. */ diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 68edf7ad..d8171f94 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -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 } diff --git a/src/ipv6nd.h b/src/ipv6nd.h index a87b57e6..63799411 100644 --- a/src/ipv6nd.h +++ b/src/ipv6nd.h @@ -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); diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c index 86da7e47..8dbb859e 100644 --- a/src/privsep-bpf.c +++ b/src/privsep-bpf.c @@ -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; diff --git a/src/privsep-inet.c b/src/privsep-inet.c index fe283359..8fa0b04c 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -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; diff --git a/src/privsep-root.c b/src/privsep-root.c index 7d816cf6..558fad92 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -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; diff --git a/src/privsep-root.h b/src/privsep-root.h index 0857f0a4..3901ef4f 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -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 diff --git a/src/privsep-sun.c b/src/privsep-sun.c index 333070bf..e19a4de8 100644 --- a/src/privsep-sun.c +++ b/src/privsep-sun.c @@ -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: diff --git a/src/privsep.c b/src/privsep.c index 25ef53dd..4ecad2d9 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -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; }