Source-Changes-HG archive

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

[src/trunk]: src/sys fix: gif(4) receive side race



details:   https://anonhg.NetBSD.org/src/rev/e51fd1c3ec93
branches:  trunk
changeset: 816402:e51fd1c3ec93
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Jul 04 04:22:47 2016 +0000

description:
fix: gif(4) receive side race

A panic cause in rn_match() called by encap[46]_lookup(). The reason is that
gif(4) does not suspend receive packet processing in spite of suspending
transmit packet processing while anyone is doing gif(4) ioctl.

diffstat:

 sys/net/if_gif.c       |  26 +++++++++++++++++++++++---
 sys/netinet/in_gif.c   |  20 +++++++++++++++-----
 sys/netinet/in_gif.h   |   3 ++-
 sys/netinet6/in6_gif.c |  18 ++++++++++++++----
 sys/netinet6/in6_gif.h |   3 ++-
 5 files changed, 56 insertions(+), 14 deletions(-)

diffs (168 lines):

diff -r fb335484ee3f -r e51fd1c3ec93 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Mon Jul 04 04:20:14 2016 +0000
+++ b/sys/net/if_gif.c  Mon Jul 04 04:22:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.115 2016/07/04 04:17:25 knakahara Exp $   */
+/*     $NetBSD: if_gif.c,v 1.116 2016/07/04 04:22:47 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.115 2016/07/04 04:17:25 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.116 2016/07/04 04:22:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -782,9 +782,29 @@
 static void
 gif_encap_pause(struct gif_softc *sc)
 {
-       struct ifnet *ifp = &sc->gif_if;
+       struct ifnet *ifp;
        uint64_t where;
 
+       if (sc == NULL || sc->gif_psrc == NULL)
+               return;
+
+       ifp = &sc->gif_if;
+       if ((ifp->if_flags & IFF_RUNNING) == 0)
+               return;
+
+       switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+       case AF_INET:
+               (void)in_gif_pause(sc);
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               (void)in6_gif_pause(sc);
+               break;
+#endif
+       }
+
        ifp->if_flags &= ~IFF_RUNNING;
        /* membar_sync() is done in xc_broadcast(). */
 
diff -r fb335484ee3f -r e51fd1c3ec93 sys/netinet/in_gif.c
--- a/sys/netinet/in_gif.c      Mon Jul 04 04:20:14 2016 +0000
+++ b/sys/netinet/in_gif.c      Mon Jul 04 04:22:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_gif.c,v 1.77 2016/07/04 04:14:47 knakahara Exp $    */
+/*     $NetBSD: in_gif.c,v 1.78 2016/07/04 04:22:47 knakahara Exp $    */
 /*     $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.77 2016/07/04 04:14:47 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.78 2016/07/04 04:22:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -390,11 +390,21 @@
 {
        int error;
 
-       error = encap_detach(sc->encap_cookie4);
-       if (error == 0)
-               sc->encap_cookie4 = NULL;
+       error = in_gif_pause(sc);
 
        rtcache_free(&sc->gif_ro);
 
        return error;
 }
+
+int
+in_gif_pause(struct gif_softc *sc)
+{
+       int error;
+
+       error = encap_detach(sc->encap_cookie4);
+       if (error == 0)
+               sc->encap_cookie4 = NULL;
+
+       return error;
+}
diff -r fb335484ee3f -r e51fd1c3ec93 sys/netinet/in_gif.h
--- a/sys/netinet/in_gif.h      Mon Jul 04 04:20:14 2016 +0000
+++ b/sys/netinet/in_gif.h      Mon Jul 04 04:22:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_gif.h,v 1.15 2016/01/26 06:00:10 knakahara Exp $    */
+/*     $NetBSD: in_gif.h,v 1.16 2016/07/04 04:22:47 knakahara Exp $    */
 /*     $KAME: in_gif.h,v 1.6 2001/07/25 00:55:48 itojun Exp $  */
 
 /*
@@ -45,5 +45,6 @@
 #endif
 int in_gif_attach(struct gif_softc *);
 int in_gif_detach(struct gif_softc *);
+int in_gif_pause(struct gif_softc *);
 
 #endif /* !_NETINET_IN_GIF_H_ */
diff -r fb335484ee3f -r e51fd1c3ec93 sys/netinet6/in6_gif.c
--- a/sys/netinet6/in6_gif.c    Mon Jul 04 04:20:14 2016 +0000
+++ b/sys/netinet6/in6_gif.c    Mon Jul 04 04:22:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_gif.c,v 1.76 2016/07/04 04:14:47 knakahara Exp $   */
+/*     $NetBSD: in6_gif.c,v 1.77 2016/07/04 04:22:47 knakahara Exp $   */
 /*     $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $        */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.76 2016/07/04 04:14:47 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.77 2016/07/04 04:22:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -391,12 +391,22 @@
 {
        int error;
 
+       error = in6_gif_pause(sc);
+
+       rtcache_free(&sc->gif_ro);
+
+       return error;
+}
+
+int
+in6_gif_pause(struct gif_softc *sc)
+{
+       int error;
+
        error = encap_detach(sc->encap_cookie6);
        if (error == 0)
                sc->encap_cookie6 = NULL;
 
-       rtcache_free(&sc->gif_ro);
-
        return error;
 }
 
diff -r fb335484ee3f -r e51fd1c3ec93 sys/netinet6/in6_gif.h
--- a/sys/netinet6/in6_gif.h    Mon Jul 04 04:20:14 2016 +0000
+++ b/sys/netinet6/in6_gif.h    Mon Jul 04 04:22:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_gif.h,v 1.14 2016/02/26 07:35:17 knakahara Exp $   */
+/*     $NetBSD: in6_gif.h,v 1.15 2016/07/04 04:22:47 knakahara Exp $   */
 /*     $KAME: in6_gif.h,v 1.7 2001/07/26 06:53:16 jinmei Exp $ */
 
 /*
@@ -45,6 +45,7 @@
 #endif
 int in6_gif_attach(struct gif_softc *);
 int in6_gif_detach(struct gif_softc *);
+int in6_gif_pause(struct gif_softc *);
 void *in6_gif_ctlinput(int, const struct sockaddr *, void *, void *);
 
 #endif /* !_NETINET6_IN6_GIF_H_ */



Home | Main Index | Thread Index | Old Index