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