summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2005-10-03 11:09:39 +0000
committerrwatson <rwatson@FreeBSD.org>2005-10-03 11:09:39 +0000
commit2d9ef0269a70026a60fef6d99a7e43e7eacb2907 (patch)
tree63186fb2fc06ebc97c0f3a3ab1435d1369bb912e /sys/netinet/in.c
parent6026f74dcd180b8c501980ab3251934e5709a291 (diff)
downloadFreeBSD-src-2d9ef0269a70026a60fef6d99a7e43e7eacb2907.zip
FreeBSD-src-2d9ef0269a70026a60fef6d99a7e43e7eacb2907.tar.gz
Acquire Giant conditionally in in_addmulti() and in_delmulti() based on
whether the interface being accessed is IFF_NEEDSGIANT or not. This avoids lock order reversals when calling into the interface ioctl handler, which could potentially lead to deadlock. The long term solution is to eliminate non-MPSAFE network drivers. Discussed with: jhb MFC after: 1 week
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 2eb5e94..0f44ba8 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -961,6 +961,7 @@ in_addmulti(ap, ifp)
struct sockaddr_in sin;
struct ifmultiaddr *ifma;
+ IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
/*
* Call generic routine to add membership or increment
@@ -974,6 +975,7 @@ in_addmulti(ap, ifp)
error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
if (error) {
IN_MULTI_UNLOCK();
+ IFF_UNLOCKGIANT(ifp);
return 0;
}
@@ -983,6 +985,7 @@ in_addmulti(ap, ifp)
*/
if (ifma->ifma_protospec != NULL) {
IN_MULTI_UNLOCK();
+ IFF_UNLOCKGIANT(ifp);
return ifma->ifma_protospec;
}
@@ -990,6 +993,7 @@ in_addmulti(ap, ifp)
M_NOWAIT | M_ZERO);
if (inm == NULL) {
IN_MULTI_UNLOCK();
+ IFF_UNLOCKGIANT(ifp);
return (NULL);
}
@@ -1004,6 +1008,7 @@ in_addmulti(ap, ifp)
*/
igmp_joingroup(inm);
IN_MULTI_UNLOCK();
+ IFF_UNLOCKGIANT(ifp);
return (inm);
}
@@ -1016,7 +1021,10 @@ in_delmulti(inm)
{
struct ifmultiaddr *ifma;
struct in_multi my_inm;
+ struct ifnet *ifp;
+ ifp = inm->inm_ifp;
+ IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
ifma = inm->inm_ifma;
my_inm.inm_ifp = NULL ; /* don't send the leave msg */
@@ -1036,6 +1044,7 @@ in_delmulti(inm)
if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
if (my_inm.inm_ifp != NULL)
igmp_leavegroup(&my_inm);
+ IFF_UNLOCKGIANT(ifp);
IN_MULTI_UNLOCK();
}
OpenPOWER on IntegriCloud