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;