📄 ieee80211_skb.c.svn-base
字号:
skb_print_message(0 /* show_counter */, skb, func, line, "ERROR: Untracked skb received. Probable duplicate free error!"); dump_stack(); return; } /* If free is unacceptable for current user count, report the error. */ if (atomic_read(&skb->users) < 1) { skb_print_message(0 /* show_counter */, skb, func, line, "ERROR: free an skb with %d users", atomic_read(&skb->users)); dump_stack(); return; } if (skb_shared(skb)) { atomic_dec(&skb_refs_counter); print_skb_refchange_message(skb, -1, func2, line2); } else { if (SKB_NI(skb) != NULL) { printk(KERN_ERR "%s:%d - ERROR: non-NULL node pointer in %p, %p<" MAC_FMT ">! " "Driver Leak Detected!\n", __func__, __LINE__, skb, SKB_NI(skb), MAC_ADDR(SKB_NI(skb)->ni_macaddr)); dump_stack(); /* Allow the leak and let programmer fix it, but do not * report it again in the destructor. */ SKB_NI(skb) = NULL; } untrack_skb(skb, -1, func, line); }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if ((in_irq() || irqs_disabled()) && (type == UNREF_USE_KFREE_SKB || type == UNREF_USE_DEV_KFREE_SKB)) { skb_print_message(0 /* show_counter */, skb, func, line, "ERROR: free an skb in interrupt context using a non-" "safe form of skb free function."); type = UNREF_USE_DEV_KFREE_SKB_ANY; dump_stack(); }#endif switch (type) { case UNREF_USE_DEV_KFREE_SKB_ANY: dev_kfree_skb_any(skb); break; case UNREF_USE_DEV_KFREE_SKB_IRQ: dev_kfree_skb_irq(skb); break; case UNREF_USE_DEV_KFREE_SKB: /* NOTE: dev_kfree_skb is a macro pointing to kfree_skb, so * fallthrough... */ case UNREF_USE_KFREE_SKB: /* fallthrough */ default: kfree_skb(skb); break; }}/* Assumes SKB reference counter has already been updated and reports count as * atomic_read(&skb->users). */static struct sk_buff *ref_skb(struct sk_buff *skb, const char *func, int line) { if (NULL == skb) { skb_print_message(0 /* show_counter */, skb, func, line, "ERROR: NULL skb received. No changes made."); dump_stack(); return NULL; } if (!M_FLAG_GET(skb, M_SKB_TRACKED)) { skb_print_message(0 /* show_counter */, skb, func, line, "ERROR: Untracked skb received. Probable use after free! " "No changes made."); dump_stack(); return skb; } print_skb_refchange_message(skb, 0, func, line); return skb;}#endif /* #ifdef IEEE80211_DEBUG_REFCNT *//******************************************************************************* * Public API ******************************************************************************//* ieee80211_dev_kfree_skb will release one reference from SKB. * If SKB refcount is going to zero: * - Free the node reference and set it to null. * - Break the linked list, clearing next skb's prev pointer if possible. */void ieee80211_dev_kfree_skb(struct sk_buff **pskb) { struct sk_buff *skb; /* Do not fail on null, as we are going to use this in cleanup code. */ if (!pskb || !(skb = *pskb)) return; /* Release the SKB references, for fragments of chain that are * unshared... starting at skb passed in. */ if (skb->prev == NULL) { if (skb->next != NULL) skb->next->prev = NULL; skb->next = NULL; } if (SKB_NI(skb) != NULL) ieee80211_unref_node(&SKB_NI(skb));#ifdef IEEE80211_DEBUG_REFCNT unref_skb(skb, UNREF_USE_DEV_KFREE_SKB_ANY, __func__, __LINE__);#else dev_kfree_skb_any(skb);#endif *pskb = NULL;}/* ieee80211_dev_kfree_skb_list will invoke ieee80211_dev_kfree_skb on each node in * a list of skbs, starting with the first. */voidieee80211_dev_kfree_skb_list(struct sk_buff **pskb) { struct sk_buff *skb, *tskb; /* Do not fail on null, as we are going to use this in cleanup code */ if (!pskb || !(skb = *pskb)) return; while (skb) { tskb = skb->next; ieee80211_dev_kfree_skb(&skb); skb = tskb; } *pskb = NULL;}struct sk_buff *ieee80211_dev_alloc_skb(int size) { struct sk_buff *skb = dev_alloc_skb(size); if (skb == NULL) { skb_print_message( 0 /* show_counter */, NULL /* skb */, __func__, __LINE__, "sk_buff allocation of size %u failed", size); return NULL; }#ifdef IEEE80211_DEBUG_REFCNT return track_skb(skb, 0, __func__, __LINE__);#else return skb;#endif}voidieee80211_skb_track(struct sk_buff *skb) {#ifdef IEEE80211_DEBUG_REFCNT track_skb(skb, 0 /* users_adjustment */, __func__, __LINE__);#else /* Just a dumb counter, in no-debug builds */ atomic_inc(&skb_total_counter);#endif /* #ifdef IEEE80211_DEBUG_REFCNT */}voidieee80211_skb_untrack(struct sk_buff *skb) { /* Just a dumb counter, in no-debug builds */ atomic_dec(&skb_total_counter);}#ifdef IEEE80211_DEBUG_REFCNTint ieee80211_skb_counter(void) { return atomic_read(&skb_total_counter);}intieee80211_skb_references(void) { return atomic_read(&skb_refs_counter);}#endif /* #ifdef IEEE80211_DEBUG_REFCNT *//******************************************************************************* * skbuff leak/refcount debugging Replacement Functions * PUT last in order to avoid conflicts with use of original functions in * inline functions above this point. ******************************************************************************/#ifdef IEEE80211_DEBUG_REFCNTint vlan_hwaccel_rx_debug(struct sk_buff *skb, struct vlan_group *grp, unsigned short vlan_tag, const char *func, int line) { return vlan_hwaccel_rx( untrack_skb(skb, 0, __func__, __LINE__), grp, vlan_tag);}int netif_rx_debug(struct sk_buff *skb, const char *func, int line) { return netif_rx(untrack_skb(skb, 0, __func__, __LINE__));}struct sk_buff *alloc_skb_debug(unsigned int length, gfp_t gfp_mask, const char *func, int line) { return track_skb(alloc_skb(length, gfp_mask), 0 /* users_adjustment */, __func__, __LINE__);}struct sk_buff *dev_alloc_skb_debug(unsigned int length, const char *func, int line){ return track_skb(dev_alloc_skb(length), 0 /* users_adjustment */, __func__, __LINE__);}struct sk_buff *skb_clone_debug(struct sk_buff *skb, gfp_t pri, const char *func, int line) { return track_skb( clean_clone_or_copy(skb_clone(skb, pri)), 0 /* users_adjustment */, __func__, __LINE__);}struct sk_buff *skb_copy_debug(struct sk_buff *skb, gfp_t pri, const char *func, int line){ return track_skb( clean_clone_or_copy(skb_copy(skb, pri)), 0 /* users_adjustment */, __func__, __LINE__);}struct sk_buff *skb_get_debug(struct sk_buff *skb, const char *func, int line){ return ref_skb(skb_get(skb), __func__, __LINE__);}struct sk_buff *skb_realloc_headroom_debug(struct sk_buff *skb, unsigned int headroom, const char *func, int line){ /* skb_realloc_headroom ALWAYS returns a copy or a clone, refcount of * new one is always zero and refcount of original is not touched. */ return track_skb( clean_clone_or_copy( skb_realloc_headroom(skb, headroom)), 0 /* users_adjustment */, __func__, __LINE__);}struct sk_buff *pskb_copy_debug(struct sk_buff *skb, gfp_t pri, const char *func, int line){ return track_skb( clean_clone_or_copy(pskb_copy(skb, pri)), 0 /* users_adjustment */, __func__, __LINE__);}int dev_queue_xmit_debug(struct sk_buff *skb, const char *func, int line){ return dev_queue_xmit(untrack_skb(skb, 0, __func__, __LINE__));}struct sk_buff *skb_share_check_debug(struct sk_buff *skb, gfp_t pri, const char *func, int line){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) might_sleep_if(pri & __GFP_WAIT);#endif if (skb_shared(skb)) { struct sk_buff *nskb = track_skb( clean_clone_or_copy(skb_clone(skb, pri)), 0, __func__, __LINE__); unref_skb(skb, UNREF_USE_DEV_KFREE_SKB_ANY, __func__, __LINE__); skb = nskb; } return skb;}void kfree_skb_fast_debug(struct sk_buff *skb, const char *func, int line){ /* NOT so fast... */ unref_skb(skb, UNREF_USE_DEV_KFREE_SKB_ANY, func, line, __func__, __LINE__);}struct sk_buff *skb_unshare_debug(struct sk_buff *skb, gfp_t pri, const char *func, int line){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) might_sleep_if(pri & __GFP_WAIT);#endif if (skb_cloned(skb)) { struct sk_buff *nskb = track_skb( clean_clone_or_copy(skb_copy(skb, pri)), 0, __func__, __LINE__); unref_skb(skb, UNREF_USE_DEV_KFREE_SKB_ANY, __func__, __LINE__); skb = nskb; } return skb;}struct sk_buff *skb_copy_expand_debug(const struct sk_buff *skb, int newheadroom, int newtailroom, gfp_t gfp_mask, const char *func, int line){ return track_skb( clean_clone_or_copy( skb_copy_expand(skb, newheadroom, newtailroom, gfp_mask)), 0 /* users_adjustment */, __func__, __LINE__);}EXPORT_SYMBOL(vlan_hwaccel_rx_debug);EXPORT_SYMBOL(netif_rx_debug);EXPORT_SYMBOL(alloc_skb_debug);EXPORT_SYMBOL(dev_alloc_skb_debug);EXPORT_SYMBOL(skb_clone_debug);EXPORT_SYMBOL(skb_copy_debug);EXPORT_SYMBOL(skb_get_debug);EXPORT_SYMBOL(skb_realloc_headroom_debug);EXPORT_SYMBOL(pskb_copy_debug);EXPORT_SYMBOL(dev_queue_xmit_debug);EXPORT_SYMBOL(skb_share_check_debug);EXPORT_SYMBOL(kfree_skb_fast_debug);EXPORT_SYMBOL(skb_unshare_debug);EXPORT_SYMBOL(skb_copy_expand_debug);EXPORT_SYMBOL(ieee80211_skb_counter);EXPORT_SYMBOL(ieee80211_skb_references);#endif /* #ifdef IEEE80211_DEBUG_REFCNT */EXPORT_SYMBOL(ieee80211_dev_alloc_skb);EXPORT_SYMBOL(ieee80211_skb_untrack);EXPORT_SYMBOL(ieee80211_dev_kfree_skb_list);EXPORT_SYMBOL(ieee80211_dev_kfree_skb);EXPORT_SYMBOL(ieee80211_skb_track);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -