netfilter: nf_tables: take module reference when starting a batch
authorFlorian Westphal <fw@strlen.de>
Wed, 11 Jul 2018 11:45:12 +0000 (13:45 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 18 Jul 2018 09:26:46 +0000 (11:26 +0200)
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nfnetlink.h
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink.c

index 3ecc305..4a520d3 100644 (file)
@@ -29,6 +29,7 @@ struct nfnetlink_subsystem {
        __u8 subsys_id;                 /* nfnetlink subsystem ID */
        __u8 cb_count;                  /* number of callbacks */
        const struct nfnl_callback *cb; /* callback for individual types */
+       struct module *owner;
        int (*commit)(struct net *net, struct sk_buff *skb);
        int (*abort)(struct net *net, struct sk_buff *skb);
        void (*cleanup)(struct net *net);
index 594b395..c16c481 100644 (file)
@@ -6603,6 +6603,7 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
        .abort          = nf_tables_abort,
        .cleanup        = nf_tables_cleanup,
        .valid_genid    = nf_tables_valid_genid,
+       .owner          = THIS_MODULE,
 };
 
 int nft_chain_validate_dependency(const struct nft_chain *chain,
index 94f9bca..dd1d7bc 100644 (file)
@@ -337,7 +337,14 @@ replay:
                return kfree_skb(skb);
        }
 
+       if (!try_module_get(ss->owner)) {
+               nfnl_unlock(subsys_id);
+               netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
+               return kfree_skb(skb);
+       }
+
        if (!ss->valid_genid(net, genid)) {
+               module_put(ss->owner);
                nfnl_unlock(subsys_id);
                netlink_ack(oskb, nlh, -ERESTART, NULL);
                return kfree_skb(skb);
@@ -472,6 +479,7 @@ done:
                nfnl_err_reset(&err_list);
                nfnl_unlock(subsys_id);
                kfree_skb(skb);
+               module_put(ss->owner);
                goto replay;
        } else if (status == NFNL_BATCH_DONE) {
                err = ss->commit(net, oskb);
@@ -491,6 +499,7 @@ done:
        nfnl_err_deliver(&err_list, oskb);
        nfnl_unlock(subsys_id);
        kfree_skb(skb);
+       module_put(ss->owner);
 }
 
 static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX + 1] = {