Module Name:    src
Committed By:   roy
Date:           Mon Jun 15 16:59:05 UTC 2020

Modified Files:
        src/external/bsd/dhcpcd/dist/src: bpf.c dhcp6.c dhcpcd.c if-bsd.c
            if-options.c ipv6nd.c logerr.c privsep.c script.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/src/dhcp6.c \
    src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.38 -r1.39 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.21 -r1.22 src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.24 -r1.25 src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/src/logerr.c \
    src/external/bsd/dhcpcd/dist/src/privsep.c
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/src/script.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.15 src/external/bsd/dhcpcd/dist/src/bpf.c:1.16
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.15	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Mon Jun 15 16:59:05 2020
@@ -703,6 +703,14 @@ bpf_bootp(const struct bpf *bpf, __unuse
 		return -1;
 	return 0;
 #else
+#ifdef PRIVSEP
+#if defined(__sun) /* Solaris cannot send via BPF. */
+#elif defined(BIOCSETF)
+#warning No BIOCSETWF support - a compromised BPF can be used as a raw socket
+#else
+#warning A compromised PF_PACKET socket can be used as a raw socket
+#endif
+#endif
 	return bpf_bootp_rw(bpf, true);
 #endif
 }

Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.20 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.21
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.20	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Mon Jun 15 16:59:05 2020
@@ -541,12 +541,12 @@ dhcp6_delegateaddr(struct in6_addr *addr
 		state->reason = "DELEGATED6";
 	}
 
-	if (sla == NULL || sla->sla_set == 0) {
+	if (sla == NULL || !sla->sla_set) {
 		/* No SLA set, so make an assumption of
 		 * desired SLA and prefix length. */
 		asla.sla = ifp->index;
 		asla.prefix_len = 0;
-		asla.sla_set = 0;
+		asla.sla_set = false;
 		sla = &asla;
 	} else if (sla->prefix_len == 0) {
 		/* An SLA was given, but prefix length was not.
@@ -554,7 +554,7 @@ dhcp6_delegateaddr(struct in6_addr *addr
 		 * potentially more than one interface. */
 		asla.sla = sla->sla;
 		asla.prefix_len = 0;
-		asla.sla_set = 0;
+		asla.sla_set = sla->sla_set;
 		sla = &asla;
 	}
 
@@ -562,16 +562,15 @@ dhcp6_delegateaddr(struct in6_addr *addr
 		uint32_t sla_max;
 		int bits;
 
-		if (ia->sla_max == 0) {
+		sla_max = ia->sla_max;
+		if (sla_max == 0 && (sla == NULL || !sla->sla_set)) {
 			const struct interface *ifi;
 
-			sla_max = 0;
 			TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
 				if (ifi->index > sla_max)
 					sla_max = ifi->index;
 			}
-		} else
-			sla_max = ia->sla_max;
+		}
 
 		bits = fls32(sla_max);
 
@@ -1727,6 +1726,7 @@ dhcp6_fail(struct interface *ifp)
 		if (state->old != NULL)
 			script_runreason(ifp, "EXPIRE6");
 		dhcp_unlink(ifp->ctx, state->leasefile);
+		dhcp6_addrequestedaddrs(ifp);
 	}
 
 	if (!dhcp6_startdiscoinform(ifp)) {
@@ -2672,6 +2672,7 @@ ex:
 	free(state->new);
 	state->new = NULL;
 	state->new_len = 0;
+	dhcp6_addrequestedaddrs(ifp);
 	return bytes == 0 ? 0 : -1;
 }
 
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.20 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.21
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.20	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c	Mon Jun 15 16:59:05 2020
@@ -1100,7 +1100,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 	bool new_ia;
 #endif
 
-	if (ifp == NULL) {
+	if (ifp == NULL || RS_STATE(ifp) == NULL) {
 #ifdef DEBUG_RS
 		logdebugx("RA for unexpected interface from %s", sfrom);
 #endif
@@ -1155,10 +1155,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 		if (ifp == rap->iface)
 			break;
 	}
-	if (rap != NULL && rap->willexpire) {
-		logerrx("settng def RA");
+	if (rap != NULL && rap->willexpire)
 		ipv6nd_applyra(ifp);
-	}
 #endif
 
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.38 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.39
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.38	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Mon Jun 15 16:59:05 2020
@@ -943,9 +943,12 @@ dhcpcd_startinterface(void *arg)
 		}
 
 #ifdef DHCP6
