Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/roy]: src/external/bsd/dhcpcd/dist/src Import dhcpcd-7.2.2 with the foll...



details:   https://anonhg.NetBSD.org/src/rev/8392e1c2f711
branches:  roy
changeset: 451033:8392e1c2f711
user:      roy <roy%NetBSD.org@localhost>
date:      Sat May 04 09:40:27 2019 +0000

description:
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 <max%m00nbsd.net@localhost> for discovering this issue.

diffstat:

 external/bsd/dhcpcd/dist/src/bpf.c        |   23 ++-
 external/bsd/dhcpcd/dist/src/defs.h       |    2 +-
 external/bsd/dhcpcd/dist/src/dhcp.c       |    7 +-
 external/bsd/dhcpcd/dist/src/dhcp6.c      |   48 ++++----
 external/bsd/dhcpcd/dist/src/dhcpcd.c     |   99 +++++------------
 external/bsd/dhcpcd/dist/src/dhcpcd.h     |    1 -
 external/bsd/dhcpcd/dist/src/if-bsd.c     |  143 ++++++++++++++++++--------
 external/bsd/dhcpcd/dist/src/if-linux.c   |    9 +
 external/bsd/dhcpcd/dist/src/if-options.c |    2 +-
 external/bsd/dhcpcd/dist/src/if-sun.c     |  160 +++++++++++++++++++----------
 external/bsd/dhcpcd/dist/src/if.c         |   72 ++++---------
 external/bsd/dhcpcd/dist/src/if.h         |    2 +-
 12 files changed, 312 insertions(+), 256 deletions(-)

diffs (truncated from 1144 to 300 lines):

diff -r a243c030c783 -r 8392e1c2f711 external/bsd/dhcpcd/dist/src/bpf.c
--- a/external/bsd/dhcpcd/dist/src/bpf.c        Fri Apr 26 14:32:27 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/bpf.c        Sat May 04 09:40:27 2019 +0000
@@ -301,6 +301,7 @@
 /* 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 @@
                 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 @@
        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 @@
        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 @@
 
        /* 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);
diff -r a243c030c783 -r 8392e1c2f711 external/bsd/dhcpcd/dist/src/defs.h
--- a/external/bsd/dhcpcd/dist/src/defs.h       Fri Apr 26 14:32:27 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/defs.h       Sat May 04 09:40:27 2019 +0000
@@ -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"
diff -r a243c030c783 -r 8392e1c2f711 external/bsd/dhcpcd/dist/src/dhcp.c
--- a/external/bsd/dhcpcd/dist/src/dhcp.c       Fri Apr 26 14:32:27 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcp.c       Sat May 04 09:40:27 2019 +0000
@@ -3499,9 +3499,14 @@
                        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
 }
diff -r a243c030c783 -r 8392e1c2f711 external/bsd/dhcpcd/dist/src/dhcp6.c
--- a/external/bsd/dhcpcd/dist/src/dhcp6.c      Fri Apr 26 14:32:27 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcp6.c      Sat May 04 09:40:27 2019 +0000
@@ -2166,40 +2166,38 @@
                        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;
+               }
+
+               /* 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--;
+               /* Check option length matches prefix length. */
+               if (((*o - a->prefix_len - 1) / NBBY) + 1 != ol) {
+                       logerrx("%s: PD Exclude length mismatch", ifp->name);
                        continue;
                }
                a->prefix_exclude_len = *o++;
-               ol--;
-               if (((a->prefix_exclude_len - 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;
+
                memcpy(&a->prefix_exclude, &a->prefix,
                    sizeof(a->prefix_exclude));
+               nb = a->prefix_len % NBBY;
                if (nb)
                        ol--;
                pw = a->prefix_exclude.s6_addr +
diff -r a243c030c783 -r 8392e1c2f711 external/bsd/dhcpcd/dist/src/dhcpcd.c
--- a/external/bsd/dhcpcd/dist/src/dhcpcd.c     Fri Apr 26 14:32:27 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcpcd.c     Sat May 04 09:40:27 2019 +0000
@@ -84,6 +84,9 @@
 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 @@
 }
 
 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 @@
            !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 @@
        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 @@
                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 @@
            )
                logerr("%s: %s", __func__, ifp->name);
 
-       if (ifp->options->options & DHCPCD_LINK &&
-           ifp->carrier == LINK_UNKNOWN)



Home | Main Index | Thread Index | Old Index