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.
This commit is contained in:
Ian Dowse 2005-06-02 00:04:08 +00:00
parent e1d27f08f1
commit ba5da2a06f
2 changed files with 34 additions and 18 deletions

View File

@ -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) {

View File

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