X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b36670cedae0009469e8ee117453de831de64a6b..c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1:/bsd/net/dlil.c diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index 5f766f6b7..4b24b76f9 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -78,8 +78,6 @@ #define DLIL_PRINTF kprintf #endif -//#define DLIL_ALWAYS_DELAY_DETACH 1 - enum { kProtoKPI_DLIL = 0, kProtoKPI_v1 = 1 @@ -553,7 +551,6 @@ dlil_init(void) /* Setup the lock groups we will use */ grp_attributes = lck_grp_attr_alloc_init(); - lck_grp_attr_setdefault(grp_attributes); dlil_lock_group = lck_grp_alloc_init("dlil internal locks", grp_attributes); #if IFNET_RW_LOCK @@ -568,10 +565,8 @@ dlil_init(void) /* Setup the lock attributes we will use */ lck_attributes = lck_attr_alloc_init(); - lck_attr_setdefault(lck_attributes); ifnet_lock_attr = lck_attr_alloc_init(); - lck_attr_setdefault(ifnet_lock_attr); dlil_input_lock = lck_spin_alloc_init(input_lock_grp, lck_attributes); input_lock_grp = 0; @@ -632,34 +627,59 @@ dlil_detach_filter_internal(interface_filter_t filter, int detached) { int retval = 0; - - /* Take the write lock */ -#if DLIL_ALWAYS_DELAY_DETACH - retval = EDEADLK; -#else - if (detached == 0 && (retval = dlil_write_begin()) != 0) -#endif - { + if (detached == 0) { + ifnet_t ifp = NULL; + interface_filter_t entry = NULL; + + /* Take the write lock */ + retval = dlil_write_begin(); + if (retval != 0 && retval != EDEADLK) + return retval; + + /* + * At this point either we have the write lock (retval == 0) + * or we couldn't get it (retval == EDEADLK) because someone + * else up the stack is holding the read lock. It is safe to + * read, either the read or write is held. Verify the filter + * parameter before proceeding. + */ + ifnet_head_lock_shared(); + TAILQ_FOREACH(ifp, &ifnet_head, if_link) { + TAILQ_FOREACH(entry, &ifp->if_flt_head, filt_next) { + if (entry == filter) + break; + } + if (entry == filter) + break; + } + ifnet_head_done(); + + if (entry != filter) { + /* filter parameter is not a valid filter ref */ + if (retval == 0) { + dlil_write_end(); + } + return EINVAL; + } + if (retval == EDEADLK) { /* Perform a delayed detach */ filter->filt_detaching = 1; dlil_detach_waiting = 1; wakeup(&dlil_detach_waiting); - retval = 0; + return 0; } - return retval; - } - - if (detached == 0) - TAILQ_REMOVE(&filter->filt_ifp->if_flt_head, filter, filt_next); - - /* release the write lock */ - if (detached == 0) + + /* Remove the filter from the list */ + TAILQ_REMOVE(&ifp->if_flt_head, filter, filt_next); dlil_write_end(); + } + /* Call the detached funciton if there is one */ if (filter->filt_detached) filter->filt_detached(filter->filt_cookie, filter->filt_ifp); + /* Free the filter */ FREE(filter, M_NKE); return retval; @@ -668,6 +688,8 @@ dlil_detach_filter_internal(interface_filter_t filter, int detached) void dlil_detach_filter(interface_filter_t filter) { + if (filter == NULL) + return; dlil_detach_filter_internal(filter, 0); } @@ -972,6 +994,7 @@ dlil_event(struct ifnet *ifp, struct kern_event_msg *event) return result; } +int dlil_output_list( struct ifnet* ifp, u_long proto_family, @@ -1964,12 +1987,7 @@ dlil_detach_protocol(struct ifnet *ifp, u_long proto_family) int use_reached_zero = 0; -#if DLIL_ALWAYS_DELAY_DETACH - { - retval = EDEADLK; -#else if ((retval = dlil_write_begin()) != 0) { -#endif if (retval == EDEADLK) { retval = 0; dlil_read_begin();