-		if (ifo->options & DHCPCD_DHCP6) {
+		/* DHCPv6 could be turned off, but the interface
+		 * is still delegated to. */
+		if (ifp->active)
 			dhcp6_find_delegates(ifp);
 
+		if (ifo->options & DHCPCD_DHCP6) {
 			if (ifp->active == IF_ACTIVE_USER) {
 				enum DH6S d6_state;
 
@@ -1400,6 +1403,11 @@ dhcpcd_signal_cb(int sig, void *arg)
 	unsigned long long opts;
 	int exit_code;
 
+	if (ctx->options & DHCPCD_DUMPLEASE) {
+		eloop_exit(ctx->eloop, EXIT_FAILURE);
+		return;
+	}
+
 	if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
 		pid_t pid = pidfile_read(ctx->pidfile);
 		if (pid == -1) {
@@ -1462,48 +1470,6 @@ dhcpcd_signal_cb(int sig, void *arg)
 }
 #endif
 
-static void
-dhcpcd_getinterfaces(void *arg)
-{
-	struct fd_list *fd = arg;
-	struct interface *ifp;
-	size_t len;
-
-	len = 0;
-	TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
-		if (!ifp->active)
-			continue;
-		len++;
-#ifdef INET
-		if (D_STATE_RUNNING(ifp))
-			len++;
-#endif
-#ifdef IPV4LL
-		if (IPV4LL_STATE_RUNNING(ifp))
-			len++;
-#endif
-#ifdef INET6
-		if (IPV6_STATE_RUNNING(ifp))
-			len++;
-		if (RS_STATE_RUNNING(ifp))
-			len++;
-#endif
-#ifdef DHCP6
-		if (D6_STATE_RUNNING(ifp))
-			len++;
-#endif
-	}
-	if (write(fd->fd, &len, sizeof(len)) != sizeof(len))
-		return;
-	eloop_event_remove_writecb(fd->ctx->eloop, fd->fd);
-	TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
-		if (!ifp->active)
-			continue;
-		if (send_interface(fd, ifp, AF_UNSPEC) == -1)
-			logerr(__func__);
-	}
-}
-
 int
 dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
     int argc, char **argv)
@@ -1511,23 +1477,23 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 	struct interface *ifp;
 	unsigned long long opts;
 	int opt, oi, do_reboot, do_renew, af = AF_UNSPEC;
-	size_t len, l;
+	size_t len, l, nifaces;
 	char *tmp, *p;
 
 	/* Special commands for our control socket
 	 * as the other end should be blocking until it gets the
 	 * expected reply we should be safely able just to change the
 	 * write callback on the fd */
