From: Florian Westphal <fw@strlen.de>
To: subashab@codeaurora.org
Cc: Florian Westphal <fw@strlen.de>, Will Deacon <will@kernel.org>,
pablo@netfilter.org, Sean Tranchetti <stranche@codeaurora.org>,
netfilter-devel@vger.kernel.org, peterz@infradead.org,
tglx@linutronix.de
Subject: Re: [PATCH nf] x_tables: Properly close read section with read_seqcount_retry
Date: Wed, 18 Nov 2020 22:10:07 +0100 [thread overview]
Message-ID: <20201118211007.GA15137@breakpoint.cc> (raw)
In-Reply-To: <7d52f54a7e3ebc794f0b775e793ab142@codeaurora.org>
subashab@codeaurora.org <subashab@codeaurora.org> wrote:
> I have tried the following to ensure the instruction ordering of private
> assignment and I haven't seen the crash so far.
>
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index af22dbe..2a4f6b3 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1389,6 +1389,9 @@ xt_replace_table(struct xt_table *table,
> /* make sure all cpus see new ->private value */
> smp_wmb();
>
> + /* make sure the instructions above are actually executed */
> + smp_mb();
> +
This looks funny, I'd rather have s/smp_wmb/smp_mb instead of yet
another one.
> I assume we would need the following changes to address this.
Yes, something like this. More comments below.
> diff --git a/include/linux/netfilter/x_tables.h
> b/include/linux/netfilter/x_tables.h
> index 5deb099..7ab0e4f 100644
> --- a/include/linux/netfilter/x_tables.h
> +++ b/include/linux/netfilter/x_tables.h
> @@ -227,7 +227,7 @@ struct xt_table {
> unsigned int valid_hooks;
>
> /* Man behind the curtain... */
> - struct xt_table_info *private;
> + struct xt_table_info __rcu *private;
>
> /* Set this to THIS_MODULE if you are a module, otherwise NULL */
> struct module *me;
> diff --git a/net/ipv4/netfilter/arp_tables.c
> b/net/ipv4/netfilter/arp_tables.c
> index d1e04d2..6a2b551 100644
> --- a/net/ipv4/netfilter/arp_tables.c
> +++ b/net/ipv4/netfilter/arp_tables.c
> @@ -203,7 +203,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
>
> local_bh_disable();
> addend = xt_write_recseq_begin();
> - private = READ_ONCE(table->private); /* Address dependency. */
> + private = rcu_access_pointer(table->private);
The three _do_table() functions need to use rcu_dereference().
> cpu = smp_processor_id();
> table_base = private->entries;
> jumpstack = (struct arpt_entry **)private->jumpstack[cpu];
> @@ -649,7 +649,7 @@ static struct xt_counters *alloc_counters(const struct
> xt_table *table)
> {
> unsigned int countersize;
> struct xt_counters *counters;
> - const struct xt_table_info *private = table->private;
> + const struct xt_table_info *private = rcu_access_pointer(table->private);
This looks wrong. I know its ok, but perhaps its better to add this:
struct xt_table_info *xt_table_get_private_protected(const struct xt_table *table)
{
return rcu_dereference_protected(table->private, mutex_is_locked(&xt[table->af].mutex));
}
EXPORT_SYMBOL(xt_table_get_private_protected);
to x_tables.c.
If you dislike this extra function, add
#define xt_table_get_private_protected(t) rcu_access_pointer((t)->private)
in include/linux/netfilter/x_tables.h, with a bit fat comment telling
that the xt table mutex must be held.
But I'd rather have/use the helper function as it documents when its
safe to do this (and there will be splats if misused).
> index af22dbe..2e6c09c 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1367,7 +1367,7 @@ xt_replace_table(struct xt_table *table,
>
> /* Do the substitution. */
> local_bh_disable();
> - private = table->private;
> + private = rcu_access_pointer(table->private);
AFAICS the local_bh_disable/enable calls can be removed too after this,
if we're interrupted by softirq calling any of the _do_table()
functions changes to the xt seqcount do not matter anymore.
> /*
> * Even though table entries have now been swapped, other CPU's
We need this additional hunk to switch to rcu for replacement/sync, no?
- local_bh_enable();
-
- /* ... so wait for even xt_recseq on all cpus */
- for_each_possible_cpu(cpu) {
- seqcount_t *s = &per_cpu(xt_recseq, cpu);
- u32 seq = raw_read_seqcount(s);
-
- if (seq & 1) {
- do {
- cond_resched();
- cpu_relax();
- } while (seq == raw_read_seqcount(s));
- }
- }
+ synchronize_rcu();
next prev parent reply other threads:[~2020-11-18 21:10 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-14 2:21 [PATCH nf] x_tables: Properly close read section with read_seqcount_retry Sean Tranchetti
2020-11-14 16:53 ` Florian Westphal
2020-11-16 6:32 ` subashab
2020-11-16 14:18 ` Florian Westphal
2020-11-16 16:26 ` subashab
2020-11-16 17:04 ` Florian Westphal
2020-11-16 17:51 ` subashab
2020-11-16 18:20 ` Florian Westphal
2020-11-18 12:13 ` Will Deacon
2020-11-18 12:42 ` Florian Westphal
2020-11-18 12:54 ` Will Deacon
2020-11-18 13:14 ` Florian Westphal
2020-11-18 20:39 ` subashab
2020-11-18 21:10 ` Florian Westphal [this message]
2020-11-20 5:53 ` subashab
2020-11-20 6:31 ` Florian Westphal
2020-11-20 9:44 ` Peter Zijlstra
2020-11-20 9:53 ` Peter Zijlstra
2020-11-20 10:20 ` Florian Westphal
2020-11-20 10:47 ` Peter Zijlstra
2020-11-21 1:27 ` subashab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201118211007.GA15137@breakpoint.cc \
--to=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=peterz@infradead.org \
--cc=stranche@codeaurora.org \
--cc=subashab@codeaurora.org \
--cc=tglx@linutronix.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).