Download raw body.
ip6_sysctl(): push netlock down to mrt6_sysctl_mif()
On Thu, Jul 24, 2025 at 11:18:15PM +0300, Vitaliy Makkoveev wrote:
> Except the delivered data, it is the same as mrt_sysctl_vif(). So link
> the network interfaces to the temporary list protected by
> `if_tmplist_lock' rwlock(9) to avoid copyout() with netlock held. Also
> use shared netlock instead of exclusive.
OK bluhm@
> Index: sys/netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.285
> diff -u -p -r1.285 ip6_input.c
> --- sys/netinet6/ip6_input.c 24 Jul 2025 18:02:19 -0000 1.285
> +++ sys/netinet6/ip6_input.c 24 Jul 2025 20:13:22 -0000
> @@ -1516,10 +1516,7 @@ ip6_sysctl(int *name, u_int namelen, voi
> case IPV6CTL_MRTMIF:
> if (newp)
> return (EPERM);
> - NET_LOCK();
> - error = mrt6_sysctl_mif(oldp, oldlenp);
> - NET_UNLOCK();
> - return (error);
> + return (mrt6_sysctl_mif(oldp, oldlenp));
> case IPV6CTL_MRTMFC:
> if (newp)
> return (EPERM);
> Index: sys/netinet6/ip6_mroute.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v
> retrieving revision 1.151
> diff -u -p -r1.151 ip6_mroute.c
> --- sys/netinet6/ip6_mroute.c 23 Jul 2025 18:58:38 -0000 1.151
> +++ sys/netinet6/ip6_mroute.c 24 Jul 2025 20:13:22 -0000
> @@ -304,18 +304,36 @@ get_mif6_cnt(struct sioc_mif_req6 *req,
> int
> mrt6_sysctl_mif(void *oldp, size_t *oldlenp)
> {
> + TAILQ_HEAD(, ifnet) if_tmplist =
> + TAILQ_HEAD_INITIALIZER(if_tmplist);
> struct ifnet *ifp;
> caddr_t where = oldp;
> size_t needed, given;
> struct mif6 *mifp;
> struct mif6info minfo;
> + int error = 0;
>
> given = *oldlenp;
> needed = 0;
> memset(&minfo, 0, sizeof minfo);
> +
> + rw_enter_write(&if_tmplist_lock);
> + NET_LOCK_SHARED();
> +
> TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
> - if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL)
> + if (ifp->if_mcast6 != NULL) {
> + if_ref(ifp);
> + TAILQ_INSERT_TAIL(&if_tmplist, ifp, if_tmplist);
> + }
> + }
> + NET_UNLOCK_SHARED();
> +
> + TAILQ_FOREACH (ifp, &if_tmplist, if_tmplist) {
> + NET_LOCK_SHARED();
> + if ((mifp = (struct mif6 *)ifp->if_mcast6) == NULL) {
> + NET_UNLOCK_SHARED();
> continue;
> + }
>
> minfo.m6_mifi = mifp->m6_mifi;
> minfo.m6_flags = mifp->m6_flags;
> @@ -326,6 +344,7 @@ mrt6_sysctl_mif(void *oldp, size_t *oldl
> minfo.m6_bytes_in = mifp->m6_bytes_in;
> minfo.m6_bytes_out = mifp->m6_bytes_out;
> minfo.m6_rate_limit = mifp->m6_rate_limit;
> + NET_UNLOCK_SHARED();
>
> needed += sizeof(minfo);
> if (where && needed <= given) {
> @@ -333,10 +352,21 @@ mrt6_sysctl_mif(void *oldp, size_t *oldl
>
> error = copyout(&minfo, where, sizeof(minfo));
> if (error)
> - return (error);
> + break;
> where += sizeof(minfo);
> }
> }
> +
> + while ((ifp = TAILQ_FIRST(&if_tmplist))) {
> + TAILQ_REMOVE(&if_tmplist, ifp, if_tmplist);
> + if_put(ifp);
> + }
> +
> + rw_exit_write(&if_tmplist_lock);
> +
> + if (error)
> + return (error);
> +
> if (where) {
> *oldlenp = needed;
> if (given < needed)
ip6_sysctl(): push netlock down to mrt6_sysctl_mif()