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) &&