fix panics caused by replacing m_copym2 with m_dup_pkt.
authordlg <dlg@openbsd.org>
Thu, 18 Aug 2016 06:01:10 +0000 (06:01 +0000)
committerdlg <dlg@openbsd.org>
Thu, 18 Aug 2016 06:01:10 +0000 (06:01 +0000)
m_copym2 is fine duplicating an arbitrary chain of mbufs, while
m_dup_pkt wants to dup a packet with proper headers in the first
mbuf. ipsec copied the tail of an mbuf if any of the clusters are
shared or readonly, and swapped that tail with the result of m_copym2.

m_dup_pkt panics cos of that.

this makes ipsec duplicate the whole packet if any of the chain is
readonly.

found by naddy@ and mlarkin@
this fix is from visa@ who told me to commit it cos he's afk (sleeping)
tested by naddy@

sys/netinet/ip_ah.c
sys/netinet/ip_esp.c
sys/netinet/ip_ipcomp.c

index 1fc2c14..222a6ee 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ah.c,v 1.120 2016/08/15 11:35:25 dlg Exp $ */
+/*     $OpenBSD: ip_ah.c,v 1.121 2016/08/18 06:01:10 dlg Exp $ */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -929,7 +929,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
        struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
        struct cryptodesc *crda;
        struct tdb_crypto *tc;
-       struct mbuf *mo, *mi;
+       struct mbuf *mi;
        struct cryptop *crp;
        u_int16_t iplen;
        int len, rplen;
@@ -1037,18 +1037,14 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
 
        /*
         * Loop through mbuf chain; if we find a readonly mbuf,
-        * replace the rest of the chain.
+        * copy the packet.
         */
-       mo = NULL;
        mi = m;
-       while (mi != NULL && !M_READONLY(mi)) {
-               mo = mi;
+       while (mi != NULL && !M_READONLY(mi))
                mi = mi->m_next;
-       }
 
        if (mi != NULL) {
-               /* Replace the rest of the mbuf chain. */
-               struct mbuf *n = m_dup_pkt(mi, 0, M_DONTWAIT);
+               struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
 
                if (n == NULL) {
                        ahstat.ahs_hdrops++;
@@ -1056,12 +1052,8 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
                        return ENOBUFS;
                }
 
-               if (mo != NULL)
-                       mo->m_next = n;
-               else
-                       m = n;
-
-               m_freem(mi);
+               m_freem(m);
+               m = n;
        }
 
        /* Inject AH header. */
index 4b44c77..2c7b988 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_esp.c,v 1.138 2016/08/15 11:35:25 dlg Exp $ */
+/*     $OpenBSD: ip_esp.c,v 1.139 2016/08/18 06:01:10 dlg Exp $ */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -884,18 +884,14 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
 
        /*
         * Loop through mbuf chain; if we find a readonly mbuf,
-        * replace the rest of the chain.
+        * copy the packet.
         */
-       mo = NULL;
        mi = m;
-       while (mi != NULL && !M_READONLY(mi)) {
-               mo = mi;
+       while (mi != NULL && !M_READONLY(mi))
                mi = mi->m_next;
-       }
 
        if (mi != NULL) {
-               /* Replace the rest of the mbuf chain. */
-               struct mbuf *n = m_dup_pkt(mi, 0, M_DONTWAIT);
+               struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
 
                if (n == NULL) {
                        DPRINTF(("esp_output(): bad mbuf chain, SA %s/%08x\n",
@@ -906,12 +902,8 @@ esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
                        return ENOBUFS;
                }
 
-               if (mo != NULL)
-                       mo->m_next = n;
-               else
-                       m = n;
-
-               m_freem(mi);
+               m_freem(m);
+               m = n;
        }
 
        /* Inject ESP header. */
index 27bc2f3..120511b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipcomp.c,v 1.45 2016/08/15 11:35:25 dlg Exp $ */
+/* $OpenBSD: ip_ipcomp.c,v 1.46 2016/08/18 06:01:10 dlg Exp $ */
 
 /*
  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
@@ -373,7 +373,7 @@ ipcomp_output(m, tdb, mp, skip, protoff)
        struct cryptodesc *crdc = NULL;
        struct cryptop *crp;
        struct tdb_crypto *tc;
-       struct mbuf    *mi, *mo;
+       struct mbuf    *mi;
 #ifdef ENCDEBUG
        char buf[INET6_ADDRSTRLEN];
 #endif
@@ -462,18 +462,14 @@ ipcomp_output(m, tdb, mp, skip, protoff)
        }
        /*
         * Loop through mbuf chain; if we find a readonly mbuf,
-        * replace the rest of the chain.
+        * copy the packet.
         */
-       mo = NULL;
        mi = m;
-       while (mi != NULL && !M_READONLY(mi)) {
-               mo = mi;
+       while (mi != NULL && !M_READONLY(mi))
                mi = mi->m_next;
-       }
 
        if (mi != NULL) {
-               /* Replace the rest of the mbuf chain. */
-               struct mbuf    *n = m_dup_pkt(mi, 0, M_DONTWAIT);
+               struct mbuf *n = m_dup_pkt(m, 0, M_DONTWAIT);
 
                if (n == NULL) {
                        DPRINTF(("ipcomp_output(): bad mbuf chain, IPCA %s/%08x\n",
@@ -483,12 +479,9 @@ ipcomp_output(m, tdb, mp, skip, protoff)
                        m_freem(m);
                        return ENOBUFS;
                }
-               if (mo != NULL)
-                       mo->m_next = n;
-               else
-                       m = n;
 
-               m_freem(mi);
+               m_freem(m);
+               m = n;
        }
        /* Ok now, we can pass to the crypto processing */