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