svn commit: r336131 - head/sys/net

Andrey V. Elsukov ae at FreeBSD.org
Mon Jul 9 11:03:30 UTC 2018


Author: ae
Date: Mon Jul  9 11:03:28 2018
New Revision: 336131
URL: https://svnweb.freebsd.org/changeset/base/336131

Log:
  Deduplicate the code.
  
  Add generic function if_tunnel_check_nesting() that does check for
  allowed nesting level for tunneling interfaces and also does loop
  detection. Use it in gif(4), gre(4) and me(4) interfaces.
  
  Differential Revision:	https://reviews.freebsd.org/D16162

Modified:
  head/sys/net/if.c
  head/sys/net/if_gif.c
  head/sys/net/if_gre.c
  head/sys/net/if_me.c
  head/sys/net/if_var.h

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c	Mon Jul  9 09:00:16 2018	(r336130)
+++ head/sys/net/if.c	Mon Jul  9 11:03:28 2018	(r336131)
@@ -3903,6 +3903,44 @@ if_requestencap_default(struct ifnet *ifp, struct if_e
 }
 
 /*
+ * Tunnel interfaces can nest, also they may cause infinite recursion
+ * calls when misconfigured. We'll prevent this by detecting loops.
+ * High nesting level may cause stack exhaustion. We'll prevent this
+ * by introducing upper limit.
+ *
+ * Return 0, if tunnel nesting count is equal or less than limit.
+ */
+int
+if_tunnel_check_nesting(struct ifnet *ifp, struct mbuf *m, uint32_t cookie,
+    int limit)
+{
+	struct m_tag *mtag;
+	int count;
+
+	count = 1;
+	mtag = NULL;
+	while ((mtag = m_tag_locate(m, cookie, 0, mtag)) != NULL) {
+		if (*(struct ifnet **)(mtag + 1) == ifp) {
+			log(LOG_NOTICE, "%s: loop detected\n", if_name(ifp));
+			return (EIO);
+		}
+		count++;
+	}
+	if (count > limit) {
+		log(LOG_NOTICE,
+		    "%s: if_output recursively called too many times(%d)\n",
+		    if_name(ifp), count);
+		return (EIO);
+	}
+	mtag = m_tag_alloc(cookie, 0, sizeof(struct ifnet *), M_NOWAIT);
+	if (mtag == NULL)
+		return (ENOMEM);
+	*(struct ifnet **)(mtag + 1) = ifp;
+	m_tag_prepend(m, mtag);
+	return (0);
+}
+
+/*
  * Get the link layer address that was read from the hardware at attach.
  *
  * This is only set by Ethernet NICs (IFT_ETHER), but laggX interfaces re-type

Modified: head/sys/net/if_gif.c
==============================================================================
--- head/sys/net/if_gif.c	Mon Jul  9 09:00:16 2018	(r336130)
+++ head/sys/net/if_gif.c	Mon Jul  9 11:03:28 2018	(r336131)
@@ -104,7 +104,6 @@ void	(*ng_gif_input_orphan_p)(struct ifnet *ifp, struc
 void	(*ng_gif_attach_p)(struct ifnet *ifp);
 void	(*ng_gif_detach_p)(struct ifnet *ifp);
 
-static int	gif_check_nesting(struct ifnet *, struct mbuf *);
 static void	gif_delete_tunnel(struct gif_softc *);
 static int	gif_ioctl(struct ifnet *, u_long, caddr_t);
 static int	gif_transmit(struct ifnet *, struct mbuf *);
@@ -256,6 +255,7 @@ gif_hashdestroy(struct gif_list *hash)
 	free(hash, M_GIF);
 }
 
+#define	MTAG_GIF	1080679712
 static int
 gif_transmit(struct ifnet *ifp, struct mbuf *m)
 {
@@ -285,7 +285,8 @@ gif_transmit(struct ifnet *ifp, struct mbuf *m)
 	if ((ifp->if_flags & IFF_MONITOR) != 0 ||
 	    (ifp->if_flags & IFF_UP) == 0 ||
 	    sc->gif_family == 0 ||
-	    (error = gif_check_nesting(ifp, m)) != 0) {
+	    (error = if_tunnel_check_nesting(ifp, m, MTAG_GIF,
+		V_max_gif_nesting)) != 0) {
 		m_freem(m);
 		goto err;
 	}
@@ -378,42 +379,6 @@ gif_qflush(struct ifnet *ifp __unused)
 
 }
 
-#define	MTAG_GIF	1080679712
-static int
-gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
-{
-	struct m_tag *mtag;
-	int count;
-
-	/*
-	 * gif may cause infinite recursion calls when misconfigured.
-	 * We'll prevent this by detecting loops.
-	 *
-	 * High nesting level may cause stack exhaustion.
-	 * We'll prevent this by introducing upper limit.
-	 */
-	count = 1;
-	mtag = NULL;
-	while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) {
-		if (*(struct ifnet **)(mtag + 1) == ifp) {
-			log(LOG_NOTICE, "%s: loop detected\n", if_name(ifp));
-			return (EIO);
-		}
-		count++;
-	}
-	if (count > V_max_gif_nesting) {
-		log(LOG_NOTICE,
-		    "%s: if_output recursively called too many times(%d)\n",
-		    if_name(ifp), count);
-		return (EIO);
-	}
-	mtag = m_tag_alloc(MTAG_GIF, 0, sizeof(struct ifnet *), M_NOWAIT);
-	if (mtag == NULL)
-		return (ENOMEM);
-	*(struct ifnet **)(mtag + 1) = ifp;
-	m_tag_prepend(m, mtag);
-	return (0);
-}
 
 int
 gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,

