]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
netfilter: nf_tables: add destroy_clone expression
authorPablo Neira Ayuso <pablo@netfilter.org>
Sat, 2 Jun 2018 21:38:50 +0000 (23:38 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 2 Jun 2018 22:02:11 +0000 (00:02 +0200)
Before this patch, cloned expressions are released via ->destroy. This
is a problem for the new connlimit expression since the ->destroy path
drop a reference on the conntrack modules and it unregisters hooks. The
new ->destroy_clone provides context that this expression is being
released from the packet path, so it is mirroring ->clone(), where
neither module reference is dropped nor hooks need to be unregistered -
because this done from the control plane path from the ->init() path.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_counter.c

index 871cb3b012e978886cbdffb99210d0173de5c836..83e7b83ecf3ed0b4568b97369468c852fc7c4940 100644 (file)
@@ -745,6 +745,8 @@ struct nft_expr_ops {
                                                      const struct nft_expr *expr);
        void                            (*destroy)(const struct nft_ctx *ctx,
                                                   const struct nft_expr *expr);
+       void                            (*destroy_clone)(const struct nft_ctx *ctx,
+                                                        const struct nft_expr *expr);
        int                             (*dump)(struct sk_buff *skb,
                                                const struct nft_expr *expr);
        int                             (*validate)(const struct nft_ctx *ctx,
index 12463984dd5c6f9796901ffc179a8c4feb63dac2..0a6eafa498795d309df0a28fd69ce299804309ed 100644 (file)
@@ -4046,8 +4046,16 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
        nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
        if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
                nft_data_release(nft_set_ext_data(ext), set->dtype);
-       if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
-               nf_tables_expr_destroy(&ctx, nft_set_ext_expr(ext));
+       if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) {
+               struct nft_expr *expr = nft_set_ext_expr(ext);
+
+               if (expr->ops->destroy_clone) {
+                       expr->ops->destroy_clone(&ctx, expr);
+                       module_put(expr->ops->type->owner);
+               } else {
+                       nf_tables_expr_destroy(&ctx, expr);
+               }
+       }
        if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
                (*nft_set_ext_obj(ext))->use--;
        kfree(elem);
index e59a74d6b7d6a16222d94c2fb7eb965966aa3b8a..a61d7edfc290d854e9216d015efa22c38aacc39b 100644 (file)
@@ -258,6 +258,7 @@ static const struct nft_expr_ops nft_counter_ops = {
        .eval           = nft_counter_eval,
        .init           = nft_counter_init,
        .destroy        = nft_counter_destroy,
+       .destroy_clone  = nft_counter_destroy,
        .dump           = nft_counter_dump,
        .clone          = nft_counter_clone,
 };