aboutsummaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorAndrey V. Elsukov <ae@FreeBSD.org>2018-07-09 11:03:28 +0000
committerAndrey V. Elsukov <ae@FreeBSD.org>2018-07-09 11:03:28 +0000
commit98a8fdf6dac8aa5c28a3ac6640a1020bbd7a28da (patch)
treec11f5f87210b66df9470574aa6fc69041276361e /sys/net
parentd50fbe3fe2e7918d3649eba32c470a0f32e240ce (diff)
downloadsrc-98a8fdf6dac8aa5c28a3ac6640a1020bbd7a28da.tar.gz
src-98a8fdf6dac8aa5c28a3ac6640a1020bbd7a28da.zip
Notes
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c38
-rw-r--r--sys/net/if_gif.c41
-rw-r--r--sys/net/if_gre.c34
-rw-r--r--sys/net/if_me.c34
-rw-r--r--sys/net/if_var.h1
5 files changed, 48 insertions, 100 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 8448de8bd09e..f398bc1075c0 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -3903,6 +3903,44 @@ if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
}
/*
+ * 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
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 3293ded9dbbd..415409610500 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -104,7 +104,6 @@ void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
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,
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index aa9672d2bee1..2ef1a35497b2 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -503,36 +503,6 @@ 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;
}
diff --git a/sys/net/if_me.c b/sys/net/if_me.c
index 534d7030a8f5..aa2e305fec29 100644
--- a/sys/net/if_me.c
+++ b/sys/net/if_me.c
@@ -455,36 +455,6 @@ 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 struct sockaddr *dst,
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;
}
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 43893b401545..6a7443b5f7fb 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -644,6 +644,7 @@ int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
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);