]> git.ipfire.org Git - people/ms/linux.git/blobdiff - net/netfilter/nfnetlink_queue.c
NFQUEUE: Hold RCU read lock while calling nf_reinject
[people/ms/linux.git] / net / netfilter / nfnetlink_queue.c
index 4c3fbaaeb10303d48c1c388ef8c9e2b8aedbd716..b12cc5d2131088eb0af7d99a1c5eb404441dec21 100644 (file)
@@ -228,19 +228,20 @@ static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
        struct nf_ct_hook *ct_hook;
        int err;
 
+       rcu_read_lock();
+
        if (verdict == NF_ACCEPT ||
            verdict == NF_REPEAT ||
            verdict == NF_STOP) {
-               rcu_read_lock();
                ct_hook = rcu_dereference(nf_ct_hook);
                if (ct_hook) {
                        err = ct_hook->update(entry->state.net, entry->skb);
                        if (err < 0)
                                verdict = NF_DROP;
                }
-               rcu_read_unlock();
        }
        nf_reinject(entry, verdict);
+       rcu_read_unlock();
 }
 
 static void
@@ -560,7 +561,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                goto nla_put_failure;
 
        if (indev && entskb->dev &&
-           entskb->mac_header != entskb->network_header) {
+           skb_mac_header_was_set(entskb) &&
+           skb_mac_header_len(entskb) != 0) {
                struct nfqnl_msg_packet_hw phw;
                int len;
 
@@ -709,9 +711,15 @@ static struct nf_queue_entry *
 nf_queue_entry_dup(struct nf_queue_entry *e)
 {
        struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
-       if (entry)
-               nf_queue_entry_get_refs(entry);
-       return entry;
+
+       if (!entry)
+               return NULL;
+
+       if (nf_queue_entry_get_refs(entry))
+               return entry;
+
+       kfree(entry);
+       return NULL;
 }
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)