+	/* Make any change here in privsep-control.c as well. */
 	if (strcmp(*argv, "--version") == 0) {
 		return control_queue(fd, UNCONST(VERSION),
-		    strlen(VERSION) + 1, false);
+		    strlen(VERSION) + 1);
 	} else if (strcmp(*argv, "--getconfigfile") == 0) {
 		return control_queue(fd, UNCONST(fd->ctx->cffile),
-		    strlen(fd->ctx->cffile) + 1, false);
+		    strlen(fd->ctx->cffile) + 1);
 	} else if (strcmp(*argv, "--getinterfaces") == 0) {
-		eloop_event_add_w(fd->ctx->eloop, fd->fd,
-		    dhcpcd_getinterfaces, fd);
-		return 0;
+		optind = argc = 0;
+		goto dumplease;
 	} else if (strcmp(*argv, "--listen") == 0) {
 		fd->flags |= FD_LISTEN;
 		return 0;
@@ -1591,8 +1557,8 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 
 	if (opts & DHCPCD_DUMPLEASE) {
 		ctx->options |= DHCPCD_DUMPLEASE;
-		size_t nifaces = 0;
-
+dumplease:
+		nifaces = 0;
 		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 			if (!ifp->active)
 				continue;
@@ -1672,68 +1638,119 @@ dumperr:
 	return 0;
 }
 
-static int
-dhcpcd_readdump(struct dhcpcd_ctx *ctx)
+static void dhcpcd_readdump1(void *);
+
+static void
+dhcpcd_readdump2(void *arg)
 {
-	int error = 0;
-	size_t nifaces, buflen = 0, dlen;
+	struct dhcpcd_ctx *ctx = arg;
 	ssize_t len;
-	char *buf = NULL;
+	int exit_code = EXIT_FAILURE;
 
-again1:
-	len = read(ctx->control_fd, &nifaces, sizeof(nifaces));
+	len = read(ctx->control_fd, ctx->ctl_buf + ctx->ctl_bufpos,
+	    ctx->ctl_buflen - ctx->ctl_bufpos);
 	if (len == -1) {
-		if (errno == EAGAIN)
-			goto again1;
-		return -1;
+		logerr(__func__);
+		goto finished;
+	} else if (len == 0)
+		goto finished;
+	if ((size_t)len + ctx->ctl_bufpos != ctx->ctl_buflen) {
+		ctx->ctl_bufpos += (size_t)len;
+		return;
 	}
-	if (len != sizeof(nifaces)) {
-		errno = EINVAL;
-		return -1;
+
+	if (ctx->ctl_buf[ctx->ctl_buflen - 1] != '\0') /* unlikely */
+		ctx->ctl_buf[ctx->ctl_buflen - 1] = '\0';
+	script_dump(ctx->ctl_buf, ctx->ctl_buflen);
+	fflush(stdout);
+	if (--ctx->ctl_extra != 0) {
+		putchar('\n');
+		eloop_event_add(ctx->eloop, ctx->control_fd,
+		    dhcpcd_readdump1, ctx);
+		return;
 	}
-	for (; nifaces > 0; nifaces--) {
-again2:
-		len = read(ctx->control_fd, &dlen, sizeof(dlen));
-		if (len == -1) {
-			if (errno == EAGAIN)
-				goto again2;
-			error = -1;
-			goto out;
-		}
-		if (len != sizeof(dlen)) {
+	exit_code = EXIT_SUCCESS;
+
+finished:
+	shutdown(ctx->control_fd, SHUT_RDWR);
+	eloop_exit(ctx->eloop, exit_code);
+}
+
+static void
+dhcpcd_readdump1(void *arg)
+{
+	struct dhcpcd_ctx *ctx = arg;
+	ssize_t len;
+
+	len = read(ctx->control_fd, &ctx->ctl_buflen, sizeof(ctx->ctl_buflen));
+	if (len != sizeof(ctx->ctl_buflen)) {
+		if (len != -1)
 			errno = EINVAL;
-			goto out;
-		}
-		if (dlen > buflen) {
-			char *nbuf = realloc(buf, dlen);
-			if (nbuf == NULL) {
-				error = -1;
-				goto out;
-			}
-			buf = nbuf;
-			buflen = dlen;
-		}
-		if (dlen == 0) {
+		goto err;
+	}
+	if (ctx->ctl_buflen > SSIZE_MAX) {
+		errno = ENOBUFS;
+		goto err;
+	}
+
+	free(ctx->ctl_buf);
+	ctx->ctl_buf = malloc(ctx->ctl_buflen);
+	if (ctx->ctl_buf == NULL)
+		goto err;
+
+	ctx->ctl_bufpos = 0;
+	eloop_event_add(ctx->eloop, ctx->control_fd,
+	    dhcpcd_readdump2, ctx);
+	return;
+
+err:
+	logerr(__func__);
+	eloop_exit(ctx->eloop, EXIT_FAILURE);
+}
+
+static void
+dhcpcd_readdump0(void *arg)
+{
+	struct dhcpcd_ctx *ctx = arg;
+	ssize_t len;
+
+	len = read(ctx->control_fd, &ctx->ctl_extra, sizeof(ctx->ctl_extra));
+	if (len != sizeof(ctx->ctl_extra)) {
+		if (len != -1)
 			errno = EINVAL;
-			error = -1;
-			goto out;
-		}
-again3:
-		if (read(ctx->control_fd, buf, dlen) != (ssize_t)dlen) {
-			if (errno == EAGAIN)
-				goto again3;
-			error = -1;
-			goto out;
-		}
-		script_dump(buf, dlen);
-		fflush(stdout);
-		if (nifaces != 1)
-			putchar('\n');
+		logerr(__func__);
+		eloop_exit(ctx->eloop, EXIT_FAILURE);
+		return;
 	}
 
-out:
-	free(buf);
-	return error;
+	if (ctx->ctl_extra == 0) {
+		eloop_exit(ctx->eloop, EXIT_SUCCESS);
+		return;
+	}
+
+	eloop_event_add(ctx->eloop, ctx->control_fd,
+	    dhcpcd_readdump1, ctx);
+}
+
+static void
+dhcpcd_readdumptimeout(void *arg)
+{
+	struct dhcpcd_ctx *ctx = arg;
+
+	logerrx(__func__);
+	eloop_exit(ctx->eloop, EXIT_FAILURE);
+}
+
+static int
+dhcpcd_readdump(struct dhcpcd_ctx *ctx)
+{
+
+	ctx->options |=	DHCPCD_FORKED;
+	if (eloop_timeout_add_sec(ctx->eloop, 5,
+	    dhcpcd_readdumptimeout, ctx) == -1)
+		return -1;
+	return eloop_event_add(ctx->eloop, ctx->control_fd,
+	    dhcpcd_readdump0, ctx);
 }
 
 static void
@@ -1820,6 +1837,9 @@ main(int argc, char **argv)
 	ctx.script = UNCONST(dhcpcd_default_script);
 	ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
 	ctx.pf_inet_fd = -1;
+#ifdef PF_LINK
+	ctx.pf_link_fd = -1;
+#endif
 
 	TAILQ_INIT(&ctx.control_fds);
 #ifdef USE_SIGNALS
@@ -1841,6 +1861,9 @@ main(int argc, char **argv)
 #endif
 #ifdef PRIVSEP
 	ctx.ps_root_fd = ctx.ps_data_fd = -1;
+#ifdef PRIVSEP_COMTROLLER
+	ctx.ps_ctl_fd = -1;
+#endif
 	TAILQ_INIT(&ctx.ps_processes);
 #endif
 	rt_init(&ctx);
@@ -2153,6 +2176,7 @@ printpidfile:
 					logerr("%s: dhcpcd_readdump", __func__);
 					goto exit_failure;
 				}
+				goto run_loop;
 			}
 			goto exit_success;
 		} else {
@@ -2163,6 +2187,8 @@ printpidfile:
 					logerrx("dhcpcd is not running");
 				goto exit_failure;
 			}
