I would like an explanation of the root cause.  What commit broke this?

Visa Hankala <v...@openbsd.org> wrote:

> On Fri, Apr 10, 2020 at 10:16:47AM -0400, David Hill wrote:
> > On a April 9, 2020 cvs built machine:
> > 
> > An splassert shows when I add or delete vlan0 on bridge0
> > 
> > # ifconfig bridge0 add vlan0
> > splassert: vlan_ioctl: want 2 have 0
> > Starting stack trace...
> > vlan_ioctl(ffff800000936800,80206910,ffff80003316f318) at vlan_ioctl+0x65
> > ifpromisc(ffff800000936800,1) at ifpromisc+0xbb
> > bridge_ioctl(ffff8000009da000,8060693c,ffff80003316f520) at
> > bridge_ioctl+0x8c8
> > ifioctl(fffffd811e7e5e40,8060693c,ffff80003316f520,ffff800032fd49e8) at
> > ifioctl+0xa03
> > soo_ioctl(fffffd81015768e8,8060693c,ffff80003316f520,ffff800032fd49e8) at
> > soo_ioctl+0x171
> > sys_ioctl(ffff800032fd49e8,ffff80003316f630,ffff80003316f690) at
> > sys_ioctl+0x2df
> > syscall(ffff80003316f700) at syscall+0x389
> > Xsyscall() at Xsyscall+0x128
> > end of kernel
> > end trace frame: 0x7f7ffffdcef0, count: 249
> > End of stack trace.
> > 
> > # ifconfig bridge0 del vlan0
> > splassert: vlan_ioctl: want 2 have 0
> > Starting stack trace...
> > vlan_ioctl(ffff800000936800,80206910,ffff80003316ee78) at vlan_ioctl+0x65
> > ifpromisc(ffff800000936800,0) at ifpromisc+0xbb
> > bridge_ifremove(ffff8000009ed900) at bridge_ifremove+0xa4
> > bridge_ioctl(ffff8000009da000,8060693d,ffff80003316f0c0) at
> > bridge_ioctl+0x91e
> > ifioctl(fffffd811e7e5e40,8060693d,ffff80003316f0c0,ffff800032fd49e8) at
> > ifioctl+0xa03
> > soo_ioctl(fffffd81015768e8,8060693d,ffff80003316f0c0,ffff800032fd49e8) at
> > soo_ioctl+0x171
> > sys_ioctl(ffff800032fd49e8,ffff80003316f1d0,ffff80003316f230) at
> > sys_ioctl+0x2df
> > syscall(ffff80003316f2a0) at syscall+0x389
> > Xsyscall() at Xsyscall+0x128
> > end of kernel
> > end trace frame: 0x7f7fffff6a20, count: 248
> 
> Acquiring NET_LOCK() when calling ifpromisc() seems to help.
> This is similar to what bpf(4) does.
> 
> It looks that besides bridge(4), there are other places in the kernel
> where ifpromisc() is called without NET_LOCK().
> 
> Index: net/if_bridge.c
> ===================================================================
> RCS file: src/sys/net/if_bridge.c,v
> retrieving revision 1.338
> diff -u -p -r1.338 if_bridge.c
> --- net/if_bridge.c   6 Nov 2019 03:51:26 -0000       1.338
> +++ net/if_bridge.c   10 Apr 2020 19:05:05 -0000
> @@ -313,7 +313,9 @@ bridge_ioctl(struct ifnet *ifp, u_long c
>                       break;
>               }
>  
> +             NET_LOCK();
>               error = ifpromisc(ifs, 1);
> +             NET_UNLOCK();
>               if (error != 0) {
>                       free(bif, M_DEVBUF, sizeof(*bif));
>                       break;
> @@ -558,7 +560,9 @@ bridge_ifremove(struct bridge_iflist *bi
>       }
>  
>       bif->ifp->if_bridgeidx = 0;
> +     NET_LOCK();
>       error = ifpromisc(bif->ifp, 0);
> +     NET_UNLOCK();
>  
>       bridge_rtdelete(sc, bif->ifp, 0);
>       bridge_flushrule(bif);
> 

Reply via email to