Date: Fri, 9 Mar 2012 16:59:32 -0800 From: prabhakar lakhera <prabhakar.lakhera@gmail.com> To: freebsd-net@freebsd.org Subject: Race condition in IPv6 DAD detection code? Message-ID: <CALg%2BrhV8OMw5qHydbajYNAFkkSCfChH2Hk_eAr3DrW%2BdhOVkuw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hi, I had sent a mail sometime back regarding some queries/concern regarding v6 DAD detection code. Here's what my concern is, drawing tables for the whole sequence in hopes of getting some replies: *CPU1* *CPU2* In nd6_dad_na_input... struct dadq *dp; if (ifa =3D=3D NULL) panic("ifa =3D=3D NULL in nd6_dad_na_input"); dp =3D nd6_dad_find(ifa); if (dp) nd6_dad_timer.. last attempt and NA counter not yet incremented by the thread on CPU1, therefore address considered to be not duplicated. if (dp->dad_ns_ocount < dp->dad_count) { =85.. } else { /* * We have transmitted sufficient number of DAD packets. * See what we've got. */ int duplicate; duplicate =3D 0; if (dp->dad_na_icount) { /* * the check is in nd6_dad_na_input(), * but just in case */ duplicate++; } if (dp->dad_ns_icount) { /* We've seen NS, means DAD has failed. */ duplicate++; } if (duplicate) { =DF----- Duplicate 0 here /* (*dp) will be freed in nd6_dad_duplicated() */ dp =3D NULL; nd6_dad_duplicated(ifa); } else { In nd6_dad_na_input... dp->dad_na_icount++; /* remove the address. */ nd6_dad_duplicated(ifa); Inside nd6_dad_duplicated=85 nd6_dad_duplicated(struct ifaddr *ifa) { struct in6_ifaddr *ia =3D (struct in6_ifaddr *)ifa; struct ifnet *ifp; struct dadq *dp; char ip6buf[INET6_ADDRSTRLEN]; dp =3D nd6_dad_find(ifa); if (dp =3D=3D NULL) { log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n"); return; } =85. --=E0 dp is not NULL as has not yet been removed from queue. Nd6_dad_timer executing else=85. /* * We are done with DAD. No NA came, no NS came. * No duplicate address found. */ ia->ia6_flags &=3D ~IN6_IFF_TENTATIVE; nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); free(dp, M_IP6NDP); dp =3D NULL; ifa_free(ifa); } In nd6_dad_duplicated(struct ifaddr *ifa) =85 *Working on freed pointer??? * * log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "* * "NS in/out=3D%d/%d, NA in=3D%d\n",* * if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),* * dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);* On Wed, Mar 7, 2012 at 5:51 PM, prabhakar lakhera < prabhakar.lakhera@gmail.com> wrote: > Hi, > > I was puzzled to look at DAD detection code in FreeBSD. We check for > counters for any received NA/NS for DAD in nd6_dad_timer: > > if (dp->dad_na_icount) { > 1326 /* > 1327 * the check is in nd6_dad_na_input(), > 1328 * but just in case > 1329 */ > 1330 duplicate++; > 1331 } > 1332 > 1333 if (dp->dad_ns_icount) { > 1334 /* We've seen NS, means DAD has failed. */ > 1335 duplicate++; > 1336 } > 1337 > 1338 if (duplicate) { > 1339 /* (*dp) will be freed in > nd6_dad_duplicated() */ > 1340 dp =3D NULL; > 1341 nd6_dad_duplicated(ifa); > > the function later calls nd6_dad_duplicated to perform the remaining work > if the address is detected duplicate. > > nd6_dad_duplicated also gets called from nd6_dad_na_input > and nd6_dad_ns_input, both the functions are the only places which > increment the input NA/NS counters respectively. > > 1505 static void > 1506 nd6_dad_na_input(struct ifaddr *ifa) > 1507 { > 1508 struct dadq *dp; > 1509 > 1510 if (ifa =3D=3D NULL) > 1511 panic("ifa =3D=3D NULL in nd6_dad_na_input"); > 1512 > 1513 dp =3D nd6_dad_find(ifa); > 1514 if (dp) > 1515 dp->dad_na_icount++; > 1516 > 1517 /* remove the address. */ > 1518 nd6_dad_duplicated(ifa); > 1519 } > > nd6_dad_duplicated stops the timer among other things. > > Why nd6_dad_timer need check on these counters if we stop the timer on DA= D > failure anyways? > Ok.. may be just an optimization which just "hopes" that the counters hav= e > been updated but the nd6_dad_*_input has not yet called nd6_dad_duplicate= d. > > Can the this timer and na packet processing ever run in parallel, I don;t > see dp being protected by any locks, nor does it seem that it's been > reference counted. > Any explanation will be highly appreciated. > > Best, > > Prabhakar > > > > > >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CALg%2BrhV8OMw5qHydbajYNAFkkSCfChH2Hk_eAr3DrW%2BdhOVkuw>