untrusted comment: signature from openbsd 6.2 base secret key RWRVWzAMgtyg7vJlvmDDd4YkQ8dHlkKchVy8F3mVEZR6/hh8RqRKM/21wX1QkoSOfxIJpnD4J27x9anKibJgD46vhJSbTsUXmAc= OpenBSD 6.2 errata 003, December 10th, 2017: A number of bugs were discovered in the MPLS stack that can be used to remotely trigger kernel crashes. Apply by doing: signify -Vep /etc/signify/openbsd-62-base.pub -x 003_mpls.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/netmpls/mpls_input.c =================================================================== RCS file: /cvs/src/sys/netmpls/mpls_input.c,v retrieving revision 1.60 diff -u -p -r1.60 mpls_input.c --- sys/netmpls/mpls_input.c 30 May 2017 07:50:37 -0000 1.60 +++ sys/netmpls/mpls_input.c 8 Dec 2017 22:28:32 -0000 @@ -45,9 +45,9 @@ #define MPLS_TTL_GET(l) (ntohl((l) & MPLS_TTL_MASK)) #endif -int mpls_ip_adjttl(struct mbuf *, u_int8_t); +struct mbuf *mpls_ip_adjttl(struct mbuf *, u_int8_t); #ifdef INET6 -int mpls_ip6_adjttl(struct mbuf *, u_int8_t); +struct mbuf *mpls_ip6_adjttl(struct mbuf *, u_int8_t); #endif struct mbuf *mpls_do_error(struct mbuf *, int, int, int); @@ -60,19 +60,29 @@ mpls_input(struct mbuf *m) struct shim_hdr *shim; struct rtentry *rt; struct rt_mpls *rt_mpls; - struct ifnet *ifp = NULL; + struct ifnet *ifp; u_int8_t ttl; int hasbos; + if ((ifp = if_get(m->m_pkthdr.ph_ifidx)) == NULL || + !ISSET(ifp->if_xflags, IFXF_MPLS)) { + m_freem(m); + if_put(ifp); + return; + } + /* drop all broadcast and multicast packets */ if (m->m_flags & (M_BCAST | M_MCAST)) { m_freem(m); + if_put(ifp); return; } if (m->m_len < sizeof(*shim)) - if ((m = m_pullup(m, sizeof(*shim))) == NULL) + if ((m = m_pullup(m, sizeof(*shim))) == NULL) { + if_put(ifp); return; + } shim = mtod(m, struct shim_hdr *); @@ -88,8 +98,10 @@ mpls_input(struct mbuf *m) if (ttl-- <= 1) { /* TTL exceeded */ m = mpls_do_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0); - if (m == NULL) + if (m == NULL) { + if_put(ifp); return; + } shim = mtod(m, struct shim_hdr *); ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); } @@ -104,6 +116,10 @@ mpls_input(struct mbuf *m) if (ntohl(smpls->smpls_label) < MPLS_LABEL_RESERVED_MAX) { m = mpls_shim_pop(m); + if (m == NULL) { + if_put(ifp); + return; + } if (!hasbos) { /* * RFC 4182 relaxes the position of the @@ -119,11 +135,8 @@ mpls_input(struct mbuf *m) switch (ntohl(smpls->smpls_label)) { case MPLS_LABEL_IPV4NULL: do_v4: - if (mpls_ip_adjttl(m, ttl)) - return; - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) { - m_freem(m); + if ((m = mpls_ip_adjttl(m, ttl)) == NULL) { + if_put(ifp); return; } ipv4_input(ifp, m); @@ -132,11 +145,8 @@ do_v4: #ifdef INET6 case MPLS_LABEL_IPV6NULL: do_v6: - if (mpls_ip6_adjttl(m, ttl)) - return; - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) { - m_freem(m); + if ((m = mpls_ip6_adjttl(m, ttl)) == NULL) { + if_put(ifp); return; } ipv6_input(ifp, m); @@ -144,6 +154,11 @@ do_v6: return; #endif /* INET6 */ case MPLS_LABEL_IMPLNULL: + if (m->m_len < sizeof(u_char) && + (m = m_pullup(m, sizeof(u_char))) == NULL) { + if_put(ifp); + return; + } switch (*mtod(m, u_char *) >> 4) { case IPVERSION: goto do_v4; @@ -153,15 +168,19 @@ do_v6: #endif default: m_freem(m); + if_put(ifp); return; } default: /* Other cases are not handled for now */ m_freem(m); + if_put(ifp); return; } } } + if_put(ifp); + ifp = NULL; rt = rtalloc(smplstosa(smpls), RT_RESOLVE, m->m_pkthdr.ph_rtableid); if (rt == NULL) { @@ -185,6 +204,8 @@ do_v6: switch (rt_mpls->mpls_operation) { case MPLS_OP_POP: m = mpls_shim_pop(m); + if (m == NULL) + goto done; if (!hasbos) /* just forward to gw */ break; @@ -211,12 +232,12 @@ do_v6: switch(rt->rt_gateway->sa_family) { case AF_INET: - if (mpls_ip_adjttl(m, ttl)) + if ((m = mpls_ip_adjttl(m, ttl)) == NULL) goto done; break; #ifdef INET6 case AF_INET6: - if (mpls_ip6_adjttl(m, ttl)) + if ((m = mpls_ip6_adjttl(m, ttl)) == NULL) goto done; break; #endif @@ -278,7 +299,7 @@ done: rtfree(rt); } -int +struct mbuf * mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip *ip; @@ -287,18 +308,18 @@ mpls_ip_adjttl(struct mbuf *m, u_int8_t if (mpls_mapttl_ip) { if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) - return -1; + return NULL; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; if (m->m_len < hlen) { if ((m = m_pullup(m, hlen)) == NULL) - return -1; + return NULL; ip = mtod(m, struct ip *); } /* make sure we have a valid header */ if (in_cksum(m, hlen) != 0) { - m_free(m); - return -1; + m_freem(m); + return NULL; } /* set IP ttl from MPLS ttl */ @@ -308,11 +329,11 @@ mpls_ip_adjttl(struct mbuf *m, u_int8_t ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); } - return 0; + return m; } #ifdef INET6 -int +struct mbuf * mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip6_hdr *ip6hdr; @@ -320,14 +341,14 @@ mpls_ip6_adjttl(struct mbuf *m, u_int8_t if (mpls_mapttl_ip6) { if (m->m_len < sizeof(struct ip6_hdr) && (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) - return -1; + return NULL; ip6hdr = mtod(m, struct ip6_hdr *); /* set IPv6 ttl from MPLS ttl */ ip6hdr->ip6_hlim = ttl; } - return 0; + return m; } #endif /* INET6 */ @@ -346,7 +367,7 @@ mpls_do_error(struct mbuf *m, int type, for (nstk = 0; nstk < MPLS_INKERNEL_LOOP_MAX; nstk++) { if (m->m_len < sizeof(*shim) && - (m = m_pullup(m, sizeof(*ip))) == NULL) + (m = m_pullup(m, sizeof(*shim))) == NULL) return (NULL); stack[nstk] = *mtod(m, struct shim_hdr *); m_adj(m, sizeof(*shim)); @@ -355,6 +376,9 @@ mpls_do_error(struct mbuf *m, int type, } shim = &stack[0]; + if (m->m_len < sizeof(u_char) && + (m = m_pullup(m, sizeof(u_char))) == NULL) + return (NULL); switch (*mtod(m, u_char *) >> 4) { case IPVERSION: if (m->m_len < sizeof(*ip) &&