From: Will Deacon <will.deacon@arm.com>
To: "Wang, Yalin" <Yalin.Wang@sonymobile.com>
Cc: "'linux-arm-msm-owner@vger.kernel.org'"
<linux-arm-msm-owner@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"Peng, Arthur" <Arthur.Peng@sonymobile.com>,
"Zhang, Bojie" <Bojie.Zhang@sonymobile.com>
Subject: Re: BUG report about ipt_do_table( )
Date: Thu, 10 Oct 2013 12:03:09 +0100 [thread overview]
Message-ID: <20131010110309.GA6199@mudshark.cambridge.arm.com> (raw)
In-Reply-To: <35FD53F367049845BC99AC72306C23D1014D1A0971B4@CNBJMBX05.corpusers.net>
On Thu, Oct 10, 2013 at 11:22:21AM +0100, Wang, Yalin wrote:
> Thanks for your reply .
No problem.
> I have compare our kernel with 3.12 ,
> Ip_tables.c x_tables.c is the same ,
> So the BUG should can also be reproduce on 3.12 (just my guess).
[...]
> /-----------------------------------------------------------------------/
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 8d987c3..2353bcc 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -819,6 +819,12 @@ xt_replace_table(struct xt_table *table,
> return NULL;
> }
>
> + /*
> + * make sure the change is write to the memory
> + * so that the other CPU can see the changes
> + */
> + mb();
> +
> /* Do the substitution. */
> local_bh_disable();
> private = table->private;
>
> /-----------------------------------------------------------------------/
>
>
> I add a memory barrier before update table->private .
> Make sure the other CPU can see the update memory correctly.
> When the BUG happened, the other CPU can get the new private (struct xt_table_info *),
> But sometimes it see private->jumpstack == NULL , or sometimes it see private->jumpstack[cpu] == NULL ,
On one CPU, xt_replace_table is basically doing:
newinfo->jumpstack = kzalloc(...);
table->private = newinfo;
so this can be thought of as the `writer' thread.
Then, on another CPU (the `reader'), we run ipt_do_table:
private = table->private;
jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
The reader has an address dependency, so the loads are guaranteed to be
observed in order (on sane CPUs... this is probably broken for Alpha).
However, the two stores from the writer can be observed in any order by other
CPUs. To make this clearer, I think you actually want an smb_wmb() immediately
before the assignment to table->private (and that assignment to
newinfo->initial_entries probably needs moving above it). Then you want an
smb_read_barrier_depends on the read path immediately after reading
table->private.
> This is caused by CPU write buffer ?
> It has written table->private , but has not update private-> members (still in write buffer) ,
> This is really out of order write, will this happened on modern armv7 CPU?
> Especially like cortex-a15 , it can execute code out of order .
Well, stores aren't speculated and stores to the same location are always
observed in order (on ARM). This is more a consequence of the weakly ordered
memory model, which largely comes about due to speculative loads and write
buffering (including read forwarding). Things like cache coherence protocols
and buffers in the interconnect can also cause stores to be observed in
different orders, since there conceptually end up being multi copies of the
data being written.
Anyway, can you see if the patch below fixes your problem please?
Will
--->8
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d23118d..cadda40 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -326,6 +326,7 @@ ipt_do_table(struct sk_buff *skb,
local_bh_disable();
addend = xt_write_recseq_begin();
private = table->private;
+ smp_read_barrier_depends();
cpu = smp_processor_id();
table_base = private->entries[cpu];
jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8b03028..ee5e184 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -845,8 +845,9 @@ xt_replace_table(struct xt_table *table,
return NULL;
}
- table->private = newinfo;
newinfo->initial_entries = private->initial_entries;
+ smb_wmb();
+ table->private = newinfo;
/*
* Even though table entries have now been swapped, other CPU's
next prev parent reply other threads:[~2013-10-10 11:03 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-10 5:16 Wang, Yalin
2013-10-10 9:48 ` Will Deacon
2013-10-10 10:22 ` Wang, Yalin
2013-10-10 11:03 ` Will Deacon [this message]
2013-10-10 11:26 ` Wang, Yalin
2013-10-10 14:18 ` Will Deacon
2013-10-11 1:50 ` Wang, Yalin
2013-10-11 11:02 ` Will Deacon
2013-10-11 11:14 ` Wang, Yalin
2013-10-17 1:51 ` Wang, Yalin
2013-10-17 10:41 ` Will Deacon
2013-10-18 1:41 ` Wang, Yalin
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=20131010110309.GA6199@mudshark.cambridge.arm.com \
--to=will.deacon@arm.com \
--cc=Arthur.Peng@sonymobile.com \
--cc=Bojie.Zhang@sonymobile.com \
--cc=Yalin.Wang@sonymobile.com \
--cc=linux-arm-msm-owner@vger.kernel.org \
--cc=linux-kernel@vger.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
all inboxes | Powered by JetHome®