[PATCH 1/3 nf-next] netfilter: nf_tables: add release callback in nft_expr_type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds the new release callback to release resources
allocated in nft_expr_type->select_ops.
This release callback can be used by error path in the
nf_tables_newrule routine.
Only the select_ops of the nft_compat.c allocates memory and holds
modules so far.

Signed-off-by: Taehee Yoo <ap420073@xxxxxxxxx>
---
 include/net/netfilter/nf_tables.h |  2 ++
 net/netfilter/nft_compat.c        | 52 +++++++++++++++++++++------------------
 2 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index cd368d1..2e71dc7 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -688,6 +688,7 @@ static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
  *	struct nft_expr_type - nf_tables expression type
  *
  *	@select_ops: function to select nft_expr_ops
+ *	@release : function to release
  *	@ops: default ops, used when no select_ops functions is present
  *	@list: used internally
  *	@name: Identifier
@@ -700,6 +701,7 @@ static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
 struct nft_expr_type {
 	const struct nft_expr_ops	*(*select_ops)(const struct nft_ctx *,
 						       const struct nlattr * const tb[]);
+	void				(*release)(const struct nft_expr_ops *ops);
 	const struct nft_expr_ops	*ops;
 	struct list_head		list;
 	const char			*name;
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 8e23726..31ffe27 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -236,25 +236,20 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	if (ctx->nla[NFTA_RULE_COMPAT]) {
 		ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
 		if (ret < 0)
-			goto err;
+			return ret;
 	}
 
 	nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
 
 	ret = xt_check_target(&par, size, proto, inv);
 	if (ret < 0)
-		goto err;
+		return ret;
 
 	/* The standard target cannot be used */
-	if (target->target == NULL) {
-		ret = -EINVAL;
-		goto err;
-	}
+	if (!target->target)
+		return -EINVAL;
 
 	return 0;
-err:
-	module_put(target->me);
-	return ret;
 }
 
 static void
@@ -268,11 +263,8 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 	par.target = target;
 	par.targinfo = info;
 	par.family = ctx->family;
-	if (par.target->destroy != NULL)
+	if (par.target->destroy)
 		par.target->destroy(&par);
-
-	nft_xt_put(container_of(expr->ops, struct nft_xt, ops));
-	module_put(target->me);
 }
 
 static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -421,19 +413,16 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	if (ctx->nla[NFTA_RULE_COMPAT]) {
 		ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
 		if (ret < 0)
-			goto err;
+			return ret;
 	}
 
 	nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
 
 	ret = xt_check_match(&par, size, proto, inv);
 	if (ret < 0)
-		goto err;
+		return ret;
 
 	return 0;
-err:
-	module_put(match->me);
-	return ret;
 }
 
 static void
@@ -447,11 +436,8 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 	par.match = match;
 	par.matchinfo = info;
 	par.family = ctx->family;
-	if (par.match->destroy != NULL)
+	if (par.match->destroy)
 		par.match->destroy(&par);
-
-	nft_xt_put(container_of(expr->ops, struct nft_xt, ops));
-	module_put(match->me);
 }
 
 static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -674,7 +660,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 
 	/* This is the first time we use this match, allocate operations */
 	nft_match = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
-	if (nft_match == NULL) {
+	if (!nft_match) {
 		err = -ENOMEM;
 		goto err;
 	}
@@ -697,9 +683,18 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 	return ERR_PTR(err);
 }
 
+static void nft_match_release(const struct nft_expr_ops *ops)
+{
+	struct xt_match *match = ops->data;
+
+	nft_xt_put(container_of(ops, struct nft_xt, ops));
+	module_put(match->me);
+}
+
 static struct nft_expr_type nft_match_type __read_mostly = {
 	.name		= "match",
 	.select_ops	= nft_match_select_ops,
+	.release	= nft_match_release,
 	.policy		= nft_match_policy,
 	.maxattr	= NFTA_MATCH_MAX,
 	.owner		= THIS_MODULE,
@@ -759,7 +754,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
 
 	/* This is the first time we use this target, allocate operations */
 	nft_target = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
-	if (nft_target == NULL) {
+	if (!nft_target) {
 		err = -ENOMEM;
 		goto err;
 	}
@@ -786,9 +781,18 @@ nft_target_select_ops(const struct nft_ctx *ctx,
 	return ERR_PTR(err);
 }
 
+static void nft_target_release(const struct nft_expr_ops *ops)
+{
+	struct xt_target *target = ops->data;
+
+	nft_xt_put(container_of(ops, struct nft_xt, ops));
+	module_put(target->me);
+}
+
 static struct nft_expr_type nft_target_type __read_mostly = {
 	.name		= "target",
 	.select_ops	= nft_target_select_ops,
+	.release	= nft_target_release,
 	.policy		= nft_target_policy,
 	.maxattr	= NFTA_TARGET_MAX,
 	.owner		= THIS_MODULE,
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux