From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.us.es ([193.147.175.20]:44176 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752758AbeBTQjT (ORCPT ); Tue, 20 Feb 2018 11:39:19 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id DBAC739627B for ; Tue, 20 Feb 2018 17:39:17 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id CCD56DA729 for ; Tue, 20 Feb 2018 17:39:17 +0100 (CET) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Cc: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH 05/19] netfilter: ipt_CLUSTERIP: fix a refcount bug in clusterip_config_find_get() Date: Tue, 20 Feb 2018 17:38:52 +0100 Message-Id: <20180220163906.12380-6-pablo@netfilter.org> In-Reply-To: <20180220163906.12380-1-pablo@netfilter.org> References: <20180220163906.12380-1-pablo@netfilter.org> Sender: netdev-owner@vger.kernel.org List-ID: From: Cong Wang In clusterip_config_find_get() we hold RCU read lock so it could run concurrently with clusterip_config_entry_put(), as a result, the refcnt could go back to 1 from 0, which leads to a double list_del()... Just replace refcount_inc() with refcount_inc_not_zero(), as for c->refcount. Fixes: d73f33b16883 ("netfilter: CLUSTERIP: RCU conversion") Cc: Eric Dumazet Cc: Pablo Neira Ayuso Cc: Florian Westphal Signed-off-by: Cong Wang Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 1ff72b87a066..4b02ab39ebc5 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -154,8 +154,12 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry) #endif if (unlikely(!refcount_inc_not_zero(&c->refcount))) c = NULL; - else if (entry) - refcount_inc(&c->entries); + else if (entry) { + if (unlikely(!refcount_inc_not_zero(&c->entries))) { + clusterip_config_put(c); + c = NULL; + } + } } rcu_read_unlock_bh(); -- 2.11.0