The adjttl functions use m_pullup(). In some cases m_pullup() can return
authorclaudio <claudio@openbsd.org>
Fri, 8 Dec 2017 21:56:22 +0000 (21:56 +0000)
committerclaudio <claudio@openbsd.org>
Fri, 8 Dec 2017 21:56:22 +0000 (21:56 +0000)
a new mbuf chain and this chain needs to be returned to the caller else
a use after free may happen.
Issue reported by Maxime Villard
OK bluhm@ deraadt@

sys/netmpls/mpls_input.c

index b8930cb..20c395e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mpls_input.c,v 1.62 2017/12/08 21:52:49 claudio Exp $ */
+/*     $OpenBSD: mpls_input.c,v 1.63 2017/12/08 21:56:22 claudio Exp $ */
 
 /*
  * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
@@ -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);
@@ -135,7 +135,7 @@ mpls_input(struct mbuf *m)
                        switch (ntohl(smpls->smpls_label)) {
                        case MPLS_LABEL_IPV4NULL:
 do_v4:
-                               if (mpls_ip_adjttl(m, ttl)) {
+                               if ((m = mpls_ip_adjttl(m, ttl)) == NULL) {
                                        if_put(ifp);
                                        return;
                                }
@@ -145,7 +145,7 @@ do_v4:
 #ifdef INET6
                        case MPLS_LABEL_IPV6NULL:
 do_v6:
-                               if (mpls_ip6_adjttl(m, ttl)) {
+                               if ((m = mpls_ip6_adjttl(m, ttl)) == NULL) {
                                        if_put(ifp);
                                        return;
                                }
@@ -227,12 +227,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
@@ -294,7 +294,7 @@ done:
        rtfree(rt);
 }
 
-int
+struct mbuf *
 mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
 {
        struct ip *ip;
@@ -303,18 +303,18 @@ mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
        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;
+                       return NULL;
                }
 
                /* set IP ttl from MPLS ttl */
@@ -324,11 +324,11 @@ mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
                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;
@@ -336,14 +336,14 @@ mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl)
        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 */