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
This commit is contained in:
Robert Watson 2005-10-03 11:09:39 +00:00
parent 6fa40729c8
commit 1fa9efeffb

View File

@ -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();
}