Module Name: src Committed By: martin Date: Sun May 5 08:24:04 UTC 2019
Modified Files: src/external/bsd/dhcpcd/dist/src [netbsd-8]: bpf.c defs.h dhcp.c dhcp6.c dhcpcd.c dhcpcd.h if-bsd.c if-linux.c if-options.c if-sun.c if.c if.h Log Message: Sync to current, requested by roy in ticket #1256: external/bsd/dhcpcd/dist/src/bpf.c up to 1.9 external/bsd/dhcpcd/dist/src/defs.h up to 1.1.1.21 external/bsd/dhcpcd/dist/src/dhcp.c up to 1.19 external/bsd/dhcpcd/dist/src/dhcp6.c up to 1.7 external/bsd/dhcpcd/dist/src/dhcpcd.c up to 1.19 external/bsd/dhcpcd/dist/src/dhcpcd.h up to 1.1.1.10 external/bsd/dhcpcd/dist/src/if-bsd.c up to 1.7 external/bsd/dhcpcd/dist/src/if-linux.c up to 1.1.1.13 external/bsd/dhcpcd/dist/src/if-options.c up to 1.14 external/bsd/dhcpcd/dist/src/if-sun.c up to 1.1.1.8 external/bsd/dhcpcd/dist/src/if.c up to 1.1.1.13 external/bsd/dhcpcd/dist/src/if.h up to 1.1.1.8 Import dhcpcd-7.2.2 with the following changes: * DHCP: Ensure dhcp is running on the interface received from * BSD: Link handling has been simplified, however it is expected that if an interface supports SIOCGIFMEDIA then it reports the correct link status via route(4) for reliable operations * BPF: ARP filter is more robust * BSD: Validate RTM message lengths This security issue has been addressed: * DHCPv6: Fix a potential read overflow with D6_OPTION_PD_EXCLUDE Many thanks to Maxime Villard <m...@m00nbsd.net> for discovering this issue. To generate a diff of this commit: cvs rdiff -u -r1.3.8.3 -r1.3.8.4 src/external/bsd/dhcpcd/dist/src/bpf.c cvs rdiff -u -r1.1.1.4.2.7 -r1.1.1.4.2.8 \ src/external/bsd/dhcpcd/dist/src/defs.h cvs rdiff -u -r1.1.1.3.8.6 -r1.1.1.3.8.7 \ src/external/bsd/dhcpcd/dist/src/dhcp.c cvs rdiff -u -r1.1.1.4.2.5 -r1.1.1.4.2.6 \ src/external/bsd/dhcpcd/dist/src/dhcp6.c cvs rdiff -u -r1.4.2.5 -r1.4.2.6 src/external/bsd/dhcpcd/dist/src/dhcpcd.c cvs rdiff -u -r1.1.1.3.2.3 -r1.1.1.3.2.4 \ src/external/bsd/dhcpcd/dist/src/dhcpcd.h cvs rdiff -u -r1.1.1.3.2.5 -r1.1.1.3.2.6 \ src/external/bsd/dhcpcd/dist/src/if-bsd.c \ src/external/bsd/dhcpcd/dist/src/if-linux.c cvs rdiff -u -r1.4.2.4 -r1.4.2.5 \ src/external/bsd/dhcpcd/dist/src/if-options.c cvs rdiff -u -r1.1.1.2.2.3 -r1.1.1.2.2.4 \ src/external/bsd/dhcpcd/dist/src/if-sun.c \ src/external/bsd/dhcpcd/dist/src/if.h cvs rdiff -u -r1.1.1.3.2.4 -r1.1.1.3.2.5 \ src/external/bsd/dhcpcd/dist/src/if.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.3.8.3 src/external/bsd/dhcpcd/dist/src/bpf.c:1.3.8.4 --- src/external/bsd/dhcpcd/dist/src/bpf.c:1.3.8.3 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/bpf.c Sun May 5 08:24:04 2019 @@ -301,6 +301,7 @@ bpf_close(struct interface *ifp, int fd) /* Normally this is needed by bootp. * Once that uses this again, the ARP guard here can be removed. */ #ifdef ARP +#define BPF_CMP_HWADDR_LEN ((((HWADDR_LEN / 4) + 2) * 2) + 1) static unsigned int bpf_cmp_hwaddr(struct bpf_insn *bpf, size_t bpf_len, size_t off, bool equal, uint8_t *hwaddr, size_t hwaddr_len) @@ -414,7 +415,7 @@ static const struct bpf_insn bpf_arp_eth sizeof(((struct ether_arp *)0)->arp_sha), 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), }; -#define bpf_arp_ether_len __arraycount(bpf_arp_ether) +#define BPF_ARP_ETHER_LEN __arraycount(bpf_arp_ether) static const struct bpf_insn bpf_arp_filter [] = { /* Make sure this is for IP. */ @@ -425,21 +426,25 @@ static const struct bpf_insn bpf_arp_fil BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct arphdr, ar_op)), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), /* or ARP REPLY. */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 1), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), /* Make sure the protocol length matches. */ BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct arphdr, ar_pln)), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(in_addr_t), 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), }; -#define bpf_arp_filter_len __arraycount(bpf_arp_filter) -#define bpf_arp_extra ((((ARP_ADDRS_MAX + 1) * 2) * 2) + 2) -#define bpf_arp_hw ((((HWADDR_LEN / 4) + 2) * 2) + 1) +#define BPF_ARP_FILTER_LEN __arraycount(bpf_arp_filter) + +#define BPF_ARP_ADDRS_LEN 1 + (ARP_ADDRS_MAX * 2) + 3 + \ + (ARP_ADDRS_MAX * 2) + 1 + +#define BPF_ARP_LEN BPF_ARP_ETHER_LEN + BPF_ARP_FILTER_LEN + \ + BPF_CMP_HWADDR_LEN + BPF_ARP_ADDRS_LEN int bpf_arp(struct interface *ifp, int fd) { - struct bpf_insn bpf[3+ bpf_arp_filter_len + bpf_arp_hw + bpf_arp_extra]; + struct bpf_insn bpf[BPF_ARP_LEN]; struct bpf_insn *bp; struct iarp_state *state; uint16_t arp_len; @@ -452,7 +457,7 @@ bpf_arp(struct interface *ifp, int fd) switch(ifp->family) { case ARPHRD_ETHER: memcpy(bp, bpf_arp_ether, sizeof(bpf_arp_ether)); - bp += bpf_arp_ether_len; + bp += BPF_ARP_ETHER_LEN; arp_len = sizeof(struct ether_header)+sizeof(struct ether_arp); break; default: @@ -462,10 +467,10 @@ bpf_arp(struct interface *ifp, int fd) /* Copy in the main filter. */ memcpy(bp, bpf_arp_filter, sizeof(bpf_arp_filter)); - bp += bpf_arp_filter_len; + bp += BPF_ARP_FILTER_LEN; /* Ensure it's not from us. */ - bp += bpf_cmp_hwaddr(bp, bpf_arp_hw, sizeof(struct arphdr), + bp += bpf_cmp_hwaddr(bp, BPF_CMP_HWADDR_LEN, sizeof(struct arphdr), false, ifp->hwaddr, ifp->hwlen); state = ARP_STATE(ifp); Index: src/external/bsd/dhcpcd/dist/src/defs.h diff -u src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.7 src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.8 --- src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.7 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/defs.h Sun May 5 08:24:04 2019 @@ -28,7 +28,7 @@ #define CONFIG_H #define PACKAGE "dhcpcd" -#define VERSION "7.2.1" +#define VERSION "7.2.2" #ifndef CONFIG # define CONFIG SYSCONFDIR "/" PACKAGE ".conf" Index: src/external/bsd/dhcpcd/dist/src/dhcp.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.6 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.7 --- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.6 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp.c Sun May 5 08:24:04 2019 @@ -3499,9 +3499,14 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str logerr(__func__); return; } + if (D_CSTATE(ifp) == NULL) { + logdebugx("%s: received BOOTP for inactive interface", + ifp->name); + return; + } } - dhcp_handlebootp(ifp, (struct bootp *)buf, (size_t)bytes, + dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes, &from.sin_addr); #endif } Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.5 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.6 --- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.5 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Sun May 5 08:24:04 2019 @@ -2166,40 +2166,38 @@ dhcp6_findpd(struct interface *ifp, cons state->expire = a->prefix_vltime; i++; - o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol); a->prefix_exclude_len = 0; memset(&a->prefix_exclude, 0, sizeof(a->prefix_exclude)); -#if 0 - if (ex == NULL) { - struct dhcp6_option *w; - uint8_t *wp; - - w = calloc(1, 128); - w->len = htons(2); - wp = D6_OPTION_DATA(w); - *wp++ = 64; - *wp++ = 0x78; - ex = w; - } -#endif + o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol); if (o == NULL) continue; - if (ol < 2) { - logerrx("%s: truncated PD Exclude", ifp->name); + + /* RFC 6603 4.2 says option length MUST be between 2 and 17. + * This allows 1 octet for prefix length and 16 for the + * subnet ID. */ + if (ol < 2 || ol > 17) { + logerrx("%s: invalid PD Exclude option", ifp->name); continue; } - a->prefix_exclude_len = *o++; + + /* RFC 6603 4.2 says prefix length MUST be between the + * length of the IAPREFIX prefix length + 1 and 128. */ + if (*o < a->prefix_len + 1 || *o > 128) { + logerrx("%s: invalid PD Exclude length", ifp->name); + continue; + } + ol--; - if (((a->prefix_exclude_len - a->prefix_len - 1) / NBBY) + 1 - != ol) - { + /* Check option length matches prefix length. */ + if (((*o - a->prefix_len - 1) / NBBY) + 1 != ol) { logerrx("%s: PD Exclude length mismatch", ifp->name); - a->prefix_exclude_len = 0; continue; } - nb = a->prefix_len % NBBY; + a->prefix_exclude_len = *o++; + memcpy(&a->prefix_exclude, &a->prefix, sizeof(a->prefix_exclude)); + nb = a->prefix_len % NBBY; if (nb) ol--; pw = a->prefix_exclude.s6_addr + Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.5 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.6 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.5 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Sun May 5 08:24:04 2019 @@ -84,6 +84,9 @@ const int dhcpcd_signals[] = { const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals); #endif +#define IF_UPANDRUNNING(a) \ + (((a)->flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) + static void usage(void) { @@ -653,25 +656,6 @@ configure_interface(struct interface *if } static void -dhcpcd_pollup(void *arg) -{ - struct interface *ifp = arg; - int carrier; - - carrier = if_carrier(ifp); /* will set ifp->flags */ - if (carrier == LINK_UP && !(ifp->flags & IFF_UP)) { - struct timespec tv; - - tv.tv_sec = 0; - tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC; - eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp); - return; - } - - dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name); -} - -static void dhcpcd_initstate2(struct interface *ifp, unsigned long long options) { struct if_options *ifo; @@ -724,35 +708,18 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx * !ifp->active) return; - switch(carrier) { - case LINK_UNKNOWN: - carrier = if_carrier(ifp); /* will set ifp->flags */ - break; - case LINK_UP: - /* we have a carrier! Still need to check for IFF_UP */ - if (flags & IFF_UP) + if (carrier == LINK_UNKNOWN) { + if (ifp->wireless) { + carrier = LINK_DOWN; ifp->flags = flags; - else { - /* So we need to poll for IFF_UP as there is no - * kernel notification when it's set. */ - dhcpcd_pollup(ifp); - return; - } - break; - default: + } else + carrier = if_carrier(ifp); + } else ifp->flags = flags; - } + if (carrier == LINK_UNKNOWN) + carrier = IF_UPANDRUNNING(ifp) ? LINK_UP : LINK_DOWN; - /* If we here, we don't need to poll for IFF_UP any longer - * if generated by a kernel event. */ - eloop_timeout_delete(ifp->ctx->eloop, dhcpcd_pollup, ifp); - - if (carrier == LINK_UNKNOWN) { - if (errno != ENOTTY && errno != ENXIO) { - /* Don't log an error if interface departed */ - logerr("%s: %s", ifp->name, __func__); - } - } else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) { + if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) { if (ifp->carrier != LINK_DOWN) { if (ifp->carrier == LINK_UP) loginfox("%s: carrier lost", ifp->name); @@ -867,7 +834,6 @@ dhcpcd_startinterface(void *arg) struct if_options *ifo = ifp->options; char buf[DUID_LEN * 3]; int carrier; - struct timespec tv; if (ifo->options & DHCPCD_LINK) { switch (ifp->carrier) { @@ -879,14 +845,22 @@ dhcpcd_startinterface(void *arg) case LINK_UNKNOWN: /* No media state available. * Loop until both IFF_UP and IFF_RUNNING are set */ - if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) { - tv.tv_sec = 0; - tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC; - eloop_timeout_add_tv(ifp->ctx->eloop, - &tv, dhcpcd_startinterface, ifp); - } else - dhcpcd_handlecarrier(ifp->ctx, carrier, - ifp->flags, ifp->name); + carrier = if_carrier(ifp); + if (carrier == LINK_UNKNOWN) { + if (IF_UPANDRUNNING(ifp)) + carrier = LINK_UP; + else { + struct timespec tv; + + tv.tv_sec = 0; + tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC; + eloop_timeout_add_tv(ifp->ctx->eloop, + &tv, dhcpcd_startinterface, ifp); + return; + } + } + dhcpcd_handlecarrier(ifp->ctx, carrier, + ifp->flags, ifp->name); return; } } @@ -987,20 +961,6 @@ dhcpcd_prestartinterface(void *arg) ) logerr("%s: %s", __func__, ifp->name); - if (ifp->options->options & DHCPCD_LINK && - ifp->carrier == LINK_UNKNOWN) - { - int carrier; - - if ((carrier = if_carrier(ifp)) != LINK_UNKNOWN) { - dhcpcd_handlecarrier(ifp->ctx, carrier, - ifp->flags, ifp->name); - return; - } - loginfox("%s: unknown carrier, waiting for interface flags", - ifp->name); - } - dhcpcd_startinterface(ifp); } @@ -1121,7 +1081,8 @@ dhcpcd_handlelink(void *arg) dhcpcd_linkoverflow(ctx); return; } - logerr(__func__); + if (errno != ENOTSUP) + logerr(__func__); } } Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.h diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.3 src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.4 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.3 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.h Sun May 5 08:24:04 2019 @@ -85,7 +85,6 @@ struct interface { unsigned short vlanid; unsigned int metric; int carrier; - bool media_valid; bool wireless; uint8_t ssid[IF_SSIDLEN]; unsigned int ssid_len; Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.5 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.6 --- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.5 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Sun May 5 08:24:04 2019 @@ -203,6 +203,19 @@ if_closesockets_os(struct dhcpcd_ctx *ct close(priv->pf_inet6_fd); } +int +if_carrier(struct interface *ifp) +{ + struct ifmediareq ifmr = { .ifm_status = 0 }; + + strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); + if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 || + !(ifmr.ifm_status & IFM_AVALID)) + return LINK_UNKNOWN; + + return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN; +} + static void if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp) { @@ -347,20 +360,28 @@ if_vlanid(const struct interface *ifp) #endif } -static void -get_addrs(int type, const void *data, const struct sockaddr **sa) +static int +get_addrs(int type, const void *data, size_t data_len, + const struct sockaddr **sa) { - const char *cp; + const char *cp, *ep; int i; cp = data; + ep = cp + data_len; for (i = 0; i < RTAX_MAX; i++) { if (type & (1 << i)) { + if (cp >= ep) { + errno = EINVAL; + return -1; + } sa[i] = (const struct sockaddr *)cp; RT_ADVANCE(cp, sa[i]); } else sa[i] = NULL; } + + return 0; } static struct interface * @@ -634,7 +655,12 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct } #endif - get_addrs(rtm->rtm_addrs, rtm + 1, rti_info); + /* We have already checked that at least one address must be + * present after the rtm structure. */ + /* coverity[ptr_arith] */ + if (get_addrs(rtm->rtm_addrs, rtm + 1, + rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1) + return -1; memset(rt, 0, sizeof(*rt)); rt->rt_flags = (unsigned int)rtm->rtm_flags; @@ -700,13 +726,17 @@ if_initrt(struct dhcpcd_ctx *ctx, int af end = buf + needed; for (p = buf; p < end; p += rtm->rtm_msglen) { rtm = (void *)p; + if (p + rtm->rtm_msglen >= end) { + errno = EINVAL; + break; + } if (if_copyrt(ctx, &rt, rtm) == 0) { rt.rt_dflags |= RTDF_INIT; rt_recvrt(RTM_ADD, &rt, rtm->rtm_pid); } } free(buf); - return 0; + return p == end ? 0 : -1; } #ifdef INET @@ -968,40 +998,45 @@ if_getlifetime6(struct ipv6_addr *ia) } #endif -static void +static int if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan) { + if (ifan->ifan_msglen < sizeof(*ifan)) { + errno = EINVAL; + return -1; + } + switch(ifan->ifan_what) { case IFAN_ARRIVAL: - dhcpcd_handleinterface(ctx, 1, ifan->ifan_name); - break; + return dhcpcd_handleinterface(ctx, 1, ifan->ifan_name); case IFAN_DEPARTURE: - dhcpcd_handleinterface(ctx, -1, ifan->ifan_name); - break; + return dhcpcd_handleinterface(ctx, -1, ifan->ifan_name); } + + return 0; } -static void +static int if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) { struct interface *ifp; int link_state; + if (ifm->ifm_msglen < sizeof(*ifm)) { + errno = EINVAL; + return -1; + } + if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) - return; + return 0; switch (ifm->ifm_data.ifi_link_state) { case LINK_STATE_UNKNOWN: - if (ifp->media_valid) { - link_state = LINK_DOWN; - break; - } - /* Interface does not report media state, so we have - * to rely on IFF_UP. */ - /* FALLTHROUGH */ + link_state = LINK_UNKNOWN; + break; case LINK_STATE_UP: - link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN; + link_state = LINK_UP; break; default: link_state = LINK_DOWN; @@ -1010,19 +1045,25 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const dhcpcd_handlecarrier(ctx, link_state, (unsigned int)ifm->ifm_flags, ifp->name); + return 0; } -static void +static int if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) { struct rt rt; + if (rtm->rtm_msglen < sizeof(*rtm)) { + errno = EINVAL; + return -1; + } + /* Ignore errors. */ if (rtm->rtm_errno != 0) - return; + return 0; if (if_copyrt(ctx, &rt, rtm) == -1) - return; + return -1; #ifdef INET6 /* @@ -1046,9 +1087,10 @@ if_rtm(struct dhcpcd_ctx *ctx, const str #endif rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); + return 0; } -static void +static int if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) { struct interface *ifp; @@ -1056,11 +1098,21 @@ if_ifa(struct dhcpcd_ctx *ctx, const str int addrflags; pid_t pid; + if (ifam->ifam_msglen < sizeof(*ifam)) { + errno = EINVAL; + return -1; + } + if (~ifam->ifam_addrs & RTA_IFA) + return 0; if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL) - return; - get_addrs(ifam->ifam_addrs, ifam + 1, rti_info); - if (rti_info[RTAX_IFA] == NULL) - return; + return 0; + + /* We have already checked that at least one address must be + * present after the ifam structure. */ + /* coverity[ptr_arith] */ + if (get_addrs(ifam->ifam_addrs, ifam + 1, + ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1) + return -1; #ifdef HAVE_IFAM_PID pid = ifam->ifam_pid; @@ -1160,7 +1212,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str } freeifaddrs(ifaddrs); if (ifa != NULL) - return; + return 0; #endif } @@ -1223,42 +1275,41 @@ if_ifa(struct dhcpcd_ctx *ctx, const str } #endif } + + return 0; } -static void +static int if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) { if (rtm->rtm_version != RTM_VERSION) - return; + return 0; switch(rtm->rtm_type) { #ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: - if_announce(ctx, (const void *)rtm); - break; + return if_announce(ctx, (const void *)rtm); #endif case RTM_IFINFO: - if_ifinfo(ctx, (const void *)rtm); - break; + return if_ifinfo(ctx, (const void *)rtm); case RTM_ADD: /* FALLTHROUGH */ case RTM_CHANGE: /* FALLTHROUGH */ case RTM_DELETE: - if_rtm(ctx, (const void *)rtm); - break; + return if_rtm(ctx, (const void *)rtm); #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */ #endif case RTM_DELADDR: /* FALLTHROUGH */ case RTM_NEWADDR: - if_ifa(ctx, (const void *)rtm); - break; + return if_ifa(ctx, (const void *)rtm); #ifdef RTM_DESYNC case RTM_DESYNC: - dhcpcd_linkoverflow(ctx); - break; + return dhcpcd_linkoverflow(ctx); #endif } + + return 0; } int @@ -1272,9 +1323,13 @@ if_handlelink(struct dhcpcd_ctx *ctx) len = recvmsg(ctx->link_fd, &msg, 0); if (len == -1) return -1; - if (len != 0) - if_dispatch(ctx, &rtm.hdr); - return 0; + if (len == 0) + return 0; + if (len < rtm.hdr.rtm_msglen) { + errno = EINVAL; + return -1; + } + return if_dispatch(ctx, &rtm.hdr); } #ifndef SYS_NMLN /* OSX */ Index: src/external/bsd/dhcpcd/dist/src/if-linux.c diff -u src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.5 src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.6 --- src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.5 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if-linux.c Sun May 5 08:24:04 2019 @@ -349,6 +349,15 @@ if_closesockets_os(struct dhcpcd_ctx *ct } } +int +if_carrier(struct interface *ifp) +{ + + if (if_getflags(ifp) == -1) + return LINK_UNKNOWN; + return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; +} + static int get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov, struct interface *ifp, int fd, int flags, Index: src/external/bsd/dhcpcd/dist/src/if-options.c diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.4 src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.5 --- src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.4 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if-options.c Sun May 5 08:24:04 2019 @@ -1320,7 +1320,7 @@ parse_option(struct dhcpcd_ctx *ctx, con return -1; #else if (ifname == NULL) { - logerr("IA PD must belong in an " + logerrx("IA PD must belong in an " "interface block"); return -1; } Index: src/external/bsd/dhcpcd/dist/src/if-sun.c diff -u src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.3 src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.4 --- src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.3 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if-sun.c Sun May 5 08:24:04 2019 @@ -171,13 +171,16 @@ if_closesockets_os(struct dhcpcd_ctx *ct } int -if_carrier_os(struct interface *ifp) +if_carrier(struct interface *ifp) { kstat_ctl_t *kcp; kstat_t *ksp; kstat_named_t *knp; link_state_t linkstate; + if (if_getflags(ifp) == -1) + return LINK_UNKNOWN; + kcp = kstat_open(); if (kcp == NULL) goto err; @@ -423,21 +426,26 @@ if_linkaddr(struct sockaddr_dl *sdl, con } static int -get_addrs(int type, const void *data, const struct sockaddr **sa) +get_addrs(int type, const void *data, size_t data_len, + const struct sockaddr **sa) { - const char *cp; + const char *cp, *ep; int i; - const struct sockaddr **sap; cp = data; + ep = cp + data_len; for (i = 0; i < RTAX_MAX; i++) { - sap = &sa[i]; if (type & (1 << i)) { - *sap = (const struct sockaddr *)cp; - RT_ADVANCE(cp, *sap); + if (cp >= ep) { + errno = EINVAL; + return -1; + } + sa[i] = (const struct sockaddr *)cp; + RT_ADVANCE(cp, sa[i]); } else - *sap = NULL; + sa[i] = NULL; } + return 0; } @@ -629,10 +637,16 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct { const struct sockaddr *rti_info[RTAX_MAX]; - if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) + if (~rtm->rtm_addrs & RTA_DST) + return -1; + + /* We have already checked that at least one address must be + * present after the rtm structure. */ + /* coverity[ptr_arith] */ + if (get_addrs(rtm->rtm_addrs, rtm + 1, + rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1) return -1; - get_addrs(rtm->rtm_addrs, rtm + 1, rti_info); memset(rt, 0, sizeof(*rt)); rt->rt_flags = (unsigned int)rtm->rtm_flags; @@ -640,7 +654,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct if (rtm->rtm_addrs & RTA_NETMASK) COPYSA(&rt->rt_netmask, rti_info[RTAX_NETMASK]); /* dhcpcd likes an unspecified gateway to indicate via the link. */ - if (rt->rt_flags & RTF_GATEWAY && + if (rtm->rtm_addrs & RTA_GATEWAY && rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]); if (rtm->rtm_addrs & RTA_SRC) @@ -696,7 +710,7 @@ out: return rt; } -static void +static int if_finishrt(struct dhcpcd_ctx *ctx, struct rt *rt) { int mtu; @@ -740,10 +754,8 @@ if_finishrt(struct dhcpcd_ctx *ctx, stru if (rt->rt_ifp == NULL) { if (if_route_get(ctx, rt) == NULL) { rt->rt_ifp = if_loopback(ctx); - if (rt->rt_ifp == NULL) { - logerr(__func__); - return; - } + if (rt->rt_ifp == NULL) + return - 1; } } @@ -752,8 +764,12 @@ if_finishrt(struct dhcpcd_ctx *ctx, stru * This confuses dhcpcd as it expects MTU to be 0 * when no explicit MTU has been set. */ mtu = if_getmtu(rt->rt_ifp); + if (mtu == -1) + return -1; if (rt->rt_mtu == (unsigned int)mtu) rt->rt_mtu = 0; + + return 0; } static uint64_t @@ -773,12 +789,17 @@ if_addrflags0(int fd, const char *ifname return lifr.lifr_flags; } -static void +static int if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) { const struct sockaddr *sa; struct rt rt; + if (rtm->rtm_msglen < sizeof(*rtm) + sizeof(*sa)) { + errno = EINVAL; + return -1; + } + sa = (const void *)(rtm + 1); switch (sa->sa_family) { #ifdef INET6 @@ -796,7 +817,9 @@ if_rtm(struct dhcpcd_ctx *ctx, const str struct in6_addr dst6; struct sockaddr_dl sdl; - get_addrs(rtm->rtm_addrs, sa, rti_info); + if (get_addrs(rtm->rtm_addrs, sa, + rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1) + return -1; COPYOUT6(dst6, rti_info[RTAX_DST]); if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) memcpy(&sdl, rti_info[RTAX_GATEWAY], @@ -811,10 +834,12 @@ if_rtm(struct dhcpcd_ctx *ctx, const str } #endif - if (if_copyrt(ctx, &rt, rtm) == 0) { - if_finishrt(ctx, &rt); - rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); - } + if (if_copyrt(ctx, &rt, rtm) == -1 && errno != ESRCH) + return -1; + if (if_finishrt(ctx, &rt) == -1) + return -1; + rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); + return 0; } static bool @@ -860,7 +885,7 @@ if_getbrdaddr(struct dhcpcd_ctx *ctx, co return r; } -static void +static int if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) { struct interface *ifp; @@ -868,16 +893,26 @@ if_ifa(struct dhcpcd_ctx *ctx, const str int flags; char ifalias[IF_NAMESIZE]; + if (ifam->ifam_msglen < sizeof(*ifam)) { + errno = EINVAL; + return -1; + } + if (~ifam->ifam_addrs & RTA_IFA) + return 0; + + /* We have already checked that at least one address must be + * present after the ifam structure. */ + /* coverity[ptr_arith] */ + if (get_addrs(ifam->ifam_addrs, ifam + 1, + ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1) + return -1; + sa = rti_info[RTAX_IFA]; + /* XXX We have no way of knowing who generated these * messages wich truely sucks because we want to * avoid listening to our own delete messages. */ if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL) - return; - sa = (const void *)(ifam + 1); - get_addrs(ifam->ifam_addrs, sa, rti_info); - - if ((sa = rti_info[RTAX_IFA]) == NULL) - return; + return 0; /* * ifa_msghdr does not supply the alias, just the interface index. @@ -893,7 +928,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str * ifam_pid */ if (ifam->ifam_type != RTM_DELADDR && !if_getalias(ifp, sa, ifalias)) - return; + return 0; switch (sa->sa_family) { case AF_LINK: @@ -921,20 +956,20 @@ if_ifa(struct dhcpcd_ctx *ctx, const str ia = ipv4_iffindaddr(ifp, &addr, &mask); if (ia == NULL) - return; + return 0; strlcpy(ifalias, ia->alias, sizeof(ifalias)); } else if (bcast.s_addr == INADDR_ANY) { /* Work around a bug where broadcast * address is not correctly reported. */ if (if_getbrdaddr(ctx, ifalias, &bcast) == -1) - return; + return 0; } flags = if_addrflags(ifp, &addr, ifalias); if (ifam->ifam_type == RTM_DELADDR) { if (flags != -1) - return; + return 0; } else if (flags == -1) - return; + return 0; ipv4_handleifa(ctx, ifam->ifam_type == RTM_CHGADDR ? @@ -959,15 +994,15 @@ if_ifa(struct dhcpcd_ctx *ctx, const str ia = ipv6_iffindaddr(ifp, &addr6, 0); if (ia == NULL) - return; + return 0; strlcpy(ifalias, ia->alias, sizeof(ifalias)); } flags = if_addrflags6(ifp, &addr6, ifalias); if (ifam->ifam_type == RTM_DELADDR) { if (flags != -1) - return; + return 0; } else if (flags == -1) - return; + return 0; ipv6_handleifa(ctx, ifam->ifam_type == RTM_CHGADDR ? @@ -977,17 +1012,24 @@ if_ifa(struct dhcpcd_ctx *ctx, const str } #endif } + + return 0; } -static void +static int if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) { struct interface *ifp; int state; unsigned int flags; + if (ifm->ifm_msglen < sizeof(*ifm)) { + errno = EINVAL; + return -1; + } + if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) - return; + return 0; flags = (unsigned int)ifm->ifm_flags; if (ifm->ifm_flags & IFF_OFFLINE) state = LINK_DOWN; @@ -996,30 +1038,30 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const flags |= IFF_UP; } dhcpcd_handlecarrier(ctx, state, flags, ifp->name); + return 0; } -static void +static int if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) { if (rtm->rtm_version != RTM_VERSION) - return; + return 0; switch(rtm->rtm_type) { case RTM_IFINFO: - if_ifinfo(ctx, (const void *)rtm); - break; + return if_ifinfo(ctx, (const void *)rtm); case RTM_ADD: /* FALLTHROUGH */ case RTM_CHANGE: /* FALLTHROUGH */ case RTM_DELETE: - if_rtm(ctx, (const void *)rtm); - break; + return if_rtm(ctx, (const void *)rtm); case RTM_CHGADDR: /* FALLTHROUGH */ case RTM_DELADDR: /* FALLTHROUGH */ case RTM_NEWADDR: - if_ifa(ctx, (const void *)rtm); - break; + return if_ifa(ctx, (const void *)rtm); } + + return 0; } int @@ -1032,9 +1074,15 @@ if_handlelink(struct dhcpcd_ctx *ctx) if ((len = recvmsg(ctx->link_fd, &msg, 0)) == -1) return -1; - if (len != 0) - if_dispatch(ctx, &rtm.hdr); - return 0; + if (len == -1) + return -1; + if (len == 0) + return 0; + if (len < rtm.hdr.rtm_msglen) { + errno = EINVAL; + return -1; + } + return if_dispatch(ctx, &rtm.hdr); } static void @@ -1320,8 +1368,10 @@ if_walkrt(struct dhcpcd_ctx *ctx, char * rt.rt_mtu = re->ipRouteInfo.re_max_frag; if_octetstr(ifname, &re->ipRouteIfIndex, sizeof(ifname)); rt.rt_ifp = if_find(ctx->ifaces, ifname); - if_finishrt(ctx, &rt); - rt_recvrt(RTM_ADD, &rt, 0); + if (if_finishrt(ctx, &rt) == -1) + logerr(__func__); + else + rt_recvrt(RTM_ADD, &rt, 0); } while (++re < e); return 0; } @@ -1367,8 +1417,10 @@ if_walkrt6(struct dhcpcd_ctx *ctx, char rt.rt_mtu = re->ipv6RouteInfo.re_max_frag; if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname)); rt.rt_ifp = if_find(ctx->ifaces, ifname); - if_finishrt(ctx, &rt); - rt_recvrt(RTM_ADD, &rt, 0); + if (if_finishrt(ctx, &rt) == -1) + logerr(__func__); + else + rt_recvrt(RTM_ADD, &rt, 0); } while (++re < e); return 0; } Index: src/external/bsd/dhcpcd/dist/src/if.h diff -u src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.3 src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.4 --- src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.3 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if.h Sun May 5 08:24:04 2019 @@ -111,6 +111,7 @@ int if_getifaddrs(struct ifaddrs **); #define getifaddrs if_getifaddrs #endif +int if_getflags(struct interface *ifp); int if_setflag(struct interface *ifp, short flag); #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING)) bool if_valid_hwaddr(const uint8_t *, size_t); @@ -133,7 +134,6 @@ int if_carrier(struct interface *); int if_makealias(char *, size_t, const char *, int); #endif -int if_carrier_os(struct interface *); int if_mtu_os(const struct interface *); /* Index: src/external/bsd/dhcpcd/dist/src/if.c diff -u src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.4 src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.5 --- src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.4 Fri Apr 26 19:18:22 2019 +++ src/external/bsd/dhcpcd/dist/src/if.c Sun May 5 08:24:04 2019 @@ -126,65 +126,37 @@ if_closesockets(struct dhcpcd_ctx *ctx) } int -if_carrier(struct interface *ifp) +if_getflags(struct interface *ifp) { - int r; - struct ifreq ifr; -#ifdef SIOCGIFMEDIA - struct ifmediareq ifmr; -#endif + struct ifreq ifr = { .ifr_flags = 0 }; - memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr); - if (r != -1) - ifp->flags = (unsigned int)ifr.ifr_flags; - -#ifdef __sun - return if_carrier_os(ifp); -#else - if (r == -1) - return LINK_UNKNOWN; - -#ifdef SIOCGIFMEDIA - memset(&ifmr, 0, sizeof(ifmr)); - strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); - if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) != -1 && - ifmr.ifm_status & IFM_AVALID) - { - ifp->media_valid = true; - r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN; - } else { - ifp->media_valid = false; - r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN; - } -#else - r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; -#endif -#endif /* __sun */ - return r; + if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) + return -1; + ifp->flags = (unsigned int)ifr.ifr_flags; + return 0; } int if_setflag(struct interface *ifp, short flag) { - struct ifreq ifr; - int r; + struct ifreq ifr = { .ifr_flags = 0 }; + short f; + + if (if_getflags(ifp) == -1) + return -1; + + f = (short)ifp->flags; + if ((f & flag) == flag) + return 0; - memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - r = -1; - if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) { - if (flag == 0 || (ifr.ifr_flags & flag) == flag) - r = 0; - else { - ifr.ifr_flags |= flag; - if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0) - r = 0; - } - ifp->flags = (unsigned int)ifr.ifr_flags; - } - return r; + ifr.ifr_flags = f | flag; + if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1) + return -1; + + ifp->flags = (unsigned int)ifr.ifr_flags; + return 0; } static int