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