netfilter: nf_tables: bogus EBUSY when deleting flowtable after flush
authorLaura Garcia Liebana <nevola@gmail.com>
Tue, 24 Sep 2019 12:42:44 +0000 (14:42 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 25 Sep 2019 09:01:19 +0000 (11:01 +0200)
The deletion of a flowtable after a flush in the same transaction
results in EBUSY. This patch adds an activation and deactivation of
flowtables in order to update the _use_ counter.

Signed-off-by: Laura Garcia Liebana <nevola@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_flow_offload.c

index a26d64056fc839c7c963220fcac2568244270f32..001d294edf57d85bb3424c3e5fa8a6b8b683dfe7 100644 (file)
@@ -1183,6 +1183,10 @@ struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
                                           const struct nlattr *nla,
                                           u8 genmask);
 
+void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
+                                   struct nft_flowtable *flowtable,
+                                   enum nft_trans_phase phase);
+
 void nft_register_flowtable_type(struct nf_flowtable_type *type);
 void nft_unregister_flowtable_type(struct nf_flowtable_type *type);
 
index 6dc46f9b5f7b430164049b62a30aafc693376e74..d481f9baca2f8b225afbec0069ac8a3b73e1659b 100644 (file)
@@ -5598,6 +5598,22 @@ struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
 }
 EXPORT_SYMBOL_GPL(nft_flowtable_lookup);
 
+void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
+                                   struct nft_flowtable *flowtable,
+                                   enum nft_trans_phase phase)
+{
+       switch (phase) {
+       case NFT_TRANS_PREPARE:
+       case NFT_TRANS_ABORT:
+       case NFT_TRANS_RELEASE:
+               flowtable->use--;
+               /* fall through */
+       default:
+               return;
+       }
+}
+EXPORT_SYMBOL_GPL(nf_tables_deactivate_flowtable);
+
 static struct nft_flowtable *
 nft_flowtable_lookup_byhandle(const struct nft_table *table,
                              const struct nlattr *nla, u8 genmask)
index 22cf236eb5d520954a2731e56e93163017178182..f29bbc74c4bf48c0397a49db91369b06be78dd6f 100644 (file)
@@ -177,6 +177,23 @@ static int nft_flow_offload_init(const struct nft_ctx *ctx,
        return nf_ct_netns_get(ctx->net, ctx->family);
 }
 
+static void nft_flow_offload_deactivate(const struct nft_ctx *ctx,
+                                       const struct nft_expr *expr,
+                                       enum nft_trans_phase phase)
+{
+       struct nft_flow_offload *priv = nft_expr_priv(expr);
+
+       nf_tables_deactivate_flowtable(ctx, priv->flowtable, phase);
+}
+
+static void nft_flow_offload_activate(const struct nft_ctx *ctx,
+                                     const struct nft_expr *expr)
+{
+       struct nft_flow_offload *priv = nft_expr_priv(expr);
+
+       priv->flowtable->use++;
+}
+
 static void nft_flow_offload_destroy(const struct nft_ctx *ctx,
                                     const struct nft_expr *expr)
 {
@@ -205,6 +222,8 @@ static const struct nft_expr_ops nft_flow_offload_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_flow_offload)),
        .eval           = nft_flow_offload_eval,
        .init           = nft_flow_offload_init,
+       .activate       = nft_flow_offload_activate,
+       .deactivate     = nft_flow_offload_deactivate,
        .destroy        = nft_flow_offload_destroy,
        .validate       = nft_flow_offload_validate,
        .dump           = nft_flow_offload_dump,