iflib: call ether_ifdetach and netmap_detach before stop
From Jake: Calling ether_ifdetach after iflib_stop leads to a potential race where a stale ifp pointer can remain in the route entry list for IPv6 traffic. This will potentially cause a page fault or other system instability if the ifp pointer is accessed. Move both iflib_netmap_detach and ether_ifdetach to be called prior to iflib_stop. This avoids the race above, and helps ensure that other ifp references are removed before stopping the interface. Submitted by: Jacob Keller <jacob.e.keller@intel.com> Reviewed by: erj@, gallatin@, jhb@ MFC after: 3 days Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D22071
This commit is contained in:
parent
f1664f3258
commit
1558015e3e
@ -703,6 +703,7 @@ static int iflib_altq_if_transmit(if_t ifp, struct mbuf *m);
|
|||||||
#endif
|
#endif
|
||||||
static int iflib_register(if_ctx_t);
|
static int iflib_register(if_ctx_t);
|
||||||
static void iflib_deregister(if_ctx_t);
|
static void iflib_deregister(if_ctx_t);
|
||||||
|
static void iflib_unregister_vlan_handlers(if_ctx_t ctx);
|
||||||
static void iflib_init_locked(if_ctx_t ctx);
|
static void iflib_init_locked(if_ctx_t ctx);
|
||||||
static void iflib_add_device_sysctl_pre(if_ctx_t ctx);
|
static void iflib_add_device_sysctl_pre(if_ctx_t ctx);
|
||||||
static void iflib_add_device_sysctl_post(if_ctx_t ctx);
|
static void iflib_add_device_sysctl_post(if_ctx_t ctx);
|
||||||
@ -5007,6 +5008,9 @@ iflib_pseudo_deregister(if_ctx_t ctx)
|
|||||||
struct taskqgroup *tqg;
|
struct taskqgroup *tqg;
|
||||||
iflib_fl_t fl;
|
iflib_fl_t fl;
|
||||||
|
|
||||||
|
/* Unregister VLAN event handlers early */
|
||||||
|
iflib_unregister_vlan_handlers(ctx);
|
||||||
|
|
||||||
ether_ifdetach(ifp);
|
ether_ifdetach(ifp);
|
||||||
/* XXX drain any dependent tasks */
|
/* XXX drain any dependent tasks */
|
||||||
tqg = qgroup_if_io_tqg;
|
tqg = qgroup_if_io_tqg;
|
||||||
@ -5080,12 +5084,16 @@ iflib_device_deregister(if_ctx_t ctx)
|
|||||||
ctx->ifc_flags |= IFC_IN_DETACH;
|
ctx->ifc_flags |= IFC_IN_DETACH;
|
||||||
STATE_UNLOCK(ctx);
|
STATE_UNLOCK(ctx);
|
||||||
|
|
||||||
|
/* Unregister VLAN handlers before calling iflib_stop() */
|
||||||
|
iflib_unregister_vlan_handlers(ctx);
|
||||||
|
|
||||||
|
iflib_netmap_detach(ifp);
|
||||||
|
ether_ifdetach(ifp);
|
||||||
|
|
||||||
CTX_LOCK(ctx);
|
CTX_LOCK(ctx);
|
||||||
iflib_stop(ctx);
|
iflib_stop(ctx);
|
||||||
CTX_UNLOCK(ctx);
|
CTX_UNLOCK(ctx);
|
||||||
|
|
||||||
iflib_netmap_detach(ifp);
|
|
||||||
ether_ifdetach(ifp);
|
|
||||||
iflib_rem_pfil(ctx);
|
iflib_rem_pfil(ctx);
|
||||||
if (ctx->ifc_led_dev != NULL)
|
if (ctx->ifc_led_dev != NULL)
|
||||||
led_destroy(ctx->ifc_led_dev);
|
led_destroy(ctx->ifc_led_dev);
|
||||||
@ -5375,13 +5383,8 @@ iflib_register(if_ctx_t ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iflib_deregister(if_ctx_t ctx)
|
iflib_unregister_vlan_handlers(if_ctx_t ctx)
|
||||||
{
|
{
|
||||||
if_t ifp = ctx->ifc_ifp;
|
|
||||||
|
|
||||||
/* Remove all media */
|
|
||||||
ifmedia_removeall(&ctx->ifc_media);
|
|
||||||
|
|
||||||
/* Unregister VLAN events */
|
/* Unregister VLAN events */
|
||||||
if (ctx->ifc_vlan_attach_event != NULL) {
|
if (ctx->ifc_vlan_attach_event != NULL) {
|
||||||
EVENTHANDLER_DEREGISTER(vlan_config, ctx->ifc_vlan_attach_event);
|
EVENTHANDLER_DEREGISTER(vlan_config, ctx->ifc_vlan_attach_event);
|
||||||
@ -5392,6 +5395,19 @@ iflib_deregister(if_ctx_t ctx)
|
|||||||
ctx->ifc_vlan_detach_event = NULL;
|
ctx->ifc_vlan_detach_event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
iflib_deregister(if_ctx_t ctx)
|
||||||
|
{
|
||||||
|
if_t ifp = ctx->ifc_ifp;
|
||||||
|
|
||||||
|
/* Remove all media */
|
||||||
|
ifmedia_removeall(&ctx->ifc_media);
|
||||||
|
|
||||||
|
/* Ensure that VLAN event handlers are unregistered */
|
||||||
|
iflib_unregister_vlan_handlers(ctx);
|
||||||
|
|
||||||
/* Release kobject reference */
|
/* Release kobject reference */
|
||||||
kobj_delete((kobj_t) ctx, NULL);
|
kobj_delete((kobj_t) ctx, NULL);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user