Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet6 Fix racy in6m_sol



details:   https://anonhg.NetBSD.org/src/rev/6707fbb67df4
branches:  trunk
changeset: 822122:6707fbb67df4
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu Mar 02 09:16:46 2017 +0000

description:
Fix racy in6m_sol

Relook up the entry instead of reusing it, which makes locking simple.

diffstat:

 sys/netinet6/in6.c     |  54 +++++++++++++++++++++++++++++++++----------------
 sys/netinet6/in6_var.h |   4 ++-
 sys/netinet6/mld6.c    |  18 ++++++++++++++-
 3 files changed, 55 insertions(+), 21 deletions(-)

diffs (181 lines):

diff -r 3056c3017082 -r 6707fbb67df4 sys/netinet6/in6.c
--- a/sys/netinet6/in6.c        Thu Mar 02 05:35:01 2017 +0000
+++ b/sys/netinet6/in6.c        Thu Mar 02 09:16:46 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6.c,v 1.242 2017/03/02 05:27:39 ozaki-r Exp $        */
+/*     $NetBSD: in6.c,v 1.243 2017/03/02 09:16:46 ozaki-r Exp $        */
 /*     $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $   */
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.242 2017/03/02 05:27:39 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.243 2017/03/02 09:16:46 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -779,8 +779,30 @@
 }
 
 static int
+in6_get_llsol_addr(struct in6_addr *llsol, struct ifnet *ifp,
+    struct in6_addr *ip6)
+{
+       int error;
+
+       memset(llsol, 0, sizeof(struct in6_addr));
+       llsol->s6_addr16[0] = htons(0xff02);
+       llsol->s6_addr32[1] = 0;
+       llsol->s6_addr32[2] = htonl(1);
+       llsol->s6_addr32[3] = ip6->s6_addr32[3];
+       llsol->s6_addr8[12] = 0xff;
+
+       error = in6_setscope(llsol, ifp, NULL);
+       if (error != 0) {
+               /* XXX: should not happen */
+               log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
+       }
+
+       return error;
+}
+
+static int
 in6_join_mcastgroups(struct in6_aliasreq *ifra, struct in6_ifaddr *ia,
-    struct ifnet *ifp, struct in6_multi **in6m_sol, int flags)
+    struct ifnet *ifp, int flags)
 {
        int error;
        struct sockaddr_in6 mltaddr, mltmask;
@@ -790,20 +812,10 @@
        int dad_delay;
        char ip6buf[INET6_ADDRSTRLEN];
 
-       KASSERT(in6m_sol != NULL);
-
        /* join solicited multicast addr for new host id */
-       memset(&llsol, 0, sizeof(struct in6_addr));
-       llsol.s6_addr16[0] = htons(0xff02);
-       llsol.s6_addr32[1] = 0;
-       llsol.s6_addr32[2] = htonl(1);
-       llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
-       llsol.s6_addr8[12] = 0xff;
-       if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
-               /* XXX: should not happen */
-               log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
+       error = in6_get_llsol_addr(&llsol, ifp, &ifra->ifra_addr.sin6_addr);
+       if (error != 0)
                goto out;
-       }
        dad_delay = 0;
        if ((flags & IN6_IFAUPDATE_DADDELAY)) {
                /*
@@ -828,7 +840,6 @@
        mutex_enter(&in6_ifaddr_lock);
        LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
        mutex_exit(&in6_ifaddr_lock);
-       *in6m_sol = imm->i6mm_maddr;
 
        sockaddr_in6_init(&mltmask, &in6mask32, 0, 0, 0);
 
@@ -997,7 +1008,6 @@
        int error = 0, hostIsNew = 0, plen = -1;
        struct sockaddr_in6 dst6;
        struct in6_addrlifetime *lt;
-       struct in6_multi *in6m_sol = NULL;
        int dad_delay, was_tentative;
        struct in6_ifaddr *ia = iap ? *iap : NULL;
        char ip6buf[INET6_ADDRSTRLEN];
@@ -1283,7 +1293,7 @@
 
        /* join necessary multicast groups */
        if ((ifp->if_flags & IFF_MULTICAST) != 0) {
-               error = in6_join_mcastgroups(ifra, ia, ifp, &in6m_sol, flags);
+               error = in6_join_mcastgroups(ifra, ia, ifp, flags);
                if (error != 0)
                        goto cleanup;
        }
@@ -1306,6 +1316,8 @@
 
                dad_delay = 0;
                if ((flags & IN6_IFAUPDATE_DADDELAY)) {
+                       struct in6_addr llsol;
+                       struct in6_multi *in6m_sol = NULL;
                        /*
                         * We need to impose a delay before sending an NS
                         * for DAD.  Check if we also needed a delay for the
@@ -1315,10 +1327,16 @@
                         * safe).
                         */
                        mindelay = 0;
+                       error = in6_get_llsol_addr(&llsol, ifp,
+                           &ifra->ifra_addr.sin6_addr);
+                       in6_multi_lock(RW_READER);
+                       if (error == 0)
+                               in6m_sol = in6_lookup_multi(&llsol, ifp);
                        if (in6m_sol != NULL &&
                            in6m_sol->in6m_state == MLD_REPORTPENDING) {
                                mindelay = in6m_sol->in6m_timer;
                        }
+                       in6_multi_unlock();
                        maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
                        if (maxdelay - mindelay == 0)
                                dad_delay = 0;
diff -r 3056c3017082 -r 6707fbb67df4 sys/netinet6/in6_var.h
--- a/sys/netinet6/in6_var.h    Thu Mar 02 05:35:01 2017 +0000
+++ b/sys/netinet6/in6_var.h    Thu Mar 02 09:16:46 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_var.h,v 1.95 2017/03/02 05:27:39 ozaki-r Exp $     */
+/*     $NetBSD: in6_var.h,v 1.96 2017/03/02 09:16:46 ozaki-r Exp $     */
 /*     $KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $        */
 
 /*
@@ -681,6 +681,8 @@
 
 void   in6_init(void);
 
+void   in6_multi_lock(int);
+void   in6_multi_unlock(void);
 struct in6_multi *
        in6_lookup_multi(const struct in6_addr *, const struct ifnet *);
 bool   in6_multi_group(const struct in6_addr *, const struct ifnet *);
diff -r 3056c3017082 -r 6707fbb67df4 sys/netinet6/mld6.c
--- a/sys/netinet6/mld6.c       Thu Mar 02 05:35:01 2017 +0000
+++ b/sys/netinet6/mld6.c       Thu Mar 02 09:16:46 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mld6.c,v 1.86 2017/03/02 05:27:39 ozaki-r Exp $        */
+/*     $NetBSD: mld6.c,v 1.87 2017/03/02 09:16:46 ozaki-r Exp $        */
 /*     $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $   */
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.86 2017/03/02 05:27:39 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.87 2017/03/02 09:16:46 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -901,6 +901,20 @@
        rw_exit(&in6_multilock);
 }
 
+void
+in6_multi_lock(int op)
+{
+
+       rw_enter(&in6_multilock, op);
+}
+
+void
+in6_multi_unlock(void)
+{
+
+       rw_exit(&in6_multilock);
+}
+
 struct in6_multi_mship *
 in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, 
        int *errorp, int timer)



Home | Main Index | Thread Index | Old Index