Source-Changes-HG archive

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

[src/netbsd-8]: src/sys Pull up following revision(s) (requested by knakahara...



details:   https://anonhg.NetBSD.org/src/rev/80dc79d005ce
branches:  netbsd-8
changeset: 851455:80dc79d005ce
user:      martin <martin%NetBSD.org@localhost>
date:      Thu Mar 08 13:41:40 2018 +0000

description:
Pull up following revision(s) (requested by knakahara in ticket #614):
        sys/net/if_l2tp.c: revision 1.20
        sys/netinet6/in6_l2tp.c: revision 1.13
        sys/netinet6/in6_l2tp.c: revision 1.14
        sys/net/if_l2tp.h: revision 1.3
        sys/net/if_l2tp.c: revision 1.13
        sys/netinet/in_l2tp.c: revision 1.10
        sys/net/if_l2tp.c: revision 1.18
        sys/netinet/in_l2tp.c: revision 1.11
        sys/net/if_l2tp.c: revision 1.19
        sys/netinet/in_l2tp.c: revision 1.12

If if_attach() failed in the attach function, return. Add comments about if_initialize().
suggested by ozaki-r@n.o.

Fix null deref, m could be NULL if M_PREPEND fails.

style

Style, reduce the indentation level when possible, and add a missing NULL
check after M_PREPEND.

Several fixes in L2TP:
 * l2tp_input(): use m_copydata, and ensure there is enough space in the
   chain. Otherwise overflow.
 * l2tp_tcpmss_clamp(): ensure there is enough space in the chain.
 * in_l2tp_output(): don't check 'sc' against NULL, it can't be NULL.
 * in_l2tp_input(): no need to call m_pullup since we use m_copydata.
   Just check the space in the chain.
 * in_l2tp_input(): if there is a cookie, make sure the chain has enough
   space.
 * in6_l2tp_input(): same changes as in_l2tp_input().
Ok knakahara@

Use MH_ALIGN instead, ok knakahara@.

diffstat:

 sys/net/if_l2tp.c       |  177 ++++++++++++++++++++++++++++-------------------
 sys/net/if_l2tp.h       |    4 +-
 sys/netinet/in_l2tp.c   |  106 ++++++++++++++--------------
 sys/netinet6/in6_l2tp.c |  102 ++++++++++++++-------------
 4 files changed, 212 insertions(+), 177 deletions(-)

diffs (truncated from 683 to 300 lines):

diff -r def85952a655 -r 80dc79d005ce sys/net/if_l2tp.c
--- a/sys/net/if_l2tp.c Thu Mar 08 13:22:25 2018 +0000
+++ b/sys/net/if_l2tp.c Thu Mar 08 13:41:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_l2tp.c,v 1.11.2.4 2018/02/11 21:17:34 snj Exp $     */
+/*     $NetBSD: if_l2tp.c,v 1.11.2.5 2018/03/08 13:41:40 martin Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_l2tp.c,v 1.11.2.4 2018/02/11 21:17:34 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_l2tp.c,v 1.11.2.5 2018/03/08 13:41:40 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -228,10 +228,17 @@
 {
        struct l2tp_softc *sc;
        struct l2tp_variant *var;
+       int rv;
 
        sc = kmem_zalloc(sizeof(struct l2tp_softc), KM_SLEEP);
+       if_initname(&sc->l2tp_ec.ec_if, ifc->ifc_name, unit);
+       rv = l2tpattach0(sc);
+       if (rv != 0) {
+               kmem_free(sc, sizeof(struct l2tp_softc));
+               return rv;
+       }
+
        var = kmem_zalloc(sizeof(struct l2tp_variant), KM_SLEEP);
-
        var->lv_softc = sc;
        var->lv_state = L2TP_STATE_DOWN;
        var->lv_use_cookie = L2TP_COOKIE_OFF;
@@ -241,10 +248,6 @@
        mutex_init(&sc->l2tp_lock, MUTEX_DEFAULT, IPL_NONE);
        PSLIST_ENTRY_INIT(sc, l2tp_hash);
 
-       if_initname(&sc->l2tp_ec.ec_if, ifc->ifc_name, unit);
-
-       l2tpattach0(sc);
-
        sc->l2tp_ro_percpu = percpu_alloc(sizeof(struct l2tp_ro));
        percpu_foreach(sc->l2tp_ro_percpu, l2tp_ro_init_pc, NULL);
 
@@ -255,9 +258,10 @@
        return (0);
 }
 
-void
+int
 l2tpattach0(struct l2tp_softc *sc)
 {
+       int rv;
 
        sc->l2tp_ec.ec_if.if_addrlen = 0;
        sc->l2tp_ec.ec_if.if_mtu    = L2TP_MTU;
@@ -274,9 +278,19 @@
        sc->l2tp_ec.ec_if.if_transmit = l2tp_transmit;
        sc->l2tp_ec.ec_if._if_input = ether_input;
        IFQ_SET_READY(&sc->l2tp_ec.ec_if.if_snd);
-       if_attach(&sc->l2tp_ec.ec_if);
+       /* XXX
+        * It may improve performance to use if_initialize()/if_register()
+        * so that l2tp_input() calls if_input() instead of
+        * if_percpuq_enqueue(). However, that causes recursive softnet_lock
+        * when NET_MPSAFE is not set.
+        */
+       rv = if_attach(&sc->l2tp_ec.ec_if);
+       if (rv != 0)
+               return rv;
        if_alloc_sadl(&sc->l2tp_ec.ec_if);
        bpf_attach(&sc->l2tp_ec.ec_if, DLT_EN10MB, sizeof(struct ether_header));
+
+       return 0;
 }
 
 void
@@ -451,16 +465,23 @@
 void
 l2tp_input(struct mbuf *m, struct ifnet *ifp)
 {
+       u_long val;
 
        KASSERT(ifp != NULL);
 
-       if (0 == (mtod(m, u_long) & 0x03)) {
+       if (m->m_pkthdr.len < sizeof(val)) {
+               m_freem(m);
+               return;
+       }
+
+       m_copydata(m, 0, sizeof(val), &val);
+
+       if ((val & 0x03) == 0) {
                /* copy and align head of payload */
                struct mbuf *m_head;
                int copy_length;
 
 #define L2TP_COPY_LENGTH               60
-#define L2TP_LINK_HDR_ROOM     (MHLEN - L2TP_COPY_LENGTH - 4/*round4(2)*/)
 
                if (m->m_pkthdr.len < L2TP_COPY_LENGTH) {
                        copy_length = m->m_pkthdr.len;
@@ -481,19 +502,19 @@
                }
                M_COPY_PKTHDR(m_head, m);
 
-               m_head->m_data += 2 /* align */ + L2TP_LINK_HDR_ROOM;
-               memcpy(m_head->m_data, m->m_data, copy_length);
+               MH_ALIGN(m_head, L2TP_COPY_LENGTH);
+               memcpy(mtod(m_head, void *), mtod(m, void *), copy_length);
                m_head->m_len = copy_length;
                m->m_data += copy_length;
                m->m_len -= copy_length;
 
                /* construct chain */
                if (m->m_len == 0) {
-                       m_head->m_next = m_free(m); /* not m_freem */
+                       m_head->m_next = m_free(m);
                } else {
                        /*
-                        * copyed mtag in previous call M_COPY_PKTHDR
-                        * but don't delete mtag in case cutt of M_PKTHDR flag
+                        * Already copied mtag with M_COPY_PKTHDR.
+                        * but don't delete mtag in case cut off M_PKTHDR flag
                         */
                        m_tag_delete_chain(m, NULL);
                        m->m_flags &= ~M_PKTHDR;
@@ -1352,80 +1373,90 @@
 #endif
 
 struct mbuf *
-l2tp_tcpmss_clamp(struct ifnet *ifp, struct mbuf       *m)
+l2tp_tcpmss_clamp(struct ifnet *ifp, struct mbuf *m)
 {
+       struct ether_header *eh;
+       struct ether_vlan_header evh;
 
-       if (l2tp_need_tcpmss_clamp(ifp)) {
-               struct ether_header *eh;
-               struct ether_vlan_header evh;
+       if (!l2tp_need_tcpmss_clamp(ifp)) {
+               return m;
+       }
 
-               /* save ether header */
-               m_copydata(m, 0, sizeof(evh), (void *)&evh);
-               eh = (struct ether_header *)&evh;
+       if (m->m_pkthdr.len < sizeof(evh)) {
+               m_freem(m);
+               return NULL;
+       }
 
-               switch (ntohs(eh->ether_type)) {
-               case ETHERTYPE_VLAN: /* Ether + VLAN */
-                       if (m->m_pkthdr.len <= sizeof(struct ether_vlan_header))
-                               break;
-                       m_adj(m, sizeof(struct ether_vlan_header));
-                       switch (ntohs(evh.evl_proto)) {
+       /* save ether header */
+       m_copydata(m, 0, sizeof(evh), (void *)&evh);
+       eh = (struct ether_header *)&evh;
+
+       switch (ntohs(eh->ether_type)) {
+       case ETHERTYPE_VLAN: /* Ether + VLAN */
+               if (m->m_pkthdr.len <= sizeof(struct ether_vlan_header))
+                       break;
+               m_adj(m, sizeof(struct ether_vlan_header));
+               switch (ntohs(evh.evl_proto)) {
 #ifdef INET
-                       case ETHERTYPE_IP: /* Ether + VLAN + IPv4 */
-                               m = l2tp_tcpmss4_clamp(ifp, m);
-                               if (m == NULL)
-                                       return NULL;
-                               break;
-#endif /* INET */
-#ifdef INET6
-                       case ETHERTYPE_IPV6: /* Ether + VLAN + IPv6 */
-                               m = l2tp_tcpmss6_clamp(ifp, m);
-                               if (m == NULL)
-                                       return NULL;
-                               break;
-#endif /* INET6 */
-                       default:
-                               break;
-                       }
-                       /* restore ether header */
-                       M_PREPEND(m, sizeof(struct ether_vlan_header),
-                           M_DONTWAIT);
-                       if (m == NULL)
-                               return NULL;
-                       *mtod(m, struct ether_vlan_header *) = evh;
-                       break;
-#ifdef INET
-               case ETHERTYPE_IP: /* Ether + IPv4 */
-                       if (m->m_pkthdr.len <= sizeof(struct ether_header))
-                               break;
-                       m_adj(m, sizeof(struct ether_header));
+               case ETHERTYPE_IP: /* Ether + VLAN + IPv4 */
                        m = l2tp_tcpmss4_clamp(ifp, m);
                        if (m == NULL)
                                return NULL;
-                       /* restore ether header */
-                       M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
-                       if (m == NULL)
-                               return NULL;
-                       *mtod(m, struct ether_header *) = *eh;
                        break;
 #endif /* INET */
 #ifdef INET6
-               case ETHERTYPE_IPV6: /* Ether + IPv6 */
-                       if (m->m_pkthdr.len <= sizeof(struct ether_header))
-                               break;
-                       m_adj(m, sizeof(struct ether_header));
+               case ETHERTYPE_IPV6: /* Ether + VLAN + IPv6 */
                        m = l2tp_tcpmss6_clamp(ifp, m);
                        if (m == NULL)
                                return NULL;
-                       /* restore ether header */
-                       M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
-                       if (m == NULL)
-                               return NULL;
-                       *mtod(m, struct ether_header *) = *eh;
                        break;
 #endif /* INET6 */
                default:
                        break;
                }
+
+               /* restore ether header */
+               M_PREPEND(m, sizeof(struct ether_vlan_header),
+                   M_DONTWAIT);
+               if (m == NULL)
+                       return NULL;
+               *mtod(m, struct ether_vlan_header *) = evh;
+               break;
+
+#ifdef INET
+       case ETHERTYPE_IP: /* Ether + IPv4 */
+               if (m->m_pkthdr.len <= sizeof(struct ether_header))
+                       break;
+               m_adj(m, sizeof(struct ether_header));
+               m = l2tp_tcpmss4_clamp(ifp, m);
+               if (m == NULL)
+                       return NULL;
+               /* restore ether header */
+               M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+               if (m == NULL)
+                       return NULL;
+               *mtod(m, struct ether_header *) = *eh;
+               break;
+#endif /* INET */
+
+#ifdef INET6
+       case ETHERTYPE_IPV6: /* Ether + IPv6 */
+               if (m->m_pkthdr.len <= sizeof(struct ether_header))
+                       break;
+               m_adj(m, sizeof(struct ether_header));
+               m = l2tp_tcpmss6_clamp(ifp, m);
+               if (m == NULL)
+                       return NULL;
+               /* restore ether header */
+               M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+               if (m == NULL)
+                       return NULL;
+               *mtod(m, struct ether_header *) = *eh;
+               break;
+#endif /* INET6 */
+
+       default:
+               break;
        }
 
        return m;
@@ -1439,12 +1470,12 @@
 #ifdef INET
        if (ifp->if_tcpmss != 0)
                ret = 1;
-#endif /* INET */
+#endif
 
 #ifdef INET6
        if (ifp->if_tcpmss6 != 0)
                ret = 1;
-#endif /* INET6 */
+#endif
 
        return ret;
 }
diff -r def85952a655 -r 80dc79d005ce sys/net/if_l2tp.h
--- a/sys/net/if_l2tp.h Thu Mar 08 13:22:25 2018 +0000
+++ b/sys/net/if_l2tp.h Thu Mar 08 13:41:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_l2tp.h,v 1.2 2017/05/31 08:19:44 knakahara Exp $    */
+/*     $NetBSD: if_l2tp.h,v 1.2.2.1 2018/03/08 13:41:40 martin Exp $   */
 



Home | Main Index | Thread Index | Old Index