Modified: head/sys/net/if_gre.c
==============================================================================
--- head/sys/net/if_gre.c	Mon Jul  9 09:00:16 2018	(r336130)
+++ head/sys/net/if_gre.c	Mon Jul  9 11:03:28 2018	(r336131)
@@ -503,37 +503,7 @@ drop:
 	return (IPPROTO_DONE);
 }
 
-#define	MTAG_GRE	1307983903
 static int
-gre_check_nesting(struct ifnet *ifp, struct mbuf *m)
-{
-	struct m_tag *mtag;
-	int count;
-
-	count = 1;
-	mtag = NULL;
-	while ((mtag = m_tag_locate(m, MTAG_GRE, 0, mtag)) != NULL) {
-		if (*(struct ifnet **)(mtag + 1) == ifp) {
-			log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
-			return (EIO);
-		}
-		count++;
-	}
-	if (count > V_max_gre_nesting) {
-		log(LOG_NOTICE,
-		    "%s: if_output recursively called too many times(%d)\n",
-		    ifp->if_xname, count);
-		return (EIO);
-	}
-	mtag = m_tag_alloc(MTAG_GRE, 0, sizeof(struct ifnet *), M_NOWAIT);
-	if (mtag == NULL)
-		return (ENOMEM);
-	*(struct ifnet **)(mtag + 1) = ifp;
-	m_tag_prepend(m, mtag);
-	return (0);
-}
-
-static int
 gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    struct route *ro)
 {
@@ -569,6 +539,7 @@ gre_setseqn(struct grehdr *gh, uint32_t seq)
 	*opts = htonl(seq);
 }
 
+#define	MTAG_GRE	1307983903
 static int
 gre_transmit(struct ifnet *ifp, struct mbuf *m)
 {
@@ -592,7 +563,8 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m)
 	if ((ifp->if_flags & IFF_MONITOR) != 0 ||
 	    (ifp->if_flags & IFF_UP) == 0 ||
 	    sc->gre_family == 0 ||
-	    (error = gre_check_nesting(ifp, m)) != 0) {
+	    (error = if_tunnel_check_nesting(ifp, m, MTAG_GRE,
+		V_max_gre_nesting)) != 0) {
 		m_freem(m);
 		goto drop;
 	}

Modified: head/sys/net/if_me.c
==============================================================================
--- head/sys/net/if_me.c	Mon Jul  9 09:00:16 2018	(r336130)
+++ head/sys/net/if_me.c	Mon Jul  9 11:03:28 2018	(r336131)
@@ -455,37 +455,7 @@ drop:
 	return (IPPROTO_DONE);
 }
 
-#define	MTAG_ME	1414491977
 static int
-me_check_nesting(struct ifnet *ifp, struct mbuf *m)
-{
-	struct m_tag *mtag;
-	int count;
-
-	count = 1;
-	mtag = NULL;
-	while ((mtag = m_tag_locate(m, MTAG_ME, 0, mtag)) != NULL) {
-		if (*(struct ifnet **)(mtag + 1) == ifp) {
-			log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
-			return (EIO);
-		}
-		count++;
-	}
-	if (count > V_max_me_nesting) {
-		log(LOG_NOTICE,
-		    "%s: if_output recursively called too many times(%d)\n",
-		    ifp->if_xname, count);
-		return (EIO);
-	}
-	mtag = m_tag_alloc(MTAG_ME, 0, sizeof(struct ifnet *), M_NOWAIT);
-	if (mtag == NULL)
-		return (ENOMEM);
-	*(struct ifnet **)(mtag + 1) = ifp;
-	m_tag_prepend(m, mtag);
-	return (0);
-}
-
-static int
 me_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    struct route *ro __unused)
 {
@@ -499,6 +469,7 @@ me_output(struct ifnet *ifp, struct mbuf *m, const str
 	return (ifp->if_transmit(ifp, m));
 }
 
+#define	MTAG_ME	1414491977
 static int
 me_transmit(struct ifnet *ifp, struct mbuf *m)
 {
@@ -519,7 +490,8 @@ me_transmit(struct ifnet *ifp, struct mbuf *m)
 	if (sc == NULL || !ME_READY(sc) ||
 	    (ifp->if_flags & IFF_MONITOR) != 0 ||
 	    (ifp->if_flags & IFF_UP) == 0 ||
-	    (error = me_check_nesting(ifp, m) != 0)) {
+	    (error = if_tunnel_check_nesting(ifp, m, MTAG_ME,
+		V_max_me_nesting)) != 0) {
 		m_freem(m);
 		goto drop;
 	}

Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h	Mon Jul  9 09:00:16 2018	(r336130)
+++ head/sys/net/if_var.h	Mon Jul  9 11:03:28 2018	(r336131)
@@ -644,6 +644,7 @@ int	if_printf(struct ifnet *, const char *, ...) __pri
 void	if_ref(struct ifnet *);
 void	if_rele(struct ifnet *);
 int	if_setlladdr(struct ifnet *, const u_char *, int);
+int	if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int);
 void	if_up(struct ifnet *);
 int	ifioctl(struct socket *, u_long, caddr_t, struct thread *);
 int	ifpromisc(struct ifnet *, int);


More information about the svn-src-all mailing list