Source-Changes-HG archive

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

[src/trunk]: src/sys/net gif(4): Infinite recursion calls prevention code wor...



details:   https://anonhg.NetBSD.org/src/rev/4f57df594634
branches:  trunk
changeset: 342059:4f57df594634
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Fri Dec 04 02:26:11 2015 +0000

description:
gif(4): Infinite recursion calls prevention code works again now.

The prevention code haven't worked since gif(4) was changed
to use softint(9). To work this prevention, git_output uses
m_tag(9) like FreeBSD and OpenBSD.

I tested with following code.
====================
# ifconfig gif0 create
# ifconfig gif0 tunnel 10.1.1.1  10.1.1.2
# ifconfig gif0 inet 192.168.100.1 192.168.100.100

# ifconfig gif1 create
# ifconfig gif1 tunnel 192.168.100.1 192.168.100.100
# ifconfig gif1 inet 192.168.101.1 192.168.101.101

# ifconfig gif2 create
# ifconfig gif2 tunnel 192.168.101.1 192.168.101.101
# ifconfig gif2 inet 192.168.102.1 192.168.102.102

# ping -w 1 -c 1 192.168.102.102
# dmesg | tail -n 1
gif0: recursively called too many times(2)
====================

diffstat:

 sys/net/if_gif.c |  59 +++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 42 insertions(+), 17 deletions(-)

diffs (105 lines):

diff -r 0d0fe08807ab -r 4f57df594634 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Fri Dec 04 01:47:48 2015 +0000
+++ b/sys/net/if_gif.c  Fri Dec 04 02:26:11 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.94 2015/12/03 03:03:58 knakahara Exp $    */
+/*     $NetBSD: if_gif.c,v 1.95 2015/12/04 02:26:11 knakahara Exp $    */
 /*     $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $    */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.94 2015/12/03 03:03:58 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.95 2015/12/04 02:26:11 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -94,6 +94,7 @@
 
 static int     gif_clone_create(struct if_clone *, int);
 static int     gif_clone_destroy(struct ifnet *);
+static int     gif_check_nesting(struct ifnet *, struct mbuf *);
 
 static struct if_clone gif_cloner =
     IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
@@ -233,31 +234,56 @@
 }
 #endif
 
+/*
+ * gif may cause infinite recursion calls when misconfigured.
+ * We'll prevent this by introducing upper limit.
+ */
+static int
+gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
+{
+       struct m_tag *mtag;
+       int *count;
+
+       mtag = m_tag_find(m, PACKET_TAG_TUNNEL_INFO, NULL);
+       if (mtag != NULL) {
+               count = (int *)(mtag + 1);
+               if (++(*count) > max_gif_nesting) {
+                       log(LOG_NOTICE,
+                           "%s: recursively called too many times(%d)\n",
+                           if_name(ifp),
+                           *count);
+                       return EIO;
+               }
+       } else {
+               mtag = m_tag_get(PACKET_TAG_TUNNEL_INFO, sizeof(*count),
+                   M_NOWAIT);
+               if (mtag != NULL) {
+                       m_tag_prepend(m, mtag);
+                       count = (int *)(mtag + 1);
+                       *count = 0;
+               } else {
+                       log(LOG_DEBUG,
+                           "%s: m_tag_get() failed, recursion calls are not prevented.\n",
+                           if_name(ifp));
+               }
+       }
+
+       return 0;
+}
+
 int
 gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
     struct rtentry *rt)
 {
        struct gif_softc *sc = ifp->if_softc;
        int error = 0;
-       static int called = 0;  /* XXX: MUTEX */
        ALTQ_DECL(struct altq_pktattr pktattr;)
        int s;
 
        IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
 
-       /*
-        * gif may cause infinite recursion calls when misconfigured.
-        * We'll prevent this by introducing upper limit.
-        * XXX: this mechanism may introduce another problem about
-        *      mutual exclusion of the variable CALLED, especially if we
-        *      use kernel thread.
-        */
-       if (++called > max_gif_nesting) {
-               log(LOG_NOTICE,
-                   "gif_output: recursively called too many times(%d)\n",
-                   called);
-               m_freem(m);
-               error = EIO;    /* is there better errno? */
+       if ((error = gif_check_nesting(ifp, m)) != 0) {
+               m_free(m);
                goto end;
        }
 
@@ -295,7 +321,6 @@
        error = 0;
 
   end:
-       called = 0;             /* reset recursion counter */
        if (error)
                ifp->if_oerrors++;
        return error;



Home | Main Index | Thread Index | Old Index