On Wed, Sep 03, 2014 at 03:25:34PM +0200, Martin Pieuchot wrote:
> Drivers that need a splnet() protection inside their SIOCSIFADDR
> generally raise the spl level themselves, so we should not need
> to do that in in{6,}_ifinit(). One exception to this rule is,
> as always, carp(4)...
>
> So the diff below moves the spl dance inside carp's SIOCSIFADDR
> handler, it's a baby step, so we can take care of carp_set_addr{6,}
> later.
Hmm. My gut feeling is that this is scary. Calling ifp functions at
non-splnet is always a cause for troubles (e.g. the watchdog callbacks
miss often the needed splnet calls).
I think the ioctl code pathes in the various places may suffer from
similar problems with missing splnet() calls. Guess a bit of an audit is
needed in that area.
Something else I wonder is if splsoftnet() is good enough when dealing
with ifp in general (aren't we detaching interfaces at splnet())?
Removable interfaces opened for sure a bucket sized can of worms.
> ok?
>
> Index: netinet/in.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/in.c,v
> retrieving revision 1.103
> diff -u -p -r1.103 in.c
> --- netinet/in.c 3 Sep 2014 08:59:06 -0000 1.103
> +++ netinet/in.c 3 Sep 2014 13:08:43 -0000
> @@ -612,7 +612,7 @@ in_ifinit(struct ifnet *ifp, struct in_i
> {
> u_int32_t i = sin->sin_addr.s_addr;
> struct sockaddr_in oldaddr;
> - int s, error = 0;
> + int error = 0;
>
> splsoftassert(IPL_SOFTNET);
>
> @@ -627,7 +627,6 @@ in_ifinit(struct ifnet *ifp, struct in_i
> rt_ifa_delloop(&ia->ia_ifa);
> ifa_del(ifp, &ia->ia_ifa);
> }
> - s = splnet();
> oldaddr = ia->ia_addr;
> ia->ia_addr = *sin;
>
> @@ -639,10 +638,8 @@ in_ifinit(struct ifnet *ifp, struct in_i
> if (ifp->if_ioctl &&
> (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
> ia->ia_addr = oldaddr;
> - splx(s);
> goto out;
> }
> - splx(s);
>
> if (ia->ia_netmask == 0) {
> if (IN_CLASSA(i))
> Index: netinet/ip_carp.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v
> retrieving revision 1.233
> diff -u -p -r1.233 ip_carp.c
> --- netinet/ip_carp.c 22 Jul 2014 11:06:10 -0000 1.233
> +++ netinet/ip_carp.c 3 Sep 2014 13:08:43 -0000
> @@ -2060,10 +2060,11 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
> struct ifaddr *ifa = (struct ifaddr *)addr;
> struct ifreq *ifr = (struct ifreq *)addr;
> struct ifnet *cdev = NULL;
> - int i, error = 0;
> + int s, i, error = 0;
>
> switch (cmd) {
> case SIOCSIFADDR:
> + s = splnet();
> switch (ifa->ifa_addr->sa_family) {
> #ifdef INET
> case AF_INET:
> @@ -2088,6 +2089,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd
> break;
> }
> break;
> + splx(s);
>
> case SIOCSIFFLAGS:
> vhe = LIST_FIRST(&sc->carp_vhosts);
> Index: netinet6/in6.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.140
> diff -u -p -r1.140 in6.c
> --- netinet6/in6.c 26 Aug 2014 21:44:29 -0000 1.140
> +++ netinet6/in6.c 3 Sep 2014 13:08:43 -0000
> @@ -1078,7 +1078,7 @@ in6_purgeaddr(struct ifaddr *ifa)
> void
> in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp)
> {
> - int s = splnet();
> + splsoftassert(IPL_SOFTNET);
>
> ifa_del(ifp, &ia6->ia_ifa);
>
> @@ -1107,8 +1107,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia6, s
> * Note that we should decrement the refcnt at least once for all *BSD.
> */
> ifafree(&ia6->ia_ifa);
> -
> - splx(s);
> }
>
> /*
> @@ -1355,9 +1353,10 @@ int
> in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost)
> {
> int error = 0, plen, ifacount = 0;
> - int s = splnet();
> struct ifaddr *ifa;
>
> + splsoftassert(IPL_SOFTNET);
> +
> /*
> * Give the interface a chance to initialize
> * if this is its first address (or it is a CARP interface)
> @@ -1374,10 +1373,8 @@ in6_ifinit(struct ifnet *ifp, struct in6
> if ((ifacount <= 1 || ifp->if_type == IFT_CARP ||
> (ifp->if_flags & IFF_POINTOPOINT)) && ifp->if_ioctl &&
> (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) {
> - splx(s);
> return (error);
> }
> - splx(s);
>
> ia6->ia_ifa.ifa_metric = ifp->if_metric;
>
>
--
:wq Claudio