All of lore.kernel.org
 help / color / mirror / Atom feed
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();

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.