The nft_expr_ops might be freed in the nf_tables_expr_destroy but after this, a member of nft_expr_ops is used. Steps to reproduce: $iptables-compat -I OUTPUT -m cpu --cpu 0 $iptables-compat -F Signed-off-by: Taehee Yoo <ap420073@xxxxxxxxx> --- net/netfilter/nf_tables_api.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 981f35e..2ab23e3 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1873,7 +1873,7 @@ static int nf_tables_newexpr(const struct nft_ctx *ctx, if (ops->init) { err = ops->init(ctx, expr, (const struct nlattr **)info->tb); if (err < 0) - goto err1; + return err; } if (ops->validate) { @@ -1881,16 +1881,14 @@ static int nf_tables_newexpr(const struct nft_ctx *ctx, err = ops->validate(ctx, expr, &data); if (err < 0) - goto err2; + goto err; } return 0; -err2: +err: if (ops->destroy) ops->destroy(ctx, expr); -err1: - expr->ops = NULL; return err; } @@ -2233,16 +2231,13 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, static void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule) { - struct nft_expr *expr; + struct nft_expr *expr, *next; - /* - * Careful: some expressions might not be initialized in case this - * is called on error from nf_tables_newrule(). - */ expr = nft_expr_first(rule); - while (expr != nft_expr_last(rule) && expr->ops) { + while (expr != nft_expr_last(rule)) { + next = nft_expr_next(expr); nf_tables_expr_destroy(ctx, expr); - expr = nft_expr_next(expr); + expr = next; } kfree(rule); } -- 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