LeavesHi guys, I think code for netif_receive_skb have a bug: int netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; int ret = NET_RX_DROP; unsigned short type = skb->protocol; /* some code skipped */ pt_prev = NULL; for (ptype = ptype_all; ptype; ptype = ptype->next) { if (!ptype->dev || ptype->dev == skb->dev) { if (pt_prev) { if (!pt_prev->data) { ret = deliver_to_old_ones(pt_prev, skb, 0); } else { atomic_inc(&skb->users); ret = pt_prev->func(skb, skb->dev, pt_prev); } /* Would be great to add this check here */ if ( ( ret == NET_RX_DROP ) || ( ret == NET_RX_BAD ) ) { /* Check here if skb was freed in pt_prev_>func(), if not - free it */ ... return ret; } } pt_prev = ptype; } } First of all, just imagine if we have only on TAP attached to ptype_all. In this case this TAP won't be called, because of pt_prev. ( BTW, why pt_prev, why we shouldn't call the function of first chain-link? ) In second case, imagine if we have three TAPs attached to ptype_all, and second TAP desided to be an universal firewall ( third one is just ordinar TAP ). If that second TAP will call kfree_skb ( skb ), and will return the code NET_RX_DROP or NET_RX_BAD, that return code will be overwritten by third TAP, which will get freed skb, and possible panic. The same issue for the bottom half of the function ( for ptype_base ). what if we will add the check for it? Like I added above. PS: BTW, how to check if skb has been freed ? I didn't found any function for it. Is it possible to add the flag, like skb->freed ? All the Best! Serge. - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html