summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-06-02 00:04:08 +0000
committeriedowse <iedowse@FreeBSD.org>2005-06-02 00:04:08 +0000
commit7de9a3957f49a3d2defeb896784a44358d279dd0 (patch)
tree32aeb891654c057245ca73c42be4699204111c11
parent4587fc275c58e748bcd2067eed3c716c7c7ca467 (diff)
downloadFreeBSD-src-7de9a3957f49a3d2defeb896784a44358d279dd0.zip
FreeBSD-src-7de9a3957f49a3d2defeb896784a44358d279dd0.tar.gz
Use IFF_LOCKGIANT/IFF_UNLOCKGIANT around calls to the interface
if_ioctl routine. This should fix a number of code paths through soo_ioctl() that could call into Giant-locked network drivers without first acquiring Giant.
-rw-r--r--sys/netinet/in.c40
-rw-r--r--sys/netinet6/in6.c12
2 files changed, 34 insertions, 18 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 6c7893c..fcc1809 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -356,10 +356,15 @@ in_control(so, cmd, data, ifp, td)
return (EINVAL);
oldaddr = ia->ia_dstaddr;
ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
- if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
- (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
- ia->ia_dstaddr = oldaddr;
- return (error);
+ if (ifp->if_ioctl) {
+ IFF_LOCKGIANT(ifp);
+ error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
+ (caddr_t)ia);
+ IFF_UNLOCKGIANT(ifp);
+ if (error) {
+ ia->ia_dstaddr = oldaddr;
+ return (error);
+ }
}
if (ia->ia_flags & IFA_ROUTE) {
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
@@ -456,7 +461,10 @@ in_control(so, cmd, data, ifp, td)
default:
if (ifp == 0 || ifp->if_ioctl == 0)
return (EOPNOTSUPP);
- return ((*ifp->if_ioctl)(ifp, cmd, data));
+ IFF_LOCKGIANT(ifp);
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ IFF_UNLOCKGIANT(ifp);
+ return (error);
}
/*
@@ -689,15 +697,19 @@ in_ifinit(ifp, ia, sin, scrub)
* if this is its first address,
* and to validate the address if necessary.
*/
- if (ifp->if_ioctl &&
- (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
- splx(s);
- /* LIST_REMOVE(ia, ia_hash) is done in in_control */
- ia->ia_addr = oldaddr;
- if (ia->ia_addr.sin_family == AF_INET)
- LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
- ia, ia_hash);
- return (error);
+ if (ifp->if_ioctl) {
+ IFF_LOCKGIANT(ifp);
+ error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
+ IFF_UNLOCKGIANT(ifp);
+ if (error) {
+ splx(s);
+ /* LIST_REMOVE(ia, ia_hash) is done in in_control */
+ ia->ia_addr = oldaddr;
+ if (ia->ia_addr.sin_family == AF_INET)
+ LIST_INSERT_HEAD(INADDR_HASH(
+ ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
+ return (error);
+ }
}
splx(s);
if (scrub) {
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 7bd5e64..1dc7516 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1507,10 +1507,14 @@ in6_ifinit(ifp, ia, sin6, newhost)
ia->ia_addr = *sin6;
- if (ifacount <= 1 && ifp->if_ioctl &&
- (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
- splx(s);
- return (error);
+ if (ifacount <= 1 && ifp->if_ioctl) {
+ IFF_LOCKGIANT(ifp);
+ error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
+ IFF_UNLOCKGIANT(ifp);
+ if (error) {
+ splx(s);
+ return (error);
+ }
}
splx(s);
OpenPOWER on IntegriCloud