netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf] netfilter: nf_tables: fix base chain stat rcu_dereference usage
@ 2019-04-30 12:33 Florian Westphal
  2019-05-05 22:27 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 2+ messages in thread
From: Florian Westphal @ 2019-04-30 12:33 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Following splat gets triggered when nfnetlink monitor is running while
xtables-nft selftests are running:

net/netfilter/nf_tables_api.c:1272 suspicious rcu_dereference_check() usage!
other info that might help us debug this:

1 lock held by xtables-nft-mul/27006:
 #0: 00000000e0f85be9 (&net->nft.commit_mutex){+.+.}, at: nf_tables_valid_genid+0x1a/0x50
Call Trace:
 nf_tables_fill_chain_info.isra.45+0x6cc/0x6e0
 nf_tables_chain_notify+0xf8/0x1a0
 nf_tables_commit+0x165c/0x1740

nf_tables_fill_chain_info() can be called both from dumps (rcu read locked)
or from the transaction path if a userspace process subscribed to nftables
notifications.

In the 'table dump' case, rcu_access_pointer() cannot be used: We do not
hold transaction mutex so the pointer can be NULLed right after the check.
Just unconditionally fetch the value, then have the helper return
immediately if its NULL.

In the notification case we don't hold the rcu read lock, but updates are
prevented due to transaction mutex. Use rcu_dereference_check() to make lockdep
aware of this.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nf_tables_api.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 1606eaa5ae0d..aa5e7b00a581 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1190,6 +1190,9 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
 	u64 pkts, bytes;
 	int cpu;
 
+	if (!stats)
+		return 0;
+
 	memset(&total, 0, sizeof(total));
 	for_each_possible_cpu(cpu) {
 		cpu_stats = per_cpu_ptr(stats, cpu);
@@ -1247,6 +1250,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
 	if (nft_is_base_chain(chain)) {
 		const struct nft_base_chain *basechain = nft_base_chain(chain);
 		const struct nf_hook_ops *ops = &basechain->ops;
+		struct nft_stats __percpu *stats;
 		struct nlattr *nest;
 
 		nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
@@ -1268,8 +1272,9 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
 		if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
 			goto nla_put_failure;
 
-		if (rcu_access_pointer(basechain->stats) &&
-		    nft_dump_stats(skb, rcu_dereference(basechain->stats)))
+		stats = rcu_dereference_check(basechain->stats,
+					      lockdep_commit_lock_is_held(net));
+		if (nft_dump_stats(skb, stats))
 			goto nla_put_failure;
 	}
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH nf] netfilter: nf_tables: fix base chain stat rcu_dereference usage
  2019-04-30 12:33 [PATCH nf] netfilter: nf_tables: fix base chain stat rcu_dereference usage Florian Westphal
@ 2019-05-05 22:27 ` Pablo Neira Ayuso
  0 siblings, 0 replies; 2+ messages in thread
From: Pablo Neira Ayuso @ 2019-05-05 22:27 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Tue, Apr 30, 2019 at 02:33:22PM +0200, Florian Westphal wrote:
> Following splat gets triggered when nfnetlink monitor is running while
> xtables-nft selftests are running:
> 
> net/netfilter/nf_tables_api.c:1272 suspicious rcu_dereference_check() usage!
> other info that might help us debug this:
> 
> 1 lock held by xtables-nft-mul/27006:
>  #0: 00000000e0f85be9 (&net->nft.commit_mutex){+.+.}, at: nf_tables_valid_genid+0x1a/0x50
> Call Trace:
>  nf_tables_fill_chain_info.isra.45+0x6cc/0x6e0
>  nf_tables_chain_notify+0xf8/0x1a0
>  nf_tables_commit+0x165c/0x1740
> 
> nf_tables_fill_chain_info() can be called both from dumps (rcu read locked)
> or from the transaction path if a userspace process subscribed to nftables
> notifications.
> 
> In the 'table dump' case, rcu_access_pointer() cannot be used: We do not
> hold transaction mutex so the pointer can be NULLed right after the check.
> Just unconditionally fetch the value, then have the helper return
> immediately if its NULL.
> 
> In the notification case we don't hold the rcu read lock, but updates are
> prevented due to transaction mutex. Use rcu_dereference_check() to make lockdep
> aware of this.

Applied, thanks Florian.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-05-05 22:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-04-30 12:33 [PATCH nf] netfilter: nf_tables: fix base chain stat rcu_dereference usage Florian Westphal
2019-05-05 22:27 ` Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).