Follow up on how in6_ioctl() does it: grab the kernel lock in all the
ioctl specific functions, where needed and not earlier, i.e. exactly where
the net lock is currently taken/released.
Like in6_ioctl_get(), in_ioctl_get() simply grabs a net lock protected
interface address, may check net lock protected interface flags and copies
out data -- all under the shared net lock.
in_ioctl_set_ifaddr() and in_ioctl_change_ifaddr() remain kernel locked,
but at least their sanity check on ioctl data now happens without it.
Feedback? Objection? OK?
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 0a59d708dfb..c1a95d6ab75 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -216,9 +216,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp)
break;
#endif /* MROUTING */
default:
- KERNEL_LOCK();
error = in_ioctl(cmd, data, ifp, privileged);
- KERNEL_UNLOCK();
break;
}
@@ -262,6 +260,7 @@ in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int
privileged)
return (error);
}
+ KERNEL_LOCK();
NET_LOCK();
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
@@ -348,6 +347,7 @@ in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int
privileged)
}
err:
NET_UNLOCK();
+ KERNEL_UNLOCK();
return (error);
}
@@ -372,6 +372,7 @@ in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet
*ifp,
if (error)
return (error);
+ KERNEL_LOCK();
NET_LOCK();
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
@@ -406,6 +407,7 @@ in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet
*ifp,
if_addrhooks_run(ifp);
NET_UNLOCK();
+ KERNEL_UNLOCK();
return error;
}
@@ -427,6 +429,7 @@ in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct
ifnet *ifp,
return (error);
}
+ KERNEL_LOCK();
NET_LOCK();
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
@@ -555,9 +558,9 @@ in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct
ifnet *ifp,
}
NET_UNLOCK();
+ KERNEL_UNLOCK();
return (error);
}
-
int
in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp)
{