On 11/09/14(Thu) 10:49, Martin Pieuchot wrote:
> On 03/09/14(Wed) 20:59, Alexander Bluhm wrote:
> > On Wed, Sep 03, 2014 at 03:53:34PM +0200, Martin Pieuchot wrote:
> > > @@ -1078,7 +1079,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);
> > >  
> > 
> > I think there are code paths that can trigger this assertion
> > 
> > netinet6/in6.c:                     in6_unlink_ifa()
> > netinet6/in6.c:                     in6_purgeaddr()
> > netinet6/nd6_rtr.c:         purge_detached()
> > netinet6/nd6_rtr.c:         nd6_prelist_add()
> > netinet6/in6.c:                     in6_control()
> > netinet/tcp_usrreq.c:               tcp_usrreq()
> > kern/sys_socket.c:          soo_ioctl()
> > 
> > netinet6/in6.c:                     in6_unlink_ifa()
> > netinet6/in6.c:                     in6_purgeaddr()
> > netinet6/nd6_rtr.c:         purge_detached()
> > netinet6/nd6_rtr.c:         nd6_prelist_add()
> > netinet6/in6_ifattach.c:    in6_ifattach_linklocal()
> > netinet/ip_carp.c           carp_set_enaddr()
> > netinet/ip_carp.c           carp_ioctl()
> > ...
> > 
> > nd6_prelist_add() does some splsoftnet() already.  I think you
> > should put one around purge_detached() there.
> 
> Nice catch, updated diff below.

Any comment or ok?

> Index: net/if_loop.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/if_loop.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 if_loop.c
> --- net/if_loop.c     22 Jul 2014 11:06:09 -0000      1.57
> +++ net/if_loop.c     11 Sep 2014 08:45:29 -0000
> @@ -288,15 +288,13 @@ loioctl(struct ifnet *ifp, u_long cmd, c
>  {
>       struct ifaddr *ifa;
>       struct ifreq *ifr;
> -     int s, error = 0;
> +     int error = 0;
>  
>       switch (cmd) {
>  
>       case SIOCSIFADDR:
> -             s = splnet();
>               ifp->if_flags |= IFF_RUNNING;
>               if_up(ifp);             /* send up RTM_IFINFO */
> -             splx(s);
>  
>               ifa = (struct ifaddr *)data;
>               if (ifa != 0)
> 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      11 Sep 2014 08:45:29 -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.234
> diff -u -p -r1.234 ip_carp.c
> --- netinet/ip_carp.c 8 Sep 2014 06:24:13 -0000       1.234
> +++ netinet/ip_carp.c 11 Sep 2014 08:45:29 -0000
> @@ -2059,10 +2059,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:
> @@ -2087,6 +2088,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    11 Sep 2014 08:45:29 -0000
> @@ -172,7 +172,7 @@ in6_control(struct socket *so, u_long cm
>       struct  in6_ifaddr *ia6 = NULL;
>       struct  in6_aliasreq *ifra = (struct in6_aliasreq *)data;
>       struct sockaddr_in6 *sa6;
> -     int privileged;
> +     int s, privileged;
>  
>       privileged = 0;
>       if ((so->so_state & SS_PRIV) != 0)
> @@ -463,7 +463,6 @@ in6_control(struct socket *so, u_long cm
>       {
>               int i, error = 0;
>               struct nd_prefix pr0, *pr;
> -             int s;
>  
>               /* reject read-only flags */
>               if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
> @@ -561,8 +560,10 @@ in6_control(struct socket *so, u_long cm
>       }
>  
>       case SIOCDIFADDR_IN6:
> +             s = splsoftnet();
>               in6_purgeaddr(&ia6->ia_ifa);
>               dohooks(ifp->if_addrhooks, 0);
> +             splx(s);
>               break;
>  
>       default:
> @@ -1078,7 +1079,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 +1108,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 +1354,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 +1374,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;
>  
> Index: netinet6/nd6_rtr.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet6/nd6_rtr.c,v
> retrieving revision 1.87
> diff -u -p -r1.87 nd6_rtr.c
> --- netinet6/nd6_rtr.c        9 Sep 2014 20:33:24 -0000       1.87
> +++ netinet6/nd6_rtr.c        11 Sep 2014 08:45:29 -0000
> @@ -990,6 +990,8 @@ purge_detached(struct ifnet *ifp)
>       struct in6_ifaddr *ia6;
>       struct ifaddr *ifa, *ifa_next;
>  
> +     splsoftassert(IPL_SOFTNET);
> +
>       LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, pr_next) {
>               /*
>                * This function is called when we need to make more room for
> @@ -1025,8 +1027,11 @@ nd6_prelist_add(struct nd_prefix *pr, st
>       struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
>  
>       if (ip6_maxifprefixes >= 0) {
> -             if (ext->nprefixes >= ip6_maxifprefixes / 2)
> +             if (ext->nprefixes >= ip6_maxifprefixes / 2) {
> +                     s = splsoftnet();
>                       purge_detached(pr->ndpr_ifp);
> +                     splx(s);
> +             }
>               if (ext->nprefixes >= ip6_maxifprefixes)
>                       return(ENOMEM);
>       }
> 

Reply via email to