+			if (errno == EPERM || errno == EACCES)
+				goto exit_failure;
 		}
 		ctx.options &= ~DHCPCD_FORKED;
 	}
@@ -2195,6 +2221,12 @@ printpidfile:
 		logerr("pipe");
 		goto exit_failure;
 	}
+#ifdef HAVE_CAPSICUM
+	if (ps_rights_limit_fdpair(sigpipe) == -1) {
+		logerr("ps_rights_limit_fdpair");
+		goto exit_failure;
+	}
+#endif
 	switch (pid = fork()) {
 	case -1:
 		logerr("fork");
@@ -2251,7 +2283,7 @@ printpidfile:
 	}
 
 #ifdef PRIVSEP
-	if (ctx.options & DHCPCD_PRIVSEP && ps_start(&ctx) == -1) {
+	if (IN_PRIVSEP(&ctx) && ps_start(&ctx) == -1) {
 		logerr("ps_start");
 		goto exit_failure;
 	}
@@ -2259,12 +2291,14 @@ printpidfile:
 		goto run_loop;
 #endif
 
-	if (!(ctx.options & DHCPCD_TEST) &&
-	    control_start(&ctx,
-	    ctx.options & DHCPCD_MASTER ? NULL : argv[optind], family) == -1)
-	{
-		logerr("%s: control_start", __func__);
-		goto exit_failure;
+	if (!(ctx.options & DHCPCD_TEST)) {
+		if (control_start(&ctx,
+		    ctx.options & DHCPCD_MASTER ?
+		    NULL : argv[optind], family) == -1)
+		{
+			logerr("%s: control_start", __func__);
+			goto exit_failure;
+		}
 	}
 
 #ifdef PLUGIN_DEV
@@ -2296,25 +2330,13 @@ printpidfile:
 	if (dhcp_vendor(ctx.vendor, sizeof(ctx.vendor)) == -1)
 		logerrx("dhcp_vendor");
 
+	/* Start handling kernel messages for interfaces, addresses and
+	 * routes. */
+	eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
+
 #ifdef PRIVSEP
-	if (ctx.options & DHCPCD_PRIVSEP) {
-		if (ps_dropprivs(&ctx) == -1) {
-			logerr("ps_dropprivs");
-			goto exit_failure;
-		}
-#ifdef HAVE_CAPSICUM
-		if (cap_enter() == -1 && errno != ENOSYS) {
-			logerr("%s: cap_enter", __func__);
-			goto exit_failure;
-		}
-#endif
-#ifdef HAVE_PLEDGE
-		if (pledge("stdio inet route dns", NULL) == -1) {
-			logerr("%s: pledge", __func__);
-			goto exit_failure;
-		}
-#endif
-	}
+	if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1)
+		goto exit_failure;
 #endif
 
 	/* When running dhcpcd against a single interface, we need to retain
@@ -2322,10 +2344,6 @@ printpidfile:
 	if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))
 		ctx.options |= DHCPCD_WAITIP;
 
-	/* Start handling kernel messages for interfaces, addresses and
-	 * routes. */
-	eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
-
 	ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv);
 	if (ctx.ifaces == NULL) {
 		logerr("%s: if_discover", __func__);
@@ -2435,11 +2453,17 @@ exit_failure:
 exit1:
 	if (control_stop(&ctx) == -1)
 		logerr("%s: control_stop", __func__);
+	if (ifaddrs != NULL) {
+#ifdef PRIVSEP_GETIFADDRS
+		if (IN_PRIVSEP(&ctx))
+			free(ifaddrs);
+		else
+#endif
+			freeifaddrs(ifaddrs);
+	}
 #ifdef PRIVSEP
 	ps_stop(&ctx);
 #endif
-	if (ifaddrs != NULL)
-		freeifaddrs(ifaddrs);
 	/* Free memory and close fd's */
 	if (ctx.ifaces) {
 		while ((ifp = TAILQ_FIRST(ctx.ifaces))) {
@@ -2480,6 +2504,7 @@ exit1:
 		loginfox(PACKAGE " exited");
 	logclose();
 	free(ctx.logfile);
+	free(ctx.ctl_buf);
 #ifdef SETPROCTITLE_H
 	setproctitle_free();
 #endif

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.21 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.22
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.21	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Mon Jun 15 16:59:05 2020
@@ -163,6 +163,10 @@ if_opensockets_os(struct dhcpcd_ctx *ctx
 
 #ifdef INET6
 	priv->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+#ifdef PRIVSEP_RIGHTS
+	if (IN_PRIVSEP(ctx))
+		ps_rights_limit_ioctl(priv->pf_inet6_fd);
+#endif
 	/* Don't return an error so we at least work on kernels witout INET6
 	 * even though we expect INET6 support.
 	 * We will fail noisily elsewhere anyway. */
@@ -292,21 +296,10 @@ if_ignore1(const char *drvname)
 	return false;
 }
 
-bool
-if_ignore(struct dhcpcd_ctx *ctx, const char *ifname)
-{
-	struct if_spec spec;
-
-	if (if_nametospec(ifname, &spec) != 0)
-		return false;
-
-	if (if_ignore1(spec.drvname))
-		return true;
-
 #ifdef SIOCGIFGROUP
-#ifdef HAVE_PLEDGE
-#warning Fix SIOCGIFGROUP to use privsep to remove inet pledge requirement
-#endif
+int
+if_ignoregroup(int s, const char *ifname)
+{
 	struct ifgroupreq ifgr = { .ifgr_len = 0 };
 	struct ifg_req *ifg;
 	size_t ifg_len;
@@ -316,12 +309,12 @@ if_ignore(struct dhcpcd_ctx *ctx, const 
 	 * will be very unlikely.... */
 
 	strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name));
-	if (ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1 ||
+	if (ioctl(s, SIOCGIFGROUP, &ifgr) == -1 ||
 	    (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL ||
-	    ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1)
+	    ioctl(s, SIOCGIFGROUP, &ifgr) == -1)
 	{
 		logerr(__func__);
-		return false;
+		return -1;
 	}
 
 	for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len;
@@ -329,13 +322,35 @@ if_ignore(struct dhcpcd_ctx *ctx, const 
 	     ifg++, ifg_len -= sizeof(*ifg))
 	{
 		if (if_ignore1(ifg->ifgrq_group))
-			return true;
+			return 1;
 	}
-#else
-	UNUSED(ctx);
+	return 0;
+}
 #endif
 
+bool
+if_ignore(struct dhcpcd_ctx *ctx, const char *ifname)
+{
+	struct if_spec spec;
+
+	if (if_nametospec(ifname, &spec) != 0)
+		return false;
+
+	if (if_ignore1(spec.drvname))
+		return true;
+
+#ifdef SIOCGIFGROUP
+#if defined(PRIVSEP) && defined(HAVE_PLEDGE)
+	if (IN_PRIVSEP(ctx))
+		return ps_root_ifignoregroup(ctx, ifname) == 1 ? true : false;
+#endif
+	else
+		return if_ignoregroup(ctx->pf_inet_fd, ifname) == 1 ?
+		    true : false;
+#else
+	UNUSED(ctx);
 	return false;
+#endif
 }
 
 int
@@ -712,9 +727,7 @@ if_route(unsigned char cmd, const struct
 		} else
 			rtm->rtm_flags |= RTF_GATEWAY;
 
-		/* Emulate the kernel by marking address generated
-		 * network routes non-static. */
-		if (!(rt->rt_dflags & RTDF_IFA_ROUTE))
+		if (rt->rt_dflags & RTDF_STATIC)
 			rtm->rtm_flags |= RTF_STATIC;
 
 		if (rt->rt_mtu != 0) {
@@ -989,8 +1002,7 @@ if_address6(unsigned char cmd, const str
 	if (ia->addr_flags & IN6_IFF_TENTATIVE)
 		ifa.ifra_flags |= IN6_IFF_TENTATIVE;
 #endif
-// #if (defined(__NetBSD__) && __NetBSD_Version__ >= 999005700) ||
-#if    (defined(__OpenBSD__) && OpenBSD >= 201605)
+#if !defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)
 	if (ia->flags & IPV6_AF_AUTOCONF)
 		ifa.ifra_flags |= IN6_IFF_AUTOCONF;
 #endif
@@ -1353,7 +1365,18 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 		struct ifaddrs *ifaddrs = NULL, *ifa;
 
 		sa = rti_info[RTAX_IFA];
-		getifaddrs(&ifaddrs);
+#ifdef PRIVSEP_GETIFADDRS
+		if (IN_PRIVSEP(ctx)) {
+			if (ps_root_getifaddrs(ctx, &ifaddrs) == -1) {
+				logerr("ps_root_getifaddrs");
+				break;
+			}
+		} else
+#endif
+		if (getifaddrs(&ifaddrs) == -1) {
+			logerr("getifaddrs");
+			break;
+		}
 		for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
 			if (ifa->ifa_addr == NULL)
 				continue;
@@ -1361,6 +1384,11 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 			    strcmp(ifa->ifa_name, ifp->name) == 0)
 				break;
 		}
+#ifdef PRIVSEP_GETIFADDRS
+		if (IN_PRIVSEP(ctx))
+			free(ifaddrs);
+		else
+#endif
 		freeifaddrs(ifaddrs);
 		if (ifam->ifam_type == RTM_DELADDR) {
 			if (ifa != NULL)

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.24 src/external/bsd/dhcpcd/dist/src/if-options.c:1.25
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.24	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Mon Jun 15 16:59:05 2020
@@ -1460,7 +1460,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				logerrx("%s: interface name too long", arg);
 				goto err_sla;
 			}
-			sla->sla_set = 0;
+			sla->sla_set = false;
 			sla->prefix_len = 0;
 			sla->suffix = 1;
 			p = np;
@@ -1471,7 +1471,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				if (*p != '\0') {
 					sla->sla = (uint32_t)strtou(p, NULL,
 					    0, 0, UINT32_MAX, &e);
-					sla->sla_set = 1;
+					sla->sla_set = true;
 					if (e) {
 						logerrx("%s: failed to convert "
 						    "sla",
@@ -1530,7 +1530,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 					    sla->ifname);
 					goto err_sla;
 				}
-				if (sla->sla_set == 0 &&
+				if (!sla->sla_set &&
 				    strcmp(slap->ifname, sla->ifname) == 0)
 				{
 					logwarnx("%s: cannot specify the "
@@ -2366,8 +2366,8 @@ read_config(struct dhcpcd_ctx *ctx,
 			return ifo;
 		}
 		if (buf[buflen - 1] != '\0') {
-			if (buflen < sizeof(buf) - 1)
-				bulen++;
+			if ((size_t)buflen < sizeof(buf) - 1)
+				buflen++;
 			buf[buflen - 1] = '\0';
 		}
 #else

Index: src/external/bsd/dhcpcd/dist/src/logerr.c
diff -u src/external/bsd/dhcpcd/dist/src/logerr.c:1.4 src/external/bsd/dhcpcd/dist/src/logerr.c:1.5
--- src/external/bsd/dhcpcd/dist/src/logerr.c:1.4	Sun May 31 12:52:11 2020
+++ src/external/bsd/dhcpcd/dist/src/logerr.c	Mon Jun 15 16:59:05 2020
@@ -50,6 +50,7 @@
 #define UNUSED(a)		(void)(a)
 
 struct logctx {
+	char		 log_buf[BUFSIZ];
 	unsigned int	 log_opts;
 #ifndef SMALL
 	FILE		*log_file;
@@ -369,6 +370,8 @@ logopen(const char *path)
 	/* Cache timezone */
 	tzset();
 
+	(void)setvbuf(stderr, ctx->log_buf, _IOLBF, sizeof(ctx->log_buf));
+
 	if (path == NULL) {
 		int opts = 0;
 
Index: src/external/bsd/dhcpcd/dist/src/privsep.c
diff -u src/external/bsd/dhcpcd/dist/src/privsep.c:1.4 src/external/bsd/dhcpcd/dist/src/privsep.c:1.5
--- src/external/bsd/dhcpcd/dist/src/privsep.c:1.4	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/privsep.c	Mon Jun 15 16:59:05 2020
@@ -39,6 +39,7 @@
  * this in a script or something.
  */
 
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -128,6 +129,49 @@ ps_dropprivs(struct dhcpcd_ctx *ctx)
 		return -1;
 	}
 
+	struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 };
+
+	if (ctx->ps_control_pid != getpid()) {
+		/* Prohibit new files, sockets, etc */
+#if defined(__linux__) || defined(__sun) || defined(__OpenBSD__)
+		/*
+		 * If poll(2) is called with nfds > RLIMIT_NOFILE
+		 * then it returns EINVAL.
+		 * This blows.
+		 * Do the best we can and limit to what we need.
+		 * An attacker could potentially close a file and
+		 * open a new one still, but that cannot be helped.
+		 */
+		unsigned long maxfd;
+		maxfd = (unsigned long)eloop_event_count(ctx->eloop);
+		if (IN_PRIVSEP_SE(ctx))
+			maxfd++; /* XXX why? */
+
+		struct rlimit rmaxfd = {
+		    .rlim_cur = maxfd,
+		    .rlim_max = maxfd
+		};
+		if (setrlimit(RLIMIT_NOFILE, &rmaxfd) == -1)
+			logerr("setrlimit RLIMIT_NOFILE");
+#else
+		if (setrlimit(RLIMIT_NOFILE, &rzero) == -1)
+			logerr("setrlimit RLIMIT_NOFILE");
+#endif
+	}
+
+	/* Prohibit writing to files.
+	 * Obviously this won't work if we are using a logfile. */
+	if (ctx->logfile == NULL) {
+		if (setrlimit(RLIMIT_FSIZE, &rzero) == -1)
+			logerr("setrlimit RLIMIT_FSIZE");
+	}
+
+#ifdef RLIMIT_NPROC
+	/* Prohibit forks */
+	if (setrlimit(RLIMIT_NPROC, &rzero) == -1)
+		logerr("setrlimit RLIMIT_NPROC");
+#endif
+
 	return 0;
 }
 
@@ -166,6 +210,71 @@ ps_setbuf(int fd)
 	return 0;
 }
 
+int
+ps_setbuf_fdpair(int fd[])
+{
+
+	if (ps_setbuf(fd[0]) == -1 || ps_setbuf(fd[1]) == -1)
+		return -1;
+	return 0;
+}
+
+#ifdef PRIVSEP_RIGHTS
+int
+ps_rights_limit_ioctl(int fd)
+{
+	cap_rights_t rights;
+
+	cap_rights_init(&rights, CAP_IOCTL);
+	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
+		return -1;
+	return 0;
+}
+
+int
+ps_rights_limit_fd_fctnl(int fd)
+{
+	cap_rights_t rights;
+
+	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT,
+	    CAP_ACCEPT, CAP_FCNTL);
+	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
+		return -1;
+	return 0;
+}
+
+int
+ps_rights_limit_fd(int fd)
+{
+	cap_rights_t rights;
+
+	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_SHUTDOWN);
+	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
+		return -1;
+	return 0;
+}
+
+int
+ps_rights_limit_fd_rdonly(int fd)
+{
+	cap_rights_t rights;
+
+	cap_rights_init(&rights, CAP_READ, CAP_EVENT);
+	if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS)
+		return -1;
+	return 0;
+}
+
+int
+ps_rights_limit_fdpair(int fd[])
+{
+
+	if (ps_rights_limit_fd(fd[0]) == -1 || ps_rights_limit_fd(fd[1]) == -1)
+		return -1;
+	return 0;
+}
+#endif
+
 pid_t
 ps_dostart(struct dhcpcd_ctx *ctx,
     pid_t *priv_pid, int *priv_fd,
@@ -176,17 +285,22 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 	int stype;
 	int fd[2];
 	pid_t pid;
-#ifdef HAVE_CAPSICUM
-	cap_rights_t rights;
-
-	cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_SHUTDOWN);
-#endif
 
 	stype = SOCK_CLOEXEC | SOCK_NONBLOCK;
 	if (socketpair(AF_UNIX, SOCK_DGRAM | stype, 0, fd) == -1) {
-		logerr("socketpair");
+		logerr("%s: socketpair", __func__);
+		return -1;
+	}
+	if (ps_setbuf_fdpair(fd) == -1) {
+		logerr("%s: ps_setbuf_fdpair", __func__);
 		return -1;
 	}
+#ifdef PRIVSEP_RIGHTS
+	if (ps_rights_limit_fdpair(fd) == -1) {
+		logerr("%s: ps_rights_limit_fdpair", __func__);
+		return -1;
+	}
+#endif
 
 	switch (pid = fork()) {
 	case -1:
@@ -195,23 +309,13 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 	case 0:
 		*priv_fd = fd[1];
 		close(fd[0]);
-		ps_setbuf(*priv_fd);
 		break;
 	default:
 		*priv_pid = pid;
 		*priv_fd = fd[0];
 		close(fd[1]);
-		ps_setbuf(*priv_fd);
 		if (recv_unpriv_msg == NULL)
 			;
-#ifdef HAVE_CAPSICUM
-		else if (cap_rights_limit(*priv_fd, &rights) == -1
-		    && errno != ENOSYS)
-		{
-			logerr("%s: cap_rights_limit", __func__);
-			return -1;
-		}
-#endif
 		else if (eloop_event_add(ctx->eloop, *priv_fd,
 		    recv_unpriv_msg, recv_ctx) == -1)
 		{
@@ -252,11 +356,6 @@ ps_dostart(struct dhcpcd_ctx *ctx,
 		goto errexit;
 	}
 
-#ifdef HAVE_CAPSICUM
-	if (cap_rights_limit(*priv_fd, &rights) == -1 && errno != ENOSYS)
-		goto errexit;
-#endif
-
 	if (eloop_event_add(ctx->eloop, *priv_fd, recv_msg, recv_ctx) == -1)
 	{
 		logerr("%s: eloop_event_add", __func__);
@@ -294,17 +393,16 @@ ps_dostop(struct dhcpcd_ctx *ctx, pid_t 
 	int err = 0;
 
 #ifdef PRIVSEP_DEBUG
-	logdebugx("%s: pid %d fd %d", __func__, *pid, *fd);
+	logdebugx("%s: pid=%d fd=%d", __func__, *pid, *fd);
 #endif
 
 	if (*fd != -1) {
 		eloop_event_delete(ctx->eloop, *fd);
-		if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1 ||
-		    shutdown(*fd, SHUT_RDWR) == -1)
-		{
+		if (ps_sendcmd(ctx, *fd, PS_STOP, 0, NULL, 0) == -1) {
 			logerr(__func__);
 			err = -1;
 		}
+		(void)shutdown(*fd, SHUT_RDWR);
 		close(*fd);
 		*fd = -1;
 	}
@@ -335,7 +433,7 @@ ps_start(struct dhcpcd_ctx *ctx)
 	/* No point in spawning the generic network listener if we're
 	 * not going to use it. */
 	if (!(ctx->options & (DHCPCD_MASTER | DHCPCD_IPV6)))
-		goto started;
+		goto started_net;
 
 	switch (pid = ps_inet_start(ctx)) {
 	case -1:
@@ -348,7 +446,17 @@ ps_start(struct dhcpcd_ctx *ctx)
 		logdebugx("spawned network proxy on PID %d", pid);
 	}
 
-started:
+started_net:
+	if (!(ctx->options & DHCPCD_TEST)) {
+		switch (pid = ps_ctl_start(ctx)) {
+		case -1:
+			return -1;
+		case 0:
+			return 0;
+		default:
+			logdebugx("spawned controller proxy on PID %d", pid);
+		}
+	}
 
 #ifdef ARC4RANDOM_H
 	/* Seed the random number generator early incase it needs /dev/urandom
@@ -360,6 +468,40 @@ started:
 }
 
 int
+ps_mastersandbox(struct dhcpcd_ctx *ctx)
+{
+
+	if (ps_dropprivs(ctx) == -1) {
+		logerr("%s: ps_dropprivs", __func__);
+		return -1;
+	}
+
+#ifdef PRIVSEP_RIGHTS
+	if ((ps_rights_limit_ioctl(ctx->pf_inet_fd) == -1 ||
+	     ps_rights_limit_fd(ctx->link_fd) == -1) &&
+	    errno != ENOSYS)
+	{
+		logerr("%s: cap_rights_limit", __func__);
+		return -1;
+	}
+#endif
+#ifdef HAVE_CAPSICUM
+	if (cap_enter() == -1 && errno != ENOSYS) {
+		logerr("%s: cap_enter", __func__);
+		return -1;
+	}
+#endif
+#ifdef HAVE_PLEDGE
+	if (pledge("stdio route", NULL) == -1) {
+		logerr("%s: pledge", __func__);
+		return -1;
+	}
+#endif
+
+	return 0;
+}
+
+int
 ps_stop(struct dhcpcd_ctx *ctx)
 {
 	int r, ret = 0;
@@ -369,6 +511,10 @@ ps_stop(struct dhcpcd_ctx *ctx)
 	    ctx->eloop == NULL)
 		return 0;
 
+	r = ps_ctl_stop(ctx);
+	if (r != 0)
+		ret = r;
+
 	r = ps_inet_stop(ctx);
 	if (r != 0)
 		ret = r;

Index: src/external/bsd/dhcpcd/dist/src/script.c
diff -u src/external/bsd/dhcpcd/dist/src/script.c:1.7 src/external/bsd/dhcpcd/dist/src/script.c:1.8
--- src/external/bsd/dhcpcd/dist/src/script.c:1.7	Thu Jun  4 13:08:13 2020
+++ src/external/bsd/dhcpcd/dist/src/script.c	Mon Jun 15 16:59:05 2020
@@ -560,7 +560,7 @@ send_interface1(struct fd_list *fd, cons
 	len = make_env(ifp->ctx, ifp, reason);
 	if (len == -1)
 		return -1;
-	return control_queue(fd, ctx->script_buf, (size_t)len, 1);
+	return control_queue(fd, ctx->script_buf, (size_t)len);
 }
 
 int
@@ -752,8 +752,7 @@ send_listeners:
 	TAILQ_FOREACH(fd, &ctx->control_fds, next) {
 		if (!(fd->flags & FD_LISTEN))
 			continue;
-		if (control_queue(fd, ctx->script_buf, ctx->script_buflen,
-		    true) == -1)
+		if (control_queue(fd, ctx->script_buf, ctx->script_buflen)== -1)
 			logerr("%s: control_queue", __func__);
 		else
 			status = 1;

Reply via email to