Hi, When creating, changing and destroying vlan interfaces multiple times, root can crash the OpenBSD 5.8 kernel with ifconfig.
The code in -current has been implemented differently, so this fix only applies to 5.8. As I cannot test it with -current machines, could someone with OpenBSD 5.8 and some funky vlan configuration run this diff? When I get enough positive reports, I will commit to 5.8-stable. 5.7 is not affected. bluhm Index: net/if_vlan.c =================================================================== RCS file: /mount/cvsdev/cvs/openbsd/src/sys/net/if_vlan.c,v retrieving revision 1.135 diff -u -p -r1.135 if_vlan.c --- net/if_vlan.c 20 Jul 2015 22:16:41 -0000 1.135 +++ net/if_vlan.c 11 Jan 2016 17:34:19 -0000 @@ -347,6 +347,7 @@ vlan_input(struct ifnet *ifp, struct mbu int vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag) { + struct ifih *vlan_ifih; struct sockaddr_dl *sdl1, *sdl2; struct vlan_taghash *tagh; u_int flags; @@ -358,15 +359,17 @@ vlan_config(struct ifvlan *ifv, struct i return (0); /* Can we share an ifih between multiple vlan(4) instances? */ - ifv->ifv_ifih = SLIST_FIRST(&p->if_inputs); - if (ifv->ifv_ifih->ifih_input != vlan_input) { - ifv->ifv_ifih = malloc(sizeof(*ifv->ifv_ifih), M_DEVBUF, + vlan_ifih = SLIST_FIRST(&p->if_inputs); + if (vlan_ifih->ifih_input != vlan_input) { + vlan_ifih = malloc(sizeof(*vlan_ifih), M_DEVBUF, M_NOWAIT); - if (ifv->ifv_ifih == NULL) + if (vlan_ifih == NULL) return (ENOMEM); - ifv->ifv_ifih->ifih_input = vlan_input; - ifv->ifv_ifih->ifih_refcnt = 0; + vlan_ifih->ifih_input = vlan_input; + vlan_ifih->ifih_refcnt = 0; } + /* Do no free our reference during vlan_unconfig() */ + ++vlan_ifih->ifih_refcnt; /* Remember existing interface flags and reset the interface */ flags = ifv->ifv_flags; @@ -437,8 +440,9 @@ vlan_config(struct ifvlan *ifv, struct i s = splnet(); /* Change input handler of the physical interface. */ - if (++ifv->ifv_ifih->ifih_refcnt == 1) - SLIST_INSERT_HEAD(&p->if_inputs, ifv->ifv_ifih, ifih_next); + ifv->ifv_ifih = vlan_ifih; + if (vlan_ifih->ifih_refcnt == 1) + SLIST_INSERT_HEAD(&p->if_inputs, vlan_ifih, ifih_next); LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list); splx(s);