| Subject: net: netfilter: Serialize xt_write_recseq sections on RT |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Sun, 28 Oct 2012 11:18:08 +0100 |
| |
| The netfilter code relies only on the implicit semantics of |
| local_bh_disable() for serializing wt_write_recseq sections. RT breaks |
| that and needs explicit serialization here. |
| |
| Reported-by: Peter LaDow <petela@gocougs.wsu.edu> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| |
| --- |
| include/linux/netfilter/x_tables.h | 7 +++++++ |
| net/netfilter/core.c | 6 ++++++ |
| 2 files changed, 13 insertions(+) |
| |
| --- a/include/linux/netfilter/x_tables.h |
| +++ b/include/linux/netfilter/x_tables.h |
| @@ -5,6 +5,7 @@ |
| #include <linux/netdevice.h> |
| #include <linux/static_key.h> |
| #include <linux/netfilter.h> |
| +#include <linux/locallock.h> |
| #include <uapi/linux/netfilter/x_tables.h> |
| |
| /* Test a struct->invflags and a boolean for inequality */ |
| @@ -337,6 +338,8 @@ void xt_free_table_info(struct xt_table_ |
| */ |
| DECLARE_PER_CPU(seqcount_t, xt_recseq); |
| |
| +DECLARE_LOCAL_IRQ_LOCK(xt_write_lock); |
| + |
| /* xt_tee_enabled - true if x_tables needs to handle reentrancy |
| * |
| * Enabled if current ip(6)tables ruleset has at least one -j TEE rule. |
| @@ -357,6 +360,9 @@ static inline unsigned int xt_write_recs |
| { |
| unsigned int addend; |
| |
| + /* RT protection */ |
| + local_lock(xt_write_lock); |
| + |
| /* |
| * Low order bit of sequence is set if we already |
| * called xt_write_recseq_begin(). |
| @@ -387,6 +393,7 @@ static inline void xt_write_recseq_end(u |
| /* this is kind of a write_seqcount_end(), but addend is 0 or 1 */ |
| smp_wmb(); |
| __this_cpu_add(xt_recseq.sequence, addend); |
| + local_unlock(xt_write_lock); |
| } |
| |
| /* |
| --- a/net/netfilter/core.c |
| +++ b/net/netfilter/core.c |
| @@ -22,12 +22,18 @@ |
| #include <linux/proc_fs.h> |
| #include <linux/mutex.h> |
| #include <linux/slab.h> |
| +#include <linux/locallock.h> |
| #include <linux/rcupdate.h> |
| #include <net/net_namespace.h> |
| #include <net/sock.h> |
| |
| #include "nf_internals.h" |
| |
| +#ifdef CONFIG_PREEMPT_RT_BASE |
| +DEFINE_LOCAL_IRQ_LOCK(xt_write_lock); |
| +EXPORT_PER_CPU_SYMBOL(xt_write_lock); |
| +#endif |
| + |
| static DEFINE_MUTEX(afinfo_mutex); |
| |
| const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; |