looks reasonable to me.
OK

On Tue, May 01, 2018 at 07:08:59PM +0200, Theo Buehler wrote:
> On Mon, Apr 30, 2018 at 02:55:21PM +0200, Martin Pieuchot wrote:
> > On 30/04/18(Mon) 12:00, Theo Buehler wrote:
> > > With mpi's encouragement and guidance, here's a diff that reduces the
> > > scope of the NET_LOCK() a bit.
> > > 
> > > in_control() is the only caller of mrt_ioctl() and the latter is a
> > > simple function only requiring a read lock.
> > > 
> > > There are only a handful callers of in_ioctl(). The two switches create
> > > relatively tangled codepaths, so this will need some refactoring before
> > > we can push the lock further down and split the read and write cases.
> > > For now, establish a single exit point, grab the netlock at the
> > > beginning and release it at the end.
> > 
> > That makes sense, the same could be done for in6_ioctl().
> 
> Here's the corresponding diff for in6_control().
> 
> Push the diff down into mrt6_ioctl() and in6_ioctl(). Much like the IPv4
> version, mrt6_ioctl() only needs a read lock.
> 
> in6_ioctl() is a bit messier. It starts off with a call to nd6_ioctl(),
> which only needs a read lock. In the diff, I pushed the NET_RLOCK() down
> into nd6_ioctl(), but perhaps it would be better to keep the locking
> inside in6_ioctl(), like this:
> 
>       switch (cmd) {
>       case SIOCGIFINFO_IN6:
>       case SIOCGNBRINFO_IN6:
>               NET_RLOCK();
>               error = nd6_ioctl(cmd, data, ifp);
>               NET_RUNLOCK();
>               return error;
>       }
> 
> I tested this as well as I could, but I don't usually use IPv6, so I
> dabbled a bit with it on my home network and I tried to use the netinet6
> regress tests, only with moderate success.
> 
> A test from people who actually use IPv6 would be welcome.
> 
> Index: sys/netinet6/in6.c
> ===================================================================
> RCS file: /var/cvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.222
> diff -u -p -r1.222 in6.c
> --- sys/netinet6/in6.c        24 Apr 2018 19:53:38 -0000      1.222
> +++ sys/netinet6/in6.c        1 May 2018 09:14:07 -0000
> @@ -183,7 +183,6 @@ in6_control(struct socket *so, u_long cm
>       int privileged;
>       int error;
>  
> -     NET_LOCK();
>       privileged = 0;
>       if ((so->so_state & SS_PRIV) != 0)
>               privileged++;
> @@ -200,7 +199,6 @@ in6_control(struct socket *so, u_long cm
>               break;
>       }
>  
> -     NET_UNLOCK();
>       return error;
>  }
>  
> @@ -211,12 +209,11 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>       struct  in6_ifaddr *ia6 = NULL;
>       struct  in6_aliasreq *ifra = (struct in6_aliasreq *)data;
>       struct sockaddr_in6 *sa6;
> +     int     error = 0;
>  
>       if (ifp == NULL)
>               return (ENXIO);
>  
> -     NET_ASSERT_LOCKED();
> -
>       switch (cmd) {
>       case SIOCGIFINFO_IN6:
>       case SIOCGNBRINFO_IN6:
> @@ -252,13 +249,16 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>       case SIOCSIFNETMASK:
>               /*
>                * Do not pass those ioctl to driver handler since they are not
> -              * properly setup. Instead just error out.
> +              * properly set up. Instead just error out.
>                */
>               return (EINVAL);
>       default:
>               sa6 = NULL;
>               break;
>       }
> +
> +     NET_LOCK();
> +
>       if (sa6 && sa6->sin6_family == AF_INET6) {
>               if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
>                       if (sa6->sin6_addr.s6_addr16[1] == 0) {
> @@ -267,12 +267,15 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                                   htons(ifp->if_index);
>                       } else if (sa6->sin6_addr.s6_addr16[1] !=
>                           htons(ifp->if_index)) {
> -                             return (EINVAL);        /* link ID contradicts 
> */
> +                             error = EINVAL; /* link ID contradicts */
> +                             goto err;
>                       }
>                       if (sa6->sin6_scope_id) {
>                               if (sa6->sin6_scope_id !=
> -                                 (u_int32_t)ifp->if_index)
> -                                     return (EINVAL);
> +                                 (u_int32_t)ifp->if_index) {
> +                                     error = EINVAL;
> +                                     goto err;
> +                             }
>                               sa6->sin6_scope_id = 0; /* XXX: good way? */
>                       }
>               }
> @@ -289,8 +292,10 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                * interface address from the day one, we consider "remove the
>                * first one" semantics to be not preferable.
>                */
> -             if (ia6 == NULL)
> -                     return (EADDRNOTAVAIL);
> +             if (ia6 == NULL) {
> +                     error = EADDRNOTAVAIL;
> +                     goto err;
> +             }
>               /* FALLTHROUGH */
>       case SIOCAIFADDR_IN6:
>               /*
> @@ -298,11 +303,14 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                * the corresponding operation.
>                */
>               if (ifra->ifra_addr.sin6_family != AF_INET6 ||
> -                 ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
> -                     return (EAFNOSUPPORT);
> -             if (!privileged)
> -                     return (EPERM);
> -
> +                 ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
> +                     error = EAFNOSUPPORT;
> +                     goto err;
> +             }
> +             if (!privileged) {
> +                     error = EPERM;
> +                     goto err;
> +             }
>               break;
>  
>       case SIOCGIFAFLAG_IN6:
> @@ -310,15 +318,19 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>       case SIOCGIFDSTADDR_IN6:
>       case SIOCGIFALIFETIME_IN6:
>               /* must think again about its semantics */
> -             if (ia6 == NULL)
> -                     return (EADDRNOTAVAIL);
> +             if (ia6 == NULL) {
> +                     error = EADDRNOTAVAIL;
> +                     goto err;
> +             }
>               break;
>       }
>  
>       switch (cmd) {
>       case SIOCGIFDSTADDR_IN6:
> -             if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
> -                     return (EINVAL);
> +             if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
> +                     error = EINVAL;
> +                     break;
> +             }
>               /*
>                * XXX: should we check if ifa_dstaddr is NULL and return
>                * an error?
> @@ -392,7 +404,8 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>               if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
>                   (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
>                   (ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
> -                     return (EINVAL);
> +                     error = EINVAL;
> +                     break;
>               }
>  
>               if (ia6 == NULL)
> @@ -413,10 +426,10 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                */
>               error = in6_ifattach(ifp);
>               if (error != 0)
> -                     return (error);
> +                     break;
>               error = in6_update_ifa(ifp, ifra, ia6);
>               if (error != 0)
> -                     return (error);
> +                     break;
>  
>               ia6 = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
>               if (ia6 == NULL) {
> @@ -446,7 +459,7 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>                   ia6->ia_ifa.ifa_addr);
>               if (error) {
>                       in6_purgeaddr(&ia6->ia_ifa);
> -                     return (error);
> +                     break;
>               }
>               dohooks(ifp->if_addrhooks, 0);
>               break;
> @@ -458,10 +471,13 @@ in6_ioctl(u_long cmd, caddr_t data, stru
>               break;
>  
>       default:
> -             return (EOPNOTSUPP);
> +             error = EOPNOTSUPP;
> +             break;
>       }
>  
> -     return (0);
> +err:
> +     NET_UNLOCK();
> +     return (error);
>  }
>  
>  /*
> Index: sys/netinet6/ip6_mroute.c
> ===================================================================
> RCS file: /var/cvs/src/sys/netinet6/ip6_mroute.c,v
> retrieving revision 1.114
> diff -u -p -r1.114 ip6_mroute.c
> --- sys/netinet6/ip6_mroute.c 26 Jun 2017 09:32:32 -0000      1.114
> +++ sys/netinet6/ip6_mroute.c 1 May 2018 08:42:18 -0000
> @@ -242,17 +242,26 @@ int
>  mrt6_ioctl(struct socket *so, u_long cmd, caddr_t data)
>  {
>       struct inpcb *inp = sotoinpcb(so);
> +     int error;
>  
>       switch (cmd) {
>       case SIOCGETSGCNT_IN6:
> -             return (get_sg6_cnt((struct sioc_sg_req6 *)data,
> -                 inp->inp_rtableid));
> +             NET_RLOCK();
> +             error = get_sg6_cnt((struct sioc_sg_req6 *)data,
> +                 inp->inp_rtableid);
> +             NET_RUNLOCK();
> +             break;
>       case SIOCGETMIFCNT_IN6:
> -             return (get_mif6_cnt((struct sioc_mif_req6 *)data,
> -                 inp->inp_rtableid));
> +             NET_RLOCK();
> +             error = get_mif6_cnt((struct sioc_mif_req6 *)data,
> +                 inp->inp_rtableid);
> +             NET_RUNLOCK();
> +             break;
>       default:
> -             return (ENOTTY);
> +             error = ENOTTY;
> +             break;
>       }
> +     return error;
>  }
>  
>  /*
> Index: sys/netinet6/nd6.c
> ===================================================================
> RCS file: /var/cvs/src/sys/netinet6/nd6.c,v
> retrieving revision 1.223
> diff -u -p -r1.223 nd6.c
> --- sys/netinet6/nd6.c        15 Jan 2018 13:48:31 -0000      1.223
> +++ sys/netinet6/nd6.c        30 Apr 2018 22:42:59 -0000
> @@ -1014,20 +1014,20 @@ nd6_ioctl(u_long cmd, caddr_t data, stru
>       struct in6_ndireq *ndi = (struct in6_ndireq *)data;
>       struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
>       struct rtentry *rt;
> -     int error = 0;
> -
> -     NET_ASSERT_LOCKED();
>  
>       switch (cmd) {
>       case SIOCGIFINFO_IN6:
> +             NET_RLOCK();
>               ndi->ndi = *ND_IFINFO(ifp);
> -             break;
> +             NET_RUNLOCK();
> +             return (0);
>       case SIOCGNBRINFO_IN6:
>       {
>               struct llinfo_nd6 *ln;
>               struct in6_addr nb_addr = nbi->addr; /* make local for safety */
>               time_t expire;
>  
> +             NET_RLOCK();
>               /*
>                * XXX: KAME specific hack for scoped addresses
>                *      XXXX: for other scopes than link-local?
> @@ -1043,9 +1043,9 @@ nd6_ioctl(u_long cmd, caddr_t data, stru
>               rt = nd6_lookup(&nb_addr, 0, ifp, ifp->if_rdomain);
>               if (rt == NULL ||
>                   (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
> -                     error = EINVAL;
>                       rtfree(rt);
> -                     break;
> +                     NET_RUNLOCK();
> +                     return (EINVAL);
>               }
>               expire = ln->ln_rt->rt_expire;
>               if (expire != 0) {
> @@ -1057,12 +1057,13 @@ nd6_ioctl(u_long cmd, caddr_t data, stru
>               nbi->asked = ln->ln_asked;
>               nbi->isrouter = ln->ln_router;
>               nbi->expire = expire;
> -             rtfree(rt);
>  
> -             break;
> +             rtfree(rt);
> +             NET_RUNLOCK();
> +             return (0);
>       }
>       }
> -     return (error);
> +     return (0);
>  }
>  
>  /*
> 


-- 
I'm not entirely sure you are real.

Reply via email to