diff options
author | rwatson <rwatson@FreeBSD.org> | 2005-10-03 11:09:39 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2005-10-03 11:09:39 +0000 |
commit | 2d9ef0269a70026a60fef6d99a7e43e7eacb2907 (patch) | |
tree | 63186fb2fc06ebc97c0f3a3ab1435d1369bb912e | |
parent | 6026f74dcd180b8c501980ab3251934e5709a291 (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/netinet/in.c | 9 |
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(); } |