Home | History | Annotate | Line # | Download | only in src
      1 /* SPDX-License-Identifier: BSD-2-Clause */
      2 /*
      3  * Privilege Separation for dhcpcd
      4  * Copyright (c) 2006-2025 Roy Marples <roy (at) marples.name>
      5  * All rights reserved
      6 
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * The current design is this:
     31  * Spawn a priv process to carry out privileged actions and
     32  * spawning unpriv process to initate network connections such as BPF
     33  * or address specific listener.
     34  * Spawn an unpriv process to send/receive common network data.
     35  * Then drop all privs and start running.
     36  * Every process aside from the privileged proxy is chrooted.
     37  * All privsep processes ignore signals - only the manager process accepts them.
     38  *
     39  * dhcpcd will maintain the config file in the chroot, no need to handle
     40  * this in a script or something.
     41  */
     42 
     43 #include <sys/resource.h>
     44 #include <sys/socket.h>
     45 #include <sys/stat.h>
     46 #include <sys/types.h>
     47 #include <sys/wait.h>
     48 
     49 #ifdef AF_LINK
     50 #include <net/if_dl.h>
     51 #endif
     52 
     53 #include <assert.h>
     54 #include <errno.h>
     55 #include <fcntl.h>
     56 #include <grp.h>
     57 #include <paths.h>
     58 #include <pwd.h>
     59 #include <stddef.h>	/* For offsetof, struct padding debug */
     60 #include <signal.h>
     61 #include <stdlib.h>
     62 #include <string.h>
     63 #include <unistd.h>
     64 
     65 #include "arp.h"
     66 #include "common.h"
     67 #include "control.h"
     68 #include "dev.h"
     69 #include "dhcp.h"
     70 #include "dhcp6.h"
     71 #include "eloop.h"
     72 #include "ipv6nd.h"
     73 #include "logerr.h"
     74 #include "privsep.h"
     75 
     76 #ifdef HAVE_CAPSICUM
     77 #include <sys/capsicum.h>
     78 #include <sys/procdesc.h>
     79 #include <capsicum_helpers.h>
     80 #endif
     81 #ifdef HAVE_UTIL_H
     82 #include <util.h>
     83 #endif
     84 
     85 /* CMSG_ALIGN is a Linux extension */
     86 #ifndef CMSG_ALIGN
     87 #define CMSG_ALIGN(n)	(CMSG_SPACE((n)) - CMSG_SPACE(0))
     88 #endif
     89 
     90 /* Calculate number of padding bytes to achieve 'struct cmsghdr' alignment */
     91 #define CALC_CMSG_PADLEN(has_cmsg, pos) \
     92     ((has_cmsg) ? (socklen_t)(CMSG_ALIGN((pos)) - (pos)) : 0)
     93 
     94 int
     95 ps_init(struct dhcpcd_ctx *ctx)
     96 {
     97 	struct passwd *pw;
     98 	struct stat st;
     99 
    100 	errno = 0;
    101 	if ((ctx->ps_user = pw = getpwnam(PRIVSEP_USER)) == NULL) {
    102 		ctx->options &= ~DHCPCD_PRIVSEP;
    103 		if (errno == 0) {
    104 			logerrx("no such user %s", PRIVSEP_USER);
    105 			/* Just incase logerrx caused an error... */
    106 			errno = 0;
    107 		} else
    108 			logerr("getpwnam");
    109 		return -1;
    110 	}
    111 
    112 	if (stat(pw->pw_dir, &st) == -1 || !S_ISDIR(st.st_mode)) {
    113 		ctx->options &= ~DHCPCD_PRIVSEP;
    114 		logerrx("refusing chroot: %s: %s",
    115 		    PRIVSEP_USER, pw->pw_dir);
    116 		errno = 0;
    117 		return -1;
    118 	}
    119 
    120 	ctx->options |= DHCPCD_PRIVSEP;
    121 	return 0;
    122 }
    123 
    124 static int
    125 ps_dropprivs(struct dhcpcd_ctx *ctx)
    126 {
    127 	struct passwd *pw = ctx->ps_user;
    128 	int fd_out = ctx->options & DHCPCD_DUMPLEASE ?
    129 	   STDOUT_FILENO : STDERR_FILENO;
    130 
    131 	if (ctx->options & DHCPCD_LAUNCHER)
    132 #ifdef ASAN
    133 		logwarnx("not chrooting as compiled for ASAN");
    134 #else
    135 		logdebugx("chrooting as %s to %s", pw->pw_name, pw->pw_dir);
    136 
    137 	if (chroot(pw->pw_dir) == -1 &&
    138 	    (errno != EPERM || ctx->options & DHCPCD_FORKED))
    139 		logerr("%s: chroot: %s", __func__, pw->pw_dir);
    140 #endif
    141 
    142 	if (chdir("/") == -1)
    143 		logerr("%s: chdir: /", __func__);
    144 
    145 	if ((setgroups(1, &pw->pw_gid) == -1 ||
    146 	     setgid(pw->pw_gid) == -1 ||
    147 	     setuid(pw->pw_uid) == -1) &&
    148 	     (errno != EPERM || ctx->options & DHCPCD_FORKED))
    149 	{
    150 		logerr("failed to drop privileges");
    151 		return -1;
    152 	}
    153 
    154 	struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 };
    155 
    156 	/* Prohibit new files, sockets, etc */
    157 	/*
    158 	 * If poll(2) is called with nfds>RLIMIT_NOFILE then it returns EINVAL.
    159 	 * We don't know the final value of nfds at this point *easily*.
    160 	 * Sadly, this is a POSIX limitation and most platforms adhere to it.
    161 	 * However, some are not that strict and are whitelisted below.
    162 	 * Also, if we're not using poll then we can be restrictive.
    163 	 *
    164 	 * For the non whitelisted platforms there should be a sandbox to
    165 	 * fallback to where we don't allow new files, etc:
    166 	 *      Linux:seccomp, FreeBSD:capsicum, OpenBSD:pledge
    167 	 * Solaris users are sadly out of luck on both counts.
    168 	 */
    169 #if defined(__NetBSD__) || defined(__DragonFly__) || \
    170     defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
    171 	/* The control proxy *does* need to create new fd's via accept(2). */
    172 	if (ctx->ps_ctl == NULL || ctx->ps_ctl->psp_pid != getpid()) {
    173 		if (setrlimit(RLIMIT_NOFILE, &rzero) == -1)
    174 			logerr("setrlimit RLIMIT_NOFILE");
    175 	}
    176 #endif
    177 
    178 #define DHC_NOCHKIO	(DHCPCD_STARTED | DHCPCD_DAEMONISE)
    179 	/* Prohibit writing to files.
    180 	 * Obviously this won't work if we are using a logfile
    181 	 * or redirecting stderr to a file. */
    182 	if ((ctx->options & DHC_NOCHKIO) == DHC_NOCHKIO ||
    183 	    (ctx->logfile == NULL && isatty(fd_out) == 1))
    184 	{
    185 		if (setrlimit(RLIMIT_FSIZE, &rzero) == -1)
    186 			logerr("setrlimit RLIMIT_FSIZE");
    187 	}
    188 
    189 #ifdef RLIMIT_NPROC
    190 	/* Prohibit forks */
    191 	if (setrlimit(RLIMIT_NPROC, &rzero) == -1)
    192 		logerr("setrlimit RLIMIT_NPROC");
    193 #endif
    194 
    195 	return 0;
    196 }
    197 
    198 static int
    199 ps_setbuf0(int fd, int ctl, int minlen)
    200 {
    201 	int len;
    202 	socklen_t slen;
    203 
    204 	slen = sizeof(len);
    205 	if (getsockopt(fd, SOL_SOCKET, ctl, &len, &slen) == -1)
    206 		return -1;
    207 
    208 #ifdef __linux__
    209 	len /= 2;
    210 #endif
    211 	if (len >= minlen)
    212 		return 0;
    213 
    214 	return setsockopt(fd, SOL_SOCKET, ctl, &minlen, sizeof(minlen));
    215 }
    216 
    217 static int
    218 ps_setbuf(int fd)
    219 {
    220 	/* Ensure we can receive a fully sized privsep message.
    221 	 * Double the send buffer. */
    222 	int minlen = (int)sizeof(struct ps_msg);
    223 
    224 	if (ps_setbuf0(fd, SO_RCVBUF, minlen) == -1 ||
    225 	    ps_setbuf0(fd, SO_SNDBUF, minlen * 2) == -1)
    226 	{
    227 		logerr(__func__);
    228 		return -1;
    229 	}
    230 	return 0;
    231 }
    232 
    233 int
    234 ps_setbuf_fdpair(int fd[])
    235 {
    236 
    237 	if (ps_setbuf(fd[0]) == -1 || ps_setbuf(fd[1]) == -1)
    238 		return -1;
    239 	return 0;
    240 }
    241 
    242 #ifdef PRIVSEP_RIGHTS
    243 int
    244 ps_rights_limit_ioctl(int fd)
    245 {
    246 	cap_rights_t rights;
    247 
    248 	cap_rights_init(&rights, CAP_IOCTL);
    249 	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
    250 		return -1;
    251 	return 0;
    252 }
    253 
    254 int
    255 ps_rights_limit_fd_fctnl(int fd)
    256 {
    257 	cap_rights_t rights;
    258 
    259 	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT,
    260 	    CAP_ACCEPT, CAP_FCNTL);
    261 	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
    262 		return -1;
    263 	return 0;
    264 }
    265 
    266 int
    267 ps_rights_limit_fd(int fd)
    268 {
    269 	cap_rights_t rights;
    270 
    271 	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_SHUTDOWN);
    272 	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
    273 		return -1;
    274 	return 0;
    275 }
    276 
    277 int
    278 ps_rights_limit_fd_sockopt(int fd)
    279 {
    280 	cap_rights_t rights;
    281 
    282 	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT,
    283 	    CAP_GETSOCKOPT, CAP_SETSOCKOPT);
    284 	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
    285 		return -1;
    286 	return 0;
    287 }
    288 
    289 int
    290 ps_rights_limit_fd_rdonly(int fd)
    291 {
    292 	cap_rights_t rights;
    293 
    294 	cap_rights_init(&rights, CAP_READ, CAP_EVENT);
    295 	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
    296 		return -1;
    297 	return 0;
    298 }
    299 
    300 int
    301 ps_rights_limit_fdpair(int fd[])
    302 {
    303 
    304 	if (ps_rights_limit_fd(fd[0]) == -1 || ps_rights_limit_fd(fd[1]) == -1)
    305 		return -1;
    306 	return 0;
    307 }
    308 
    309 static int
    310 ps_rights_limit_stdio()
    311 {
    312 	const int iebadf = CAPH_IGNORE_EBADF;
    313 	int error = 0;
    314 
    315 	if (caph_limit_stream(STDIN_FILENO, CAPH_READ | iebadf) == -1)
    316 		error = -1;
    317 	if (caph_limit_stream(STDOUT_FILENO, CAPH_WRITE | iebadf) == -1)
    318 		error = -1;
    319 	if (caph_limit_stream(STDERR_FILENO, CAPH_WRITE | iebadf) == -1)
    320 		error = -1;
    321 
    322 	return error;
    323 }
    324 #endif
    325 
    326 #ifdef HAVE_CAPSICUM
    327 static void
    328 ps_processhangup(void *arg, unsigned short events)
    329 {
    330 	struct ps_process *psp = arg;
    331 	struct dhcpcd_ctx *ctx = psp->psp_ctx;
    332 
    333 	if (!(events & ELE_HANGUP))
    334 		logerrx("%s: unexpected event 0x%04x", __func__, events);
    335 
    336 	logdebugx("%s%s%s exited from PID %d",
    337 	    psp->psp_ifname, psp->psp_ifname[0] != '\0' ? ": " : "",
    338 	    psp->psp_name, psp->psp_pid);
    339 
    340 	ps_freeprocess(psp);
    341 
    342 	if (!(ctx->options & DHCPCD_EXITING))
    343 		return;
    344 	if (!(ps_waitforprocs(ctx)))
    345 		eloop_exit(ctx->eloop, EXIT_SUCCESS);
    346 }
    347 #endif
    348 
    349 pid_t
    350 ps_startprocess(struct ps_process *psp,
    351     void (*recv_msg)(void *, unsigned short),
    352     void (*recv_unpriv_msg)(void *, unsigned short),
    353     int (*callback)(struct ps_process *),
    354     unsigned int flags)
    355 {
    356 	struct dhcpcd_ctx *ctx = psp->psp_ctx;
    357 	int fd[2];
    358 	pid_t pid;
    359 
    360 	if (xsocketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, fd) == -1) {
    361 		logerr("%s: socketpair", __func__);
    362 		return -1;
    363 	}
    364 	if (ps_setbuf_fdpair(fd) == -1) {
    365 		logerr("%s: ps_setbuf_fdpair", __func__);
    366 		return -1;
    367 	}
    368 #ifdef PRIVSEP_RIGHTS
    369 	if (ps_rights_limit_fdpair(fd) == -1) {
    370 		logerr("%s: ps_rights_limit_fdpair", __func__);
    371 		return -1;
    372 	}
    373 #endif
    374 
    375 #ifdef HAVE_CAPSICUM
    376 	pid = pdfork(&psp->psp_pfd, PD_CLOEXEC);
    377 #else
    378 	pid = fork();
    379 #endif
    380 	switch (pid) {
    381 	case -1:
    382 #ifdef HAVE_CAPSICUM
    383 		logerr("pdfork");
    384 #else
    385 		logerr("fork");
    386 #endif
    387 		return -1;
    388 	case 0:
    389 		psp->psp_pid = getpid();
    390 		psp->psp_fd = fd[1];
    391 		close(fd[0]);
    392 		break;
    393 	default:
    394 		psp->psp_pid = pid;
    395 		psp->psp_fd = fd[0];
    396 		close(fd[1]);
    397 		if (recv_unpriv_msg == NULL)
    398 			;
    399 		else if (eloop_event_add(ctx->eloop, psp->psp_fd, ELE_READ,
    400 		    recv_unpriv_msg, psp) == -1)
    401 		{
    402 			logerr("%s: eloop_event_add fd %d",
    403 			    __func__, psp->psp_fd);
    404 			return -1;
    405 		}
    406 #ifdef HAVE_CAPSICUM
    407 		if (eloop_event_add(ctx->eloop, psp->psp_pfd, ELE_HANGUP,
    408 		    ps_processhangup, psp) == -1)
    409 		{
    410 			logerr("%s: eloop_event_add pfd %d",
    411 			    __func__, psp->psp_pfd);
    412 			return -1;
    413 		}
    414 #endif
    415 		psp->psp_started = true;
    416 		return pid;
    417 	}
    418 
    419 	/* If we are not the root process, close un-needed stuff. */
    420 	if (ctx->ps_root != psp) {
    421 		ps_root_close(ctx);
    422 #ifdef PLUGIN_DEV
    423 		dev_stop(ctx);
    424 #endif
    425 	}
    426 
    427 	ctx->options |= DHCPCD_FORKED;
    428 	if (ctx->ps_log_fd != -1)
    429 		logsetfd(ctx->ps_log_fd);
    430 
    431 #ifdef DEBUG_FD
    432 	logerrx("pid %d log_fd=%d data_fd=%d psp_fd=%d",
    433 	    getpid(), ctx->ps_log_fd, ctx->ps_data_fd, psp->psp_fd);
    434 #endif
    435 
    436 	if (ctx->fork_fd != -1) {
    437 		close(ctx->fork_fd);
    438 		ctx->fork_fd = -1;
    439 	}
    440 
    441 	if (eloop_forked(ctx->eloop, ELF_KEEP_SIGNALS) == -1) {
    442 		logerr("%s: eloop_forked", __func__);
    443 		goto errexit;
    444 	}
    445 
    446 	pidfile_clean();
    447 	ps_freeprocesses(ctx, psp);
    448 
    449 	if (ctx->ps_root != psp) {
    450 		ctx->options &= ~DHCPCD_PRIVSEPROOT;
    451 		ctx->ps_root = NULL;
    452 		if (ctx->ps_log_root_fd != -1) {
    453 			/* Already removed from eloop thanks to above clear. */
    454 			close(ctx->ps_log_root_fd);
    455 			ctx->ps_log_root_fd = -1;
    456 		}
    457 #ifdef PRIVSEP_RIGHTS
    458 		if (ps_rights_limit_stdio() == -1) {
    459 			logerr("ps_rights_limit_stdio");
    460 			goto errexit;
    461 		}
    462 #endif
    463 	}
    464 
    465 	if (eloop_event_add(ctx->eloop, psp->psp_fd, ELE_READ,
    466 	    recv_msg, psp) == -1)
    467 	{
    468 		logerr("%s: eloop_event_add", __func__);
    469 		goto errexit;
    470 	}
    471 
    472 	if (callback(psp) == -1)
    473 		goto errexit;
    474 
    475 	if (flags & PSF_DROPPRIVS)
    476 		ps_dropprivs(ctx);
    477 
    478 	psp->psp_started = true;
    479 	return 0;
    480 
    481 errexit:
    482 	if (psp->psp_fd != -1) {
    483 		close(psp->psp_fd);
    484 		psp->psp_fd = -1;
    485 	}
    486 	eloop_exit(ctx->eloop, EXIT_FAILURE);
    487 	return -1;
    488 }
    489 
    490 void
    491 ps_process_timeout(void *arg)
    492 {
    493 	struct dhcpcd_ctx *ctx = arg;
    494 
    495 	logerrx("%s: timed out", __func__);
    496 	eloop_exit(ctx->eloop, EXIT_FAILURE);
    497 }
    498 
    499 int
    500 ps_stopprocess(struct ps_process *psp)
    501 {
    502 	int err = 0;
    503 
    504 	if (psp == NULL)
    505 		return 0;
    506 
    507 	psp->psp_started = false;
    508 
    509 #ifdef PRIVSEP_DEBUG
    510 	logdebugx("%s: me=%d pid=%d fd=%d %s", __func__,
    511 	    getpid(), psp->psp_pid, psp->psp_fd, psp->psp_name);
    512 #endif
    513 
    514 	if (psp->psp_fd != -1) {
    515 		eloop_event_delete(psp->psp_ctx->eloop, psp->psp_fd);
    516 #if 0
    517 		if (ps_sendcmd(psp->psp_ctx, psp->psp_fd, PS_STOP, 0,
    518 		    NULL, 0) == -1)
    519 		{
    520 			logerr("%d %d %s %s", getpid(), psp->psp_pid, psp->psp_name, __func__);
    521 			err = -1;
    522 		}
    523 		shutdown(psp->psp_fd, SHUT_WR);
    524 #else
    525 		if (shutdown(psp->psp_fd, SHUT_WR) == -1) {
    526 			logerr(__func__);
    527 			err = -1;
    528 		}
    529 #endif
    530 	}
    531 
    532 	/* Don't wait for the process as it may not respond to the shutdown
    533 	 * request. We'll reap the process on receipt of SIGCHLD where we
    534 	 * also close the fd. */
    535 	return err;
    536 }
    537 
    538 int
    539 ps_start(struct dhcpcd_ctx *ctx)
    540 {
    541 	pid_t pid;
    542 
    543 	TAILQ_INIT(&ctx->ps_processes);
    544 
    545 	switch (pid = ps_root_start(ctx)) {
    546 	case -1:
    547 		logerr("ps_root_start");
    548 		return -1;
    549 	case 0:
    550 		return 0;
    551 	default:
    552 		logdebugx("spawned privileged proxy on PID %d", pid);
    553 	}
    554 
    555 	/* No point in spawning the generic network listener if we're
    556 	 * not going to use it. */
    557 	if (!ps_inet_canstart(ctx))
    558 		goto started_net;
    559 
    560 	switch (pid = ps_inet_start(ctx)) {
    561 	case -1:
    562 		return -1;
    563 	case 0:
    564 		return 0;
    565 	default:
    566 		logdebugx("spawned network proxy on PID %d", pid);
    567 	}
    568 
    569 started_net:
    570 	if (!(ctx->options & DHCPCD_TEST)) {
    571 		switch (pid = ps_ctl_start(ctx)) {
    572 		case -1:
    573 			return -1;
    574 		case 0:
    575 			return 0;
    576 		default:
    577 			logdebugx("spawned controller proxy on PID %d", pid);
    578 		}
    579 	}
    580 
    581 #ifdef ARC4RANDOM_H
    582 	/* Seed the random number generator early incase it needs /dev/urandom
    583 	 * which won't be available in the chroot. */
    584 	arc4random();
    585 #endif
    586 
    587 	return 1;
    588 }
    589 
    590 int
    591 ps_entersandbox(const char *_pledge, const char **sandbox)
    592 {
    593 
    594 #if !defined(HAVE_PLEDGE)
    595 	UNUSED(_pledge);
    596 #endif
    597 
    598 #if defined(HAVE_CAPSICUM)
    599 	if (sandbox != NULL)
    600 		*sandbox = "capsicum";
    601 	return cap_enter();
    602 #elif defined(HAVE_PLEDGE)
    603 	if (sandbox != NULL)
    604 		*sandbox = "pledge";
    605 	// There is no need to use unveil(2) because we are in an empty chroot
    606 	// This is encouraged by Theo de Raadt himself:
    607 	// https://www.mail-archive.com/misc@openbsd.org/msg171655.html
    608 	return pledge(_pledge, NULL);
    609 #elif defined(HAVE_SECCOMP)
    610 	if (sandbox != NULL)
    611 		*sandbox = "seccomp";
    612 	return ps_seccomp_enter();
    613 #else
    614 	if (sandbox != NULL)
    615 		*sandbox = "posix resource limited";
    616 	return 0;
    617 #endif
    618 }
    619 
    620 int
    621 ps_managersandbox(struct dhcpcd_ctx *ctx, const char *_pledge)
    622 {
    623 	const char *sandbox = NULL;
    624 	bool forked;
    625 	int dropped;
    626 
    627 	forked = ctx->options & DHCPCD_FORKED;
    628 	ctx->options &= ~DHCPCD_FORKED;
    629 	dropped = ps_dropprivs(ctx);
    630 	if (forked)
    631 		ctx->options |= DHCPCD_FORKED;
    632 
    633 	/*
    634 	 * If we don't have a root process, we cannot use syslog.
    635 	 * If it cannot be opened before chrooting then syslog(3) will fail.
    636 	 * openlog(3) does not return an error which doubly sucks.
    637 	 */
    638 	if (ctx->ps_root == NULL) {
    639 		unsigned int logopts = loggetopts();
    640 
    641 		logopts &= ~LOGERR_LOG;
    642 		logsetopts(logopts);
    643 	}
    644 
    645 	if (dropped == -1) {
    646 		logerr("%s: ps_dropprivs", __func__);
    647 		return -1;
    648 	}
    649 
    650 #ifdef PRIVSEP_RIGHTS
    651 	if ((ctx->pf_inet_fd != -1 &&
    652 	    ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1) ||
    653 	     ps_rights_limit_stdio() == -1)
    654 	{
    655 		logerr("%s: cap_rights_limit", __func__);
    656 		return -1;
    657 	}
    658 #endif
    659 
    660 	if (_pledge == NULL)
    661 		_pledge = "stdio";
    662 	if (ps_entersandbox(_pledge, &sandbox) == -1) {
    663 		if (errno == ENOSYS) {
    664 			if (sandbox != NULL)
    665 				logwarnx("sandbox unavailable: %s", sandbox);
    666 			return 0;
    667 		}
    668 		logerr("%s: %s", __func__, sandbox);
    669 		return -1;
    670 	} else if (ctx->options & DHCPCD_LAUNCHER ||
    671 		  ((!(ctx->options & DHCPCD_DAEMONISE)) &&
    672 		   ctx->options & DHCPCD_MANAGER))
    673 		logdebugx("sandbox: %s", sandbox);
    674 	return 0;
    675 }
    676 
    677 int
    678 ps_stop(struct dhcpcd_ctx *ctx)
    679 {
    680 	int r, ret = 0;
    681 
    682 	if (!(ctx->options & DHCPCD_PRIVSEP) ||
    683 	    ctx->options & DHCPCD_FORKED ||
    684 	    ctx->eloop == NULL)
    685 		return 0;
    686 
    687 	if (ctx->ps_ctl != NULL) {
    688 		r = ps_ctl_stop(ctx);
    689 		if (r != 0)
    690 			ret = r;
    691 	}
    692 
    693 	if (ctx->ps_inet != NULL) {
    694 		r = ps_inet_stop(ctx);
    695 		if (r != 0)
    696 			ret = r;
    697 	}
    698 
    699 	if (ctx->ps_root != NULL) {
    700 		if (ps_root_stopprocesses(ctx) == -1)
    701 			ret = -1;
    702 	}
    703 
    704 	return ret;
    705 }
    706 
    707 bool
    708 ps_waitforprocs(struct dhcpcd_ctx *ctx)
    709 {
    710 	struct ps_process *psp = TAILQ_FIRST(&ctx->ps_processes);
    711 
    712 	if (psp == NULL)
    713 		return false;
    714 
    715 	/* Different processes */
    716 	if (psp != TAILQ_LAST(&ctx->ps_processes, ps_process_head))
    717 		return true;
    718 
    719 	return !psp->psp_started;
    720 }
    721 
    722 int
    723 ps_stopwait(struct dhcpcd_ctx *ctx)
    724 {
    725 	int error = EXIT_SUCCESS;
    726 
    727 	if (!ps_waitforprocs(ctx))
    728 		return 0;
    729 
    730 	ctx->options |= DHCPCD_EXITING;
    731 	if (eloop_timeout_add_sec(ctx->eloop, PS_PROCESS_TIMEOUT,
    732 	    ps_process_timeout, ctx) == -1)
    733 		logerr("%s: eloop_timeout_add_sec", __func__);
    734 
    735 #ifdef HAVE_CAPSICUM
    736 	struct ps_process *psp;
    737 
    738 	TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
    739 		if (psp->psp_pfd == -1)
    740 			continue;
    741 		if (eloop_event_add(ctx->eloop, psp->psp_pfd,
    742 		    ELE_HANGUP, ps_processhangup, psp) == -1)
    743 			logerr("%s: eloop_event_add pfd %d",
    744 			    __func__, psp->psp_pfd);
    745 	}
    746 #endif
    747 
    748 	error = eloop_start(ctx->eloop);
    749 	if (error < 0)
    750 		logerr("%s: eloop_start", __func__);
    751 
    752 	eloop_timeout_delete(ctx->eloop, ps_process_timeout, ctx);
    753 
    754 	return error;
    755 }
    756 
    757 void
    758 ps_freeprocess(struct ps_process *psp)
    759 {
    760 	struct dhcpcd_ctx *ctx = psp->psp_ctx;
    761 
    762 	TAILQ_REMOVE(&ctx->ps_processes, psp, next);
    763 
    764 	if (psp->psp_fd != -1) {
    765 		eloop_event_delete(ctx->eloop, psp->psp_fd);
    766 		close(psp->psp_fd);
    767 	}
    768 	if (psp->psp_work_fd != -1) {
    769 		eloop_event_delete(ctx->eloop, psp->psp_work_fd);
    770 		close(psp->psp_work_fd);
    771 	}
    772 #ifdef HAVE_CAPSICUM
    773 	if (psp->psp_pfd != -1) {
    774 		eloop_event_delete(ctx->eloop, psp->psp_pfd);
    775 		close(psp->psp_pfd);
    776 	}
    777 #endif
    778 	if (ctx->ps_root == psp)
    779 		ctx->ps_root = NULL;
    780 	if (ctx->ps_inet == psp)
    781 		ctx->ps_inet = NULL;
    782 	if (ctx->ps_ctl == psp)
    783 		ctx->ps_ctl = NULL;
    784 #ifdef INET
    785 	if (psp->psp_bpf != NULL)
    786 		bpf_close(psp->psp_bpf);
    787 #endif
    788 	free(psp);
    789 }
    790 
    791 static void
    792 ps_free(struct dhcpcd_ctx *ctx)
    793 {
    794 	struct ps_process *ppsp, *psp;
    795 	bool stop;
    796 
    797 	if (ctx->ps_root != NULL)
    798 		ppsp = ctx->ps_root;
    799 	else if (ctx->ps_ctl != NULL)
    800 		ppsp = ctx->ps_ctl;
    801 	else
    802 		ppsp = NULL;
    803 	if (ppsp != NULL)
    804 		stop = ppsp->psp_pid == getpid();
    805 	else
    806 		stop = false;
    807 
    808 	while ((psp = TAILQ_FIRST(&ctx->ps_processes)) != NULL) {
    809 		if (stop && psp != ppsp)
    810 			ps_stopprocess(psp);
    811 		ps_freeprocess(psp);
    812 	}
    813 }
    814 
    815 int
    816 ps_unrollmsg(struct msghdr *msg, struct ps_msghdr *psm,
    817     const void *data, size_t len)
    818 {
    819 	uint8_t *datap, *namep, *controlp;
    820 	socklen_t cmsg_padlen =
    821 	    CALC_CMSG_PADLEN(psm->ps_controllen, psm->ps_namelen);
    822 
    823 	namep = UNCONST(data);
    824 	controlp = namep + psm->ps_namelen + cmsg_padlen;
    825 	datap = controlp + psm->ps_controllen;
    826 
    827 	if (psm->ps_namelen != 0) {
    828 		if (psm->ps_namelen > len) {
    829 			errno = EINVAL;
    830 			return -1;
    831 		}
    832 		msg->msg_name = namep;
    833 		len -= psm->ps_namelen;
    834 	} else
    835 		msg->msg_name = NULL;
    836 	msg->msg_namelen = psm->ps_namelen;
    837 
    838 	if (psm->ps_controllen != 0) {
    839 		if (psm->ps_controllen > len) {
    840 			errno = EINVAL;
    841 			return -1;
    842 		}
    843 		msg->msg_control = controlp;
    844 		len -= psm->ps_controllen + cmsg_padlen;
    845 	} else
    846 		msg->msg_control = NULL;
    847 	msg->msg_controllen = psm->ps_controllen;
    848 
    849 	if (len != 0) {
    850 		msg->msg_iovlen = 1;
    851 		msg->msg_iov[0].iov_base = datap;
    852 		msg->msg_iov[0].iov_len = len;
    853 	} else {
    854 		msg->msg_iovlen = 0;
    855 		msg->msg_iov[0].iov_base = NULL;
    856 		msg->msg_iov[0].iov_len = 0;
    857 	}
    858 	return 0;
    859 }
    860 
    861 ssize_t
    862 ps_sendpsmmsg(struct dhcpcd_ctx *ctx, int fd,
    863     struct ps_msghdr *psm, const struct msghdr *msg)
    864 {
    865 	long padding[1] = { 0 };
    866 	struct iovec iov[] = {
    867 		{ .iov_base = UNCONST(psm), .iov_len = sizeof(*psm) },
    868 		{ .iov_base = NULL, },	/* name */
    869 		{ .iov_base = NULL, },	/* control padding */
    870 		{ .iov_base = NULL, },	/* control */
    871 		{ .iov_base = NULL, },	/* payload 1 */
    872 		{ .iov_base = NULL, },	/* payload 2 */
    873 		{ .iov_base = NULL, },	/* payload 3 */
    874 	};
    875 	struct msghdr m = { .msg_iov = iov, .msg_iovlen = 1 };
    876 	ssize_t len;
    877 
    878 	if (msg != NULL) {
    879 		struct iovec *iovp = &iov[1];
    880 		int i;
    881 		socklen_t cmsg_padlen;
    882 
    883 		psm->ps_namelen = msg->msg_namelen;
    884 		psm->ps_controllen = (socklen_t)msg->msg_controllen;
    885 
    886 		iovp->iov_base = msg->msg_name;
    887 		iovp->iov_len = msg->msg_namelen;
    888 		iovp++;
    889 		m.msg_iovlen++;
    890 
    891 		cmsg_padlen =
    892 		    CALC_CMSG_PADLEN(msg->msg_controllen, msg->msg_namelen);
    893 		assert(cmsg_padlen <= sizeof(padding));
    894 		iovp->iov_len = cmsg_padlen;
    895 		iovp->iov_base = cmsg_padlen != 0 ? padding : NULL;
    896 		iovp++;
    897 		m.msg_iovlen++;
    898 
    899 		iovp->iov_base = msg->msg_control;
    900 		iovp->iov_len = msg->msg_controllen;
    901 		iovp++;
    902 		m.msg_iovlen++;
    903 
    904 		for (i = 0; i < (int)msg->msg_iovlen; i++) {
    905 			if ((size_t)(m.msg_iovlen++) > __arraycount(iov)) {
    906 				errno =	ENOBUFS;
    907 				return -1;
    908 			}
    909 			iovp->iov_base = msg->msg_iov[i].iov_base;
    910 			iovp->iov_len = msg->msg_iov[i].iov_len;
    911 			iovp++;
    912 		}
    913 	}
    914 
    915 	len = sendmsg(fd, &m, MSG_EOR);
    916 
    917 	if (len == -1 && ctx != NULL) {
    918 		if (ctx->options & DHCPCD_FORKED &&
    919 		    !(ctx->options & DHCPCD_PRIVSEPROOT))
    920 			eloop_exit(ctx->eloop, EXIT_FAILURE);
    921 	}
    922 	return len;
    923 }
    924 
    925 ssize_t
    926 ps_sendpsmdata(struct dhcpcd_ctx *ctx, int fd,
    927     struct ps_msghdr *psm, const void *data, size_t len)
    928 {
    929 	struct iovec iov[] = {
    930 		{ .iov_base = UNCONST(data), .iov_len = len },
    931 	};
    932 	struct msghdr msg = {
    933 		.msg_iov = iov, .msg_iovlen = 1,
    934 	};
    935 
    936 	return ps_sendpsmmsg(ctx, fd, psm, &msg);
    937 }
    938 
    939 
    940 ssize_t
    941 ps_sendmsg(struct dhcpcd_ctx *ctx, int fd, uint16_t cmd, unsigned long flags,
    942     const struct msghdr *msg)
    943 {
    944 	struct ps_msghdr psm = {
    945 		.ps_cmd = cmd,
    946 		.ps_flags = flags,
    947 		.ps_namelen = msg->msg_namelen,
    948 		.ps_controllen = (socklen_t)msg->msg_controllen,
    949 	};
    950 	size_t i;
    951 
    952 	for (i = 0; i < (size_t)msg->msg_iovlen; i++)
    953 		psm.ps_datalen += msg->msg_iov[i].iov_len;
    954 
    955 #if 0	/* For debugging structure padding. */
    956 	logerrx("psa.family %lu %zu", offsetof(struct ps_addr, psa_family), sizeof(psm.ps_id.psi_addr.psa_family));
    957 	logerrx("psa.pad %lu %zu", offsetof(struct ps_addr, psa_pad), sizeof(psm.ps_id.psi_addr.psa_pad));
    958 	logerrx("psa.psa_u %lu %zu", offsetof(struct ps_addr, psa_u), sizeof(psm.ps_id.psi_addr.psa_u));
    959 	logerrx("psa %zu", sizeof(psm.ps_id.psi_addr));
    960 
    961 	logerrx("psi.addr %lu %zu", offsetof(struct ps_id, psi_addr), sizeof(psm.ps_id.psi_addr));
    962 	logerrx("psi.index %lu %zu", offsetof(struct ps_id, psi_ifindex), sizeof(psm.ps_id.psi_ifindex));
    963 	logerrx("psi.cmd %lu %zu", offsetof(struct ps_id, psi_cmd), sizeof(psm.ps_id.psi_cmd));
    964 	logerrx("psi.pad %lu %zu", offsetof(struct ps_id, psi_pad), sizeof(psm.ps_id.psi_pad));
    965 	logerrx("psi %zu", sizeof(struct ps_id));
    966 
    967 	logerrx("ps_cmd %lu", offsetof(struct ps_msghdr, ps_cmd));
    968 	logerrx("ps_pad %lu %zu", offsetof(struct ps_msghdr, ps_pad), sizeof(psm.ps_pad));
    969 	logerrx("ps_flags %lu %zu", offsetof(struct ps_msghdr, ps_flags), sizeof(psm.ps_flags));
    970 
    971 	logerrx("ps_id %lu %zu", offsetof(struct ps_msghdr, ps_id), sizeof(psm.ps_id));
    972 
    973 	logerrx("ps_namelen %lu %zu", offsetof(struct ps_msghdr, ps_namelen), sizeof(psm.ps_namelen));
    974 	logerrx("ps_controllen %lu %zu", offsetof(struct ps_msghdr, ps_controllen), sizeof(psm.ps_controllen));
    975 	logerrx("ps_pad2 %lu %zu", offsetof(struct ps_msghdr, ps_pad2), sizeof(psm.ps_pad2));
    976 	logerrx("ps_datalen %lu %zu", offsetof(struct ps_msghdr, ps_datalen), sizeof(psm.ps_datalen));
    977 	logerrx("psm %zu", sizeof(psm));
    978 #endif
    979 
    980 	return ps_sendpsmmsg(ctx, fd, &psm, msg);
    981 }
    982 
    983 ssize_t
    984 ps_sendcmd(struct dhcpcd_ctx *ctx, int fd, uint16_t cmd, unsigned long flags,
    985     const void *data, size_t len)
    986 {
    987 	struct ps_msghdr psm = {
    988 		.ps_cmd = cmd,
    989 		.ps_flags = flags,
    990 	};
    991 	struct iovec iov[] = {
    992 		{ .iov_base = UNCONST(data), .iov_len = len }
    993 	};
    994 	struct msghdr msg = {
    995 		.msg_iov = iov, .msg_iovlen = 1,
    996 	};
    997 
    998 	return ps_sendpsmmsg(ctx, fd, &psm, &msg);
    999 }
   1000 
   1001 ssize_t
   1002 ps_sendcmdmsg(struct dhcpcd_ctx *ctx, int fd, uint16_t cmd,
   1003     unsigned long flags, const struct msghdr *msg)
   1004 {
   1005 	struct ps_msghdr psm = { .ps_cmd = cmd, .ps_flags = flags };
   1006 
   1007 	return ps_sendpsmmsg(ctx, fd, &psm, msg);
   1008 }
   1009 
   1010 ssize_t
   1011 ps_recvmsg(int rfd, unsigned short events, uint16_t cmd, int wfd)
   1012 {
   1013 	struct sockaddr_storage ss = { .ss_family = AF_UNSPEC };
   1014 	uint8_t controlbuf[sizeof(struct sockaddr_storage)] = { 0 };
   1015 	uint8_t databuf[64 * 1024];
   1016 	struct iovec iov[] = {
   1017 	    { .iov_base = databuf, .iov_len = sizeof(databuf) }
   1018 	};
   1019 	struct msghdr msg = {
   1020 		.msg_name = &ss, .msg_namelen = sizeof(ss),
   1021 		.msg_control = controlbuf, .msg_controllen = sizeof(controlbuf),
   1022 		.msg_iov = iov, .msg_iovlen = 1,
   1023 	};
   1024 	ssize_t len;
   1025 
   1026 	if (!(events & ELE_READ))
   1027 		logerrx("%s: unexpected event 0x%04x", __func__, events);
   1028 
   1029 	len = recvmsg(rfd, &msg, MSG_WAITALL);
   1030 	if (len == -1) {
   1031 		logerr("%s: recvmsg", __func__);
   1032 		return len;
   1033 	}
   1034 
   1035 	iov[0].iov_len = (size_t)len;
   1036 	len = ps_sendcmdmsg(NULL, wfd, cmd, 0, &msg);
   1037 	if (len == -1)
   1038 		logerr("%s: ps_sendcmdmsg", __func__);
   1039 	return len;
   1040 }
   1041 
   1042 ssize_t
   1043 ps_daemonised(struct dhcpcd_ctx *ctx)
   1044 {
   1045 	struct ps_process *psp;
   1046 	ssize_t err = 0;
   1047 
   1048 	dhcpcd_daemonised(ctx);
   1049 
   1050 	/* Echo the message to all processes */
   1051 	TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
   1052 		if (psp->psp_pid == getpid())
   1053 			continue;
   1054 		if (ps_sendcmd(psp->psp_ctx, psp->psp_fd, PS_DAEMONISED,
   1055 		    0, NULL, 0) == -1)
   1056 			err = -1;
   1057 	}
   1058 
   1059 	return err;
   1060 }
   1061 
   1062 ssize_t
   1063 ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd, unsigned short events,
   1064     ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *),
   1065     void *cbctx)
   1066 {
   1067 	struct ps_msg psm;
   1068 	ssize_t len;
   1069 	size_t dlen;
   1070 	struct iovec iov[1];
   1071 	struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1 };
   1072 	bool stop = false;
   1073 
   1074 	if (events & ELE_HANGUP) {
   1075 		len = 0;
   1076 		goto stop;
   1077 	}
   1078 	if (!(events & ELE_READ))
   1079 		logerrx("%s: unexpected event 0x%04x", __func__, events);
   1080 
   1081 	len = read(fd, &psm, sizeof(psm));
   1082 #ifdef PRIVSEP_DEBUG
   1083 	logdebugx("%s: fd=%d %zd", __func__, fd, len);
   1084 #endif
   1085 
   1086 	if (len == -1 || len == 0)
   1087 		stop = true;
   1088 	else {
   1089 		dlen = (size_t)len;
   1090 		if (dlen < sizeof(psm.psm_hdr)) {
   1091 			errno = EINVAL;
   1092 			return -1;
   1093 		}
   1094 
   1095 		if (psm.psm_hdr.ps_cmd == PS_STOP) {
   1096 			stop = true;
   1097 			len = 0;
   1098 		} else if (psm.psm_hdr.ps_cmd == PS_DAEMONISED) {
   1099 			ps_daemonised(ctx);
   1100 			return 0;
   1101 		}
   1102 	}
   1103 
   1104 	if (stop) {
   1105 stop:
   1106 		ctx->options |= DHCPCD_EXITING;
   1107 #ifdef PRIVSEP_DEBUG
   1108 		logdebugx("process %d stopping", getpid());
   1109 #endif
   1110 		ps_free(ctx);
   1111 		eloop_exit(ctx->eloop, len != -1 ? EXIT_SUCCESS : EXIT_FAILURE);
   1112 		return len;
   1113 	}
   1114 	dlen -= sizeof(psm.psm_hdr);
   1115 
   1116 	if (ps_unrollmsg(&msg, &psm.psm_hdr, psm.psm_data, dlen) == -1)
   1117 		return -1;
   1118 
   1119 	if (callback == NULL)
   1120 		return 0;
   1121 
   1122 	errno = 0;
   1123 	return callback(cbctx, &psm.psm_hdr, &msg);
   1124 }
   1125 
   1126 struct ps_process *
   1127 ps_findprocess(struct dhcpcd_ctx *ctx, struct ps_id *psid)
   1128 {
   1129 	struct ps_process *psp;
   1130 
   1131 	TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
   1132 		if (!(psp->psp_started))
   1133 			continue;
   1134 		if (memcmp(&psp->psp_id, psid, sizeof(psp->psp_id)) == 0)
   1135 			return psp;
   1136 	}
   1137 	errno = ESRCH;
   1138 	return NULL;
   1139 }
   1140 
   1141 struct ps_process *
   1142 ps_findprocesspid(struct dhcpcd_ctx *ctx, pid_t pid)
   1143 {
   1144 	struct ps_process *psp;
   1145 
   1146 	TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
   1147 		if (psp->psp_pid == pid)
   1148 			return psp;
   1149 	}
   1150 	errno = ESRCH;
   1151 	return NULL;
   1152 }
   1153 
   1154 struct ps_process *
   1155 ps_newprocess(struct dhcpcd_ctx *ctx, struct ps_id *psid)
   1156 {
   1157 	struct ps_process *psp;
   1158 
   1159 	psp = calloc(1, sizeof(*psp));
   1160 	if (psp == NULL)
   1161 		return NULL;
   1162 	psp->psp_ctx = ctx;
   1163 	memcpy(&psp->psp_id, psid, sizeof(psp->psp_id));
   1164 	psp->psp_fd = -1;
   1165 	psp->psp_work_fd = -1;
   1166 #ifdef HAVE_CAPSICUM
   1167 	psp->psp_pfd = -1;
   1168 #endif
   1169 
   1170 	if (!(ctx->options & DHCPCD_MANAGER))
   1171 		strlcpy(psp->psp_ifname, ctx->ifv[0], sizeof(psp->psp_ifname));
   1172 	TAILQ_INSERT_TAIL(&ctx->ps_processes, psp, next);
   1173 	return psp;
   1174 }
   1175 
   1176 void
   1177 ps_freeprocesses(struct dhcpcd_ctx *ctx, struct ps_process *notthis)
   1178 {
   1179 	struct ps_process *psp, *psn;
   1180 
   1181 	TAILQ_FOREACH_SAFE(psp, &ctx->ps_processes, next, psn) {
   1182 		if (psp == notthis)
   1183 			continue;
   1184 		ps_freeprocess(psp);
   1185 	}
   1186 }
   1187