From patchwork Mon Feb 5 18:02:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Fietkau X-Patchwork-Id: 869432 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=nbd.name header.i=@nbd.name header.b="oPkB6zHO"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zZwRS30Cnz9t2c for ; Tue, 6 Feb 2018 05:02:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753411AbeBESCm (ORCPT ); Mon, 5 Feb 2018 13:02:42 -0500 Received: from nbd.name ([46.4.11.11]:50490 "EHLO nbd.name" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753028AbeBESCj (ORCPT ); Mon, 5 Feb 2018 13:02:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nbd.name; s=20160729; h=Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=eakmdYbUGmlyd+f/SaUGQT9vUTmfQZ0vNFptfcuG98c=; b=oPkB6zHOaZGrVCiy9QOfQN+KWL uD0COXJZBkjaXU9oa3zbAbVKU9y04z/S/fkeYcKjOvsErNJ5Fm+t0RuuyZx1wRl2XAfZnDzwLKVSz QnYoV7aJsimrauOTsJ/qU6gDKX6boJO6uGxiQnHvE/uon8NECA98SLs20j8d9BkgWN70=; Received: by maeck.local (Postfix, from userid 501) id F3CED1133140; Mon, 5 Feb 2018 19:02:34 +0100 (CET) From: Felix Fietkau To: netfilter-devel@vger.kernel.org Cc: netdev@vger.kernel.org, davem@davemloft.net, pablo@netfilter.org Subject: [PATCH 1/2] netfilter: nf_tables: fix flowtable free Date: Mon, 5 Feb 2018 19:02:33 +0100 Message-Id: <20180205180234.26487-1-nbd@nbd.name> X-Mailer: git-send-email 2.14.2 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Every flow_offload entry is added into the table twice. Because of this, rhashtable_free_and_destroy can't be used, since it would call kfree for each flow_offload object twice. Signed-off-by: Felix Fietkau --- include/net/netfilter/nf_flow_table.h | 2 ++ net/ipv4/netfilter/nf_flow_table_ipv4.c | 1 + net/ipv6/netfilter/nf_flow_table_ipv6.c | 1 + net/netfilter/nf_flow_table.c | 15 +++++++++++++++ net/netfilter/nf_flow_table_inet.c | 1 + net/netfilter/nf_tables_api.c | 8 +------- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index b22b22082733..67c61bda6a46 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -14,6 +14,7 @@ struct nf_flowtable_type { struct list_head list; int family; void (*gc)(struct work_struct *work); + void (*free)(struct nf_flowtable *table); const struct rhashtable_params *params; nf_hookfn *hook; struct module *owner; @@ -95,6 +96,7 @@ struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_t int nf_flow_table_iterate(struct nf_flowtable *flow_table, void (*iter)(struct flow_offload *flow, void *data), void *data); +void nf_flow_table_free(struct nf_flowtable *flow_table); void nf_flow_offload_work_gc(struct work_struct *work); extern const struct rhashtable_params nf_flow_offload_rhash_params; diff --git a/net/ipv4/netfilter/nf_flow_table_ipv4.c b/net/ipv4/netfilter/nf_flow_table_ipv4.c index b2d01eb25f2c..25d2975da156 100644 --- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c @@ -260,6 +260,7 @@ static struct nf_flowtable_type flowtable_ipv4 = { .family = NFPROTO_IPV4, .params = &nf_flow_offload_rhash_params, .gc = nf_flow_offload_work_gc, + .free = nf_flow_table_free, .hook = nf_flow_offload_ip_hook, .owner = THIS_MODULE, }; diff --git a/net/ipv6/netfilter/nf_flow_table_ipv6.c b/net/ipv6/netfilter/nf_flow_table_ipv6.c index fff21602875a..d346705d6ee6 100644 --- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c @@ -253,6 +253,7 @@ static struct nf_flowtable_type flowtable_ipv6 = { .family = NFPROTO_IPV6, .params = &nf_flow_offload_rhash_params, .gc = nf_flow_offload_work_gc, + .free = nf_flow_table_free, .hook = nf_flow_offload_ipv6_hook, .owner = THIS_MODULE, }; diff --git a/net/netfilter/nf_flow_table.c b/net/netfilter/nf_flow_table.c index 2f5099cb85b8..20f86091ab98 100644 --- a/net/netfilter/nf_flow_table.c +++ b/net/netfilter/nf_flow_table.c @@ -221,6 +221,21 @@ int nf_flow_table_iterate(struct nf_flowtable *flow_table, } EXPORT_SYMBOL_GPL(nf_flow_table_iterate); +static void +__nf_flow_offload_free(struct flow_offload *flow, void *data) +{ + struct nf_flowtable *flow_table = data; + + flow_offload_del(flow_table, flow); +} + +void nf_flow_table_free(struct nf_flowtable *flow_table) +{ + nf_flow_table_iterate(flow_table, __nf_flow_offload_free, flow_table); + rhashtable_destroy(&flow_table->rhashtable); +} +EXPORT_SYMBOL_GPL(nf_flow_table_free); + static inline bool nf_flow_has_expired(const struct flow_offload *flow) { return (__s32)(flow->timeout - (u32)jiffies) <= 0; diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c index 281209aeba8f..375a1881d93d 100644 --- a/net/netfilter/nf_flow_table_inet.c +++ b/net/netfilter/nf_flow_table_inet.c @@ -24,6 +24,7 @@ static struct nf_flowtable_type flowtable_inet = { .family = NFPROTO_INET, .params = &nf_flow_offload_rhash_params, .gc = nf_flow_offload_work_gc, + .free = nf_flow_table_free, .hook = nf_flow_offload_inet_hook, .owner = THIS_MODULE, }; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 0791813a1e7d..a6c4747c7d5d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5399,17 +5399,11 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx, nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); } -static void nft_flowtable_destroy(void *ptr, void *arg) -{ - kfree(ptr); -} - static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) { cancel_delayed_work_sync(&flowtable->data.gc_work); kfree(flowtable->name); - rhashtable_free_and_destroy(&flowtable->data.rhashtable, - nft_flowtable_destroy, NULL); + flowtable->data.type->free(&flowtable->data); module_put(flowtable->data.type->owner); } From patchwork Mon Feb 5 18:02:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felix Fietkau X-Patchwork-Id: 869431 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=nbd.name header.i=@nbd.name header.b="RZaQY9NQ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zZwRP2vhgz9t20 for ; Tue, 6 Feb 2018 05:02:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753386AbeBESCk (ORCPT ); Mon, 5 Feb 2018 13:02:40 -0500 Received: from nbd.name ([46.4.11.11]:50488 "EHLO nbd.name" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753101AbeBESCj (ORCPT ); Mon, 5 Feb 2018 13:02:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nbd.name; s=20160729; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=meSIyZauNSZk2nYyxiaP1nMxo8UyvUGJVGNkfXV34Rc=; b=RZaQY9NQSKJGTDPJm9eCwnyv9U 8EaEKDuLVJxFJPxRGmucqrKKgxB1+xsN48t22lGRNg3CLiKADOqJm8ioGivYfQBP0fpuphI9tMEuM tOZ6+lZBRDix71YwhapAQvAJiWqhURNUHOqJMiXvt6imuuNHu4DTR1fRHze0i0ig/SQo=; Received: by maeck.local (Postfix, from userid 501) id B5214113313F; Mon, 5 Feb 2018 19:02:34 +0100 (CET) From: Felix Fietkau To: netfilter-devel@vger.kernel.org Cc: netdev@vger.kernel.org, davem@davemloft.net, pablo@netfilter.org Subject: [PATCH 2/2] netfilter: nf_tables: fix flowtable resource leak Date: Mon, 5 Feb 2018 19:02:34 +0100 Message-Id: <20180205180234.26487-2-nbd@nbd.name> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20180205180234.26487-1-nbd@nbd.name> References: <20180205180234.26487-1-nbd@nbd.name> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org When cleaning up flowtable entries, associated dst and ct entries need to be released as well Signed-off-by: Felix Fietkau --- net/netfilter/nf_flow_table.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/net/netfilter/nf_flow_table.c b/net/netfilter/nf_flow_table.c index 20f86091ab98..9925bd3f93c4 100644 --- a/net/netfilter/nf_flow_table.c +++ b/net/netfilter/nf_flow_table.c @@ -124,7 +124,7 @@ void flow_offload_free(struct flow_offload *flow) dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); e = container_of(flow, struct flow_offload_entry, flow); - kfree(e); + kfree_rcu(e, rcu_head); } EXPORT_SYMBOL_GPL(flow_offload_free); @@ -161,7 +161,9 @@ void flow_offload_del(struct nf_flowtable *flow_table, *flow_table->type->params); e = container_of(flow, struct flow_offload_entry, flow); - kfree_rcu(e, rcu_head); + nf_ct_delete(e->ct, 0, 0); + nf_ct_put(e->ct); + flow_offload_free(flow); } EXPORT_SYMBOL_GPL(flow_offload_del); @@ -174,15 +176,6 @@ flow_offload_lookup(struct nf_flowtable *flow_table, } EXPORT_SYMBOL_GPL(flow_offload_lookup); -static void nf_flow_release_ct(const struct flow_offload *flow) -{ - struct flow_offload_entry *e; - - e = container_of(flow, struct flow_offload_entry, flow); - nf_ct_delete(e->ct, 0, 0); - nf_ct_put(e->ct); -} - int nf_flow_table_iterate(struct nf_flowtable *flow_table, void (*iter)(struct flow_offload *flow, void *data), void *data) @@ -276,10 +269,8 @@ void nf_flow_offload_work_gc(struct work_struct *work) flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); if (nf_flow_has_expired(flow) || - nf_flow_is_dying(flow)) { + nf_flow_is_dying(flow)) flow_offload_del(flow_table, flow); - nf_flow_release_ct(flow); - } } out: rhashtable_walk_stop(&hti);