struct nf_queue_handler {
        int             (*outfn)(struct nf_queue_entry *entry,
                                 unsigned int queuenum);
-       void            (*nf_hook_drop)(struct net *net,
-                                       const struct nf_hook_entry *hooks);
+       unsigned int    (*nf_hook_drop)(struct net *net);
 };
 
 void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
 
 void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
 {
        struct nf_hook_entry *p = __nf_unregister_net_hook(net, reg);
+       unsigned int nfq;
 
        if (!p)
                return;
 
        synchronize_net();
-       nf_queue_nf_hook_drop(net, p);
+
        /* other cpu might still process nfqueue verdict that used reg */
-       synchronize_net();
+       nfq = nf_queue_nf_hook_drop(net);
+       if (nfq)
+               synchronize_net();
        kfree(p);
 }
 EXPORT_SYMBOL(nf_unregister_net_hook);
                             unsigned int hookcount)
 {
        struct nf_hook_entry *to_free[16];
-       unsigned int i, n;
+       unsigned int i, n, nfq;
 
        do {
                n = min_t(unsigned int, hookcount, ARRAY_SIZE(to_free));
 
                synchronize_net();
 
-               for (i = 0; i < n; i++) {
-                       if (to_free[i])
-                               nf_queue_nf_hook_drop(net, to_free[i]);
-               }
-
-               synchronize_net();
+               /* need 2nd synchronize_net() if nfqueue is used, skb
+                * can get reinjected right before nf_queue_hook_drop()
+                */
+               nfq = nf_queue_nf_hook_drop(net);
+               if (nfq)
+                       synchronize_net();
 
                for (i = 0; i < n; i++)
                        kfree(to_free[i]);
 
 /* nf_queue.c */
 int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
             struct nf_hook_entry **entryp, unsigned int verdict);
-void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry);
+unsigned int nf_queue_nf_hook_drop(struct net *net);
 int __init netfilter_queue_init(void);
 
 /* nf_log.c */
 
 }
 EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
 
-void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry)
+unsigned int nf_queue_nf_hook_drop(struct net *net)
 {
        const struct nf_queue_handler *qh;
+       unsigned int count = 0;
 
        rcu_read_lock();
        qh = rcu_dereference(net->nf.queue_handler);
        if (qh)
-               qh->nf_hook_drop(net, entry);
+               count = qh->nf_hook_drop(net);
        rcu_read_unlock();
+
+       return count;
 }
 
 static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
 
        .notifier_call  = nfqnl_rcv_dev_event,
 };
 
-static int nf_hook_cmp(struct nf_queue_entry *entry, unsigned long entry_ptr)
-{
-       return rcu_access_pointer(entry->hook) ==
-               (struct nf_hook_entry *)entry_ptr;
-}
-
-static void nfqnl_nf_hook_drop(struct net *net,
-                              const struct nf_hook_entry *hook)
+static unsigned int nfqnl_nf_hook_drop(struct net *net)
 {
        struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+       unsigned int instances = 0;
        int i;
 
        rcu_read_lock();
                struct nfqnl_instance *inst;
                struct hlist_head *head = &q->instance_table[i];
 
-               hlist_for_each_entry_rcu(inst, head, hlist)
-                       nfqnl_flush(inst, nf_hook_cmp, (unsigned long)hook);
+               hlist_for_each_entry_rcu(inst, head, hlist) {
+                       nfqnl_flush(inst, NULL, 0);
+                       instances++;
+               }
        }
        rcu_read_unlock();
+
+       return instances;
 }
 
 static int