All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
@ 2020-11-22 19:17 Subash Abhinov Kasiviswanathan
  2020-11-22 19:35 ` Florian Westphal
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Subash Abhinov Kasiviswanathan @ 2020-11-22 19:17 UTC (permalink / raw)
  To: will, pablo, stranche, netfilter-devel, tglx, fw, peterz
  Cc: Subash Abhinov Kasiviswanathan

When running concurrent iptables rules replacement with data, the per CPU
sequence count is checked after the assignment of the new information.
The sequence count is used to synchronize with the packet path without the
use of any explicit locking. If there are any packets in the packet path using
the table information, the sequence count is incremented to an odd value and
is incremented to an even after the packet process completion.

The new table value assignment is followed by a write memory barrier so every
CPU should see the latest value. If the packet path has started with the old
table information, the sequence counter will be odd and the iptables
replacement will wait till the sequence count is even prior to freeing the
old table info.

However, this assumes that the new table information assignment and the memory
barrier is actually executed prior to the counter check in the replacement
thread. If CPU decides to execute the assignment later as there is no user of
the table information prior to the sequence check, the packet path in another
CPU may use the old table information. The replacement thread would then free
the table information under it leading to a use after free in the packet
processing context-

Unable to handle kernel NULL pointer dereference at virtual
address 000000000000008e
pc : ip6t_do_table+0x5d0/0x89c
lr : ip6t_do_table+0x5b8/0x89c
ip6t_do_table+0x5d0/0x89c
ip6table_filter_hook+0x24/0x30
nf_hook_slow+0x84/0x120
ip6_input+0x74/0xe0
ip6_rcv_finish+0x7c/0x128
ipv6_rcv+0xac/0xe4
__netif_receive_skb+0x84/0x17c
process_backlog+0x15c/0x1b8
napi_poll+0x88/0x284
net_rx_action+0xbc/0x23c
__do_softirq+0x20c/0x48c

This could be fixed by forcing instruction order after the new table
information assignment or by switching to RCU for the synchronization.

Fixes: 80055dab5de0 ("netfilter: x_tables: make xt_replace_table wait until old rules are not used anymore")
Reported-by: Sean Tranchetti <stranche@codeaurora.org>
Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
 include/linux/netfilter/x_tables.h |  5 +++-
 net/ipv4/netfilter/arp_tables.c    |  8 +++----
 net/ipv4/netfilter/ip_tables.c     |  8 +++----
 net/ipv6/netfilter/ip6_tables.c    |  8 +++----
 net/netfilter/x_tables.c           | 48 ++++++++++++--------------------------
 5 files changed, 31 insertions(+), 46 deletions(-)

diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 5deb099..8ebb641 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;
@@ -448,6 +448,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
 
 struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
 
+struct xt_table_info
+*xt_table_get_private_protected(const struct xt_table *table);
+
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index d1e04d2..6891a40 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);
 	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 = xt_table_get_private_protected(table);
 
 	/* We need atomic snapshot of counters: rest doesn't change
 	 * (other than comefrom, which userspace doesn't care
@@ -673,7 +673,7 @@ static int copy_entries_to_user(unsigned int total_size,
 	unsigned int off, num;
 	const struct arpt_entry *e;
 	struct xt_counters *counters;
-	struct xt_table_info *private = table->private;
+	struct xt_table_info *private = xt_table_get_private_protected(table);
 	int ret = 0;
 	void *loc_cpu_entry;
 
@@ -1330,7 +1330,7 @@ static int compat_copy_entries_to_user(unsigned int total_size,
 				       void __user *userptr)
 {
 	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = xt_table_get_private_protected(table);
 	void __user *pos;
 	unsigned int size;
 	int ret = 0;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index f15bc21..01a9753 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -258,7 +258,7 @@ ipt_do_table(struct sk_buff *skb,
 	WARN_ON(!(table->valid_hooks & (1 << hook)));
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
-	private = READ_ONCE(table->private); /* Address dependency. */
+	private = rcu_access_pointer(table->private);
 	cpu        = smp_processor_id();
 	table_base = private->entries;
 	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
@@ -791,7 +791,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 = xt_table_get_private_protected(table);
 
 	/* We need atomic snapshot of counters: rest doesn't change
 	   (other than comefrom, which userspace doesn't care
@@ -815,7 +815,7 @@ copy_entries_to_user(unsigned int total_size,
 	unsigned int off, num;
 	const struct ipt_entry *e;
 	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = xt_table_get_private_protected(table);
 	int ret = 0;
 	const void *loc_cpu_entry;
 
@@ -1543,7 +1543,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
 			    void __user *userptr)
 {
 	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = xt_table_get_private_protected(table);
 	void __user *pos;
 	unsigned int size;
 	int ret = 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 2e2119b..8a7bb06 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -280,7 +280,7 @@ ip6t_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);
 	cpu        = smp_processor_id();
 	table_base = private->entries;
 	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
@@ -807,7 +807,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 = xt_table_get_private_protected(table);
 
 	/* We need atomic snapshot of counters: rest doesn't change
 	   (other than comefrom, which userspace doesn't care
@@ -831,7 +831,7 @@ copy_entries_to_user(unsigned int total_size,
 	unsigned int off, num;
 	const struct ip6t_entry *e;
 	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = xt_table_get_private_protected(table);
 	int ret = 0;
 	const void *loc_cpu_entry;
 
@@ -1552,7 +1552,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
 			    void __user *userptr)
 {
 	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = xt_table_get_private_protected(table);
 	void __user *pos;
 	unsigned int size;
 	int ret = 0;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index af22dbe..416a617 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1349,6 +1349,14 @@ struct xt_counters *xt_counters_alloc(unsigned int counters)
 }
 EXPORT_SYMBOL(xt_counters_alloc);
 
+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);
+
 struct xt_table_info *
 xt_replace_table(struct xt_table *table,
 	      unsigned int num_counters,
@@ -1356,7 +1364,6 @@ xt_replace_table(struct xt_table *table,
 	      int *error)
 {
 	struct xt_table_info *private;
-	unsigned int cpu;
 	int ret;
 
 	ret = xt_jumpstack_alloc(newinfo);
@@ -1366,8 +1373,7 @@ xt_replace_table(struct xt_table *table,
 	}
 
 	/* Do the substitution. */
-	local_bh_disable();
-	private = table->private;
+	private = xt_table_get_private_protected(table);
 
 	/* Check inside lock: is the old number correct? */
 	if (num_counters != private->number) {
@@ -1379,34 +1385,9 @@ xt_replace_table(struct xt_table *table,
 	}
 
 	newinfo->initial_entries = private->initial_entries;
-	/*
-	 * Ensure contents of newinfo are visible before assigning to
-	 * private.
-	 */
-	smp_wmb();
-	table->private = newinfo;
-
-	/* make sure all cpus see new ->private value */
-	smp_wmb();
 
-	/*
-	 * Even though table entries have now been swapped, other CPU's
-	 * may still be using the old entries...
-	 */
-	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));
-		}
-	}
+	rcu_assign_pointer(table->private, newinfo);
+	synchronize_rcu();
 
 	audit_log_nfcfg(table->name, table->af, private->number,
 			!private->number ? AUDIT_XT_OP_REGISTER :
@@ -1442,12 +1423,12 @@ struct xt_table *xt_register_table(struct net *net,
 	}
 
 	/* Simplifies replace_table code. */
-	table->private = bootstrap;
+	rcu_assign_pointer(table->private, bootstrap);
 
 	if (!xt_replace_table(table, 0, newinfo, &ret))
 		goto unlock;
 
-	private = table->private;
+	private = xt_table_get_private_protected(table);
 	pr_debug("table->private->number = %u\n", private->number);
 
 	/* save number of initial entries */
@@ -1470,7 +1451,8 @@ void *xt_unregister_table(struct xt_table *table)
 	struct xt_table_info *private;
 
 	mutex_lock(&xt[table->af].mutex);
-	private = table->private;
+	private = xt_table_get_private_protected(table);
+	RCU_INIT_POINTER(table->private, NULL);
 	list_del(&table->list);
 	mutex_unlock(&xt[table->af].mutex);
 	audit_log_nfcfg(table->name, table->af, private->number,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
  2020-11-22 19:17 [PATCH nf] netfilter: x_tables: Switch synchronization to RCU Subash Abhinov Kasiviswanathan
@ 2020-11-22 19:35 ` Florian Westphal
  2020-11-22 19:55   ` subashab
  2020-11-22 20:58   ` kernel test robot
  2020-11-25  3:40   ` kernel test robot
  2 siblings, 1 reply; 8+ messages in thread
From: Florian Westphal @ 2020-11-22 19:35 UTC (permalink / raw)
  To: Subash Abhinov Kasiviswanathan
  Cc: will, pablo, stranche, netfilter-devel, tglx, fw, peterz

Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> wrote:
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index af22dbe..416a617 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1349,6 +1349,14 @@ struct xt_counters *xt_counters_alloc(unsigned int counters)
>  }
>  EXPORT_SYMBOL(xt_counters_alloc);
[..]

>  	/* Do the substitution. */
> -	local_bh_disable();
> -	private = table->private;
> +	private = xt_table_get_private_protected(table);
>  
>  	/* Check inside lock: is the old number correct? */
>  	if (num_counters != private->number) {

There is a local_bh_enable() here that needs removal.

Did you test it with PROVE_LOCKING enabled?

The placement/use of rcu_dereference and the _protected version
looks correct, I would not expect splats.

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
  2020-11-22 19:35 ` Florian Westphal
@ 2020-11-22 19:55   ` subashab
  2020-11-25  6:25     ` subashab
  0 siblings, 1 reply; 8+ messages in thread
From: subashab @ 2020-11-22 19:55 UTC (permalink / raw)
  To: Florian Westphal; +Cc: will, pablo, stranche, netfilter-devel, tglx, peterz

On 2020-11-22 12:35, Florian Westphal wrote:
> Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> wrote:
>> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
>> index af22dbe..416a617 100644
>> --- a/net/netfilter/x_tables.c
>> +++ b/net/netfilter/x_tables.c
>> @@ -1349,6 +1349,14 @@ struct xt_counters *xt_counters_alloc(unsigned 
>> int counters)
>>  }
>>  EXPORT_SYMBOL(xt_counters_alloc);
> [..]
> 
>>  	/* Do the substitution. */
>> -	local_bh_disable();
>> -	private = table->private;
>> +	private = xt_table_get_private_protected(table);
>> 
>>  	/* Check inside lock: is the old number correct? */
>>  	if (num_counters != private->number) {
> 
> There is a local_bh_enable() here that needs removal.

Thanks, will update that.

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 416a617..acce622 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1379,7 +1379,6 @@ xt_replace_table(struct xt_table *table,
         if (num_counters != private->number) {
                 pr_debug("num_counters != table->private->number 
(%u/%u)\n",
                          num_counters, private->number);
-               local_bh_enable();
                 *error = -EAGAIN;
                 return NULL;
         }

> 
> Did you test it with PROVE_LOCKING enabled?
> 
> The placement/use of rcu_dereference and the _protected version
> looks correct, I would not expect splats.

My config doesn't seem to have it. I will enable and try it out.

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
  2020-11-22 19:17 [PATCH nf] netfilter: x_tables: Switch synchronization to RCU Subash Abhinov Kasiviswanathan
@ 2020-11-22 20:58   ` kernel test robot
  2020-11-22 20:58   ` kernel test robot
  2020-11-25  3:40   ` kernel test robot
  2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2020-11-22 20:58 UTC (permalink / raw)
  To: Subash Abhinov Kasiviswanathan, will, pablo, stranche,
	netfilter-devel, tglx, fw, peterz
  Cc: kbuild-all, Subash Abhinov Kasiviswanathan

[-- Attachment #1: Type: text/plain, Size: 9713 bytes --]

Hi Subash,

I love your patch! Perhaps something to improve:

[auto build test WARNING on nf/master]

url:    https://github.com/0day-ci/linux/commits/Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
config: i386-randconfig-s001-20201122 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-134-gb59dbdaf-dirty
        # https://github.com/0day-ci/linux/commit/2d87a7da9e77a1c31af435d23238e60d0067aac0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
        git checkout 2d87a7da9e77a1c31af435d23238e60d0067aac0
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse:     expected struct xt_table_info const *private
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv6/netfilter/ip6_tables.c:1038:50: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv6/netfilter/ip6_tables.c:1038:50: sparse:     expected struct xt_table_info *private
   net/ipv6/netfilter/ip6_tables.c:1038:50: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv6/netfilter/ip6_tables.c:1192:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv6/netfilter/ip6_tables.c:1192:17: sparse:     expected struct xt_table_info const *private
   net/ipv6/netfilter/ip6_tables.c:1192:17: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse: sparse: Initializer entry defined twice
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse:   also defined here
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse: sparse: Initializer entry defined twice
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse:   also defined here

vim +983 net/ipv6/netfilter/ip6_tables.c

3bc3fe5eed5e866 Patrick McHardy   2007-12-17   962  
f415e76fd723594 Christoph Hellwig 2020-07-17   963  static int get_info(struct net *net, void __user *user, const int *len)
433665c9d110d78 Patrick McHardy   2007-12-17   964  {
12b00c2c025b8af Jan Engelhardt    2010-10-13   965  	char name[XT_TABLE_MAXNAMELEN];
433665c9d110d78 Patrick McHardy   2007-12-17   966  	struct xt_table *t;
433665c9d110d78 Patrick McHardy   2007-12-17   967  	int ret;
433665c9d110d78 Patrick McHardy   2007-12-17   968  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03   969  	if (*len != sizeof(struct ip6t_getinfo))
433665c9d110d78 Patrick McHardy   2007-12-17   970  		return -EINVAL;
433665c9d110d78 Patrick McHardy   2007-12-17   971  
433665c9d110d78 Patrick McHardy   2007-12-17   972  	if (copy_from_user(name, user, sizeof(name)) != 0)
433665c9d110d78 Patrick McHardy   2007-12-17   973  		return -EFAULT;
433665c9d110d78 Patrick McHardy   2007-12-17   974  
12b00c2c025b8af Jan Engelhardt    2010-10-13   975  	name[XT_TABLE_MAXNAMELEN-1] = '\0';
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   976  #ifdef CONFIG_COMPAT
f415e76fd723594 Christoph Hellwig 2020-07-17   977  	if (in_compat_syscall())
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   978  		xt_compat_lock(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   979  #endif
03d13b6868a261f Florian Westphal  2017-12-08   980  	t = xt_request_find_table_lock(net, AF_INET6, name);
03d13b6868a261f Florian Westphal  2017-12-08   981  	if (!IS_ERR(t)) {
433665c9d110d78 Patrick McHardy   2007-12-17   982  		struct ip6t_getinfo info;
5452e425adfdfc4 Jan Engelhardt    2008-04-14  @983  		const struct xt_table_info *private = t->private;
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   984  #ifdef CONFIG_COMPAT
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   985  		struct xt_table_info tmp;
14c7dbe043d01a8 Alexey Dobriyan   2010-02-08   986  
f415e76fd723594 Christoph Hellwig 2020-07-17   987  		if (in_compat_syscall()) {
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   988  			ret = compat_table_info(private, &tmp);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   989  			xt_compat_flush_offsets(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   990  			private = &tmp;
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   991  		}
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   992  #endif
cccbe5ef8528462 Jan Engelhardt    2010-11-03   993  		memset(&info, 0, sizeof(info));
433665c9d110d78 Patrick McHardy   2007-12-17   994  		info.valid_hooks = t->valid_hooks;
433665c9d110d78 Patrick McHardy   2007-12-17   995  		memcpy(info.hook_entry, private->hook_entry,
433665c9d110d78 Patrick McHardy   2007-12-17   996  		       sizeof(info.hook_entry));
433665c9d110d78 Patrick McHardy   2007-12-17   997  		memcpy(info.underflow, private->underflow,
433665c9d110d78 Patrick McHardy   2007-12-17   998  		       sizeof(info.underflow));
433665c9d110d78 Patrick McHardy   2007-12-17   999  		info.num_entries = private->number;
433665c9d110d78 Patrick McHardy   2007-12-17  1000  		info.size = private->size;
b5dd674b2a1de59 Patrick McHardy   2007-12-17  1001  		strcpy(info.name, name);
433665c9d110d78 Patrick McHardy   2007-12-17  1002  
433665c9d110d78 Patrick McHardy   2007-12-17  1003  		if (copy_to_user(user, &info, *len) != 0)
433665c9d110d78 Patrick McHardy   2007-12-17  1004  			ret = -EFAULT;
433665c9d110d78 Patrick McHardy   2007-12-17  1005  		else
433665c9d110d78 Patrick McHardy   2007-12-17  1006  			ret = 0;
433665c9d110d78 Patrick McHardy   2007-12-17  1007  
433665c9d110d78 Patrick McHardy   2007-12-17  1008  		xt_table_unlock(t);
433665c9d110d78 Patrick McHardy   2007-12-17  1009  		module_put(t->me);
433665c9d110d78 Patrick McHardy   2007-12-17  1010  	} else
03d13b6868a261f Florian Westphal  2017-12-08  1011  		ret = PTR_ERR(t);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1012  #ifdef CONFIG_COMPAT
f415e76fd723594 Christoph Hellwig 2020-07-17  1013  	if (in_compat_syscall())
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1014  		xt_compat_unlock(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1015  #endif
433665c9d110d78 Patrick McHardy   2007-12-17  1016  	return ret;
433665c9d110d78 Patrick McHardy   2007-12-17  1017  }
433665c9d110d78 Patrick McHardy   2007-12-17  1018  
^1da177e4c3f415 Linus Torvalds    2005-04-16  1019  static int
d5d1baa15f5b05e Jan Engelhardt    2009-06-26  1020  get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
d5d1baa15f5b05e Jan Engelhardt    2009-06-26  1021  	    const int *len)
^1da177e4c3f415 Linus Torvalds    2005-04-16  1022  {
^1da177e4c3f415 Linus Torvalds    2005-04-16  1023  	int ret;
d924357c50d83e7 Patrick McHardy   2007-12-17  1024  	struct ip6t_get_entries get;
2e4e6a17af35be3 Harald Welte      2006-01-12  1025  	struct xt_table *t;
^1da177e4c3f415 Linus Torvalds    2005-04-16  1026  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1027  	if (*len < sizeof(get))
d924357c50d83e7 Patrick McHardy   2007-12-17  1028  		return -EINVAL;
d924357c50d83e7 Patrick McHardy   2007-12-17  1029  	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
d924357c50d83e7 Patrick McHardy   2007-12-17  1030  		return -EFAULT;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1031  	if (*len != sizeof(struct ip6t_get_entries) + get.size)
d924357c50d83e7 Patrick McHardy   2007-12-17  1032  		return -EINVAL;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1033  
b301f2538759933 Pablo Neira Ayuso 2016-03-24  1034  	get.name[sizeof(get.name) - 1] = '\0';
d924357c50d83e7 Patrick McHardy   2007-12-17  1035  
336b517fdc0f92f Alexey Dobriyan   2008-01-31  1036  	t = xt_find_table_lock(net, AF_INET6, get.name);
03d13b6868a261f Florian Westphal  2017-12-08  1037  	if (!IS_ERR(t)) {
2e4e6a17af35be3 Harald Welte      2006-01-12 @1038  		struct xt_table_info *private = t->private;
d924357c50d83e7 Patrick McHardy   2007-12-17  1039  		if (get.size == private->size)
2e4e6a17af35be3 Harald Welte      2006-01-12  1040  			ret = copy_entries_to_user(private->size,
^1da177e4c3f415 Linus Torvalds    2005-04-16  1041  						   t, uptr->entrytable);
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1042  		else
544473c1664f3a6 Patrick McHardy   2008-04-14  1043  			ret = -EAGAIN;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1044  
6b7d31fcdda5938 Harald Welte      2005-10-26  1045  		module_put(t->me);
2e4e6a17af35be3 Harald Welte      2006-01-12  1046  		xt_table_unlock(t);
^1da177e4c3f415 Linus Torvalds    2005-04-16  1047  	} else
03d13b6868a261f Florian Westphal  2017-12-08  1048  		ret = PTR_ERR(t);
^1da177e4c3f415 Linus Torvalds    2005-04-16  1049  
^1da177e4c3f415 Linus Torvalds    2005-04-16  1050  	return ret;
^1da177e4c3f415 Linus Torvalds    2005-04-16  1051  }
^1da177e4c3f415 Linus Torvalds    2005-04-16  1052  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36080 bytes --]

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
@ 2020-11-22 20:58   ` kernel test robot
  0 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2020-11-22 20:58 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 9851 bytes --]

Hi Subash,

I love your patch! Perhaps something to improve:

[auto build test WARNING on nf/master]

url:    https://github.com/0day-ci/linux/commits/Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
config: i386-randconfig-s001-20201122 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-134-gb59dbdaf-dirty
        # https://github.com/0day-ci/linux/commit/2d87a7da9e77a1c31af435d23238e60d0067aac0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
        git checkout 2d87a7da9e77a1c31af435d23238e60d0067aac0
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse:     expected struct xt_table_info const *private
>> net/ipv6/netfilter/ip6_tables.c:983:56: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv6/netfilter/ip6_tables.c:1038:50: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv6/netfilter/ip6_tables.c:1038:50: sparse:     expected struct xt_table_info *private
   net/ipv6/netfilter/ip6_tables.c:1038:50: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv6/netfilter/ip6_tables.c:1192:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv6/netfilter/ip6_tables.c:1192:17: sparse:     expected struct xt_table_info const *private
   net/ipv6/netfilter/ip6_tables.c:1192:17: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse: sparse: Initializer entry defined twice
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse:   also defined here
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse: sparse: Initializer entry defined twice
   net/ipv6/netfilter/ip6_tables.c:42:16: sparse:   also defined here

vim +983 net/ipv6/netfilter/ip6_tables.c

3bc3fe5eed5e866 Patrick McHardy   2007-12-17   962  
f415e76fd723594 Christoph Hellwig 2020-07-17   963  static int get_info(struct net *net, void __user *user, const int *len)
433665c9d110d78 Patrick McHardy   2007-12-17   964  {
12b00c2c025b8af Jan Engelhardt    2010-10-13   965  	char name[XT_TABLE_MAXNAMELEN];
433665c9d110d78 Patrick McHardy   2007-12-17   966  	struct xt_table *t;
433665c9d110d78 Patrick McHardy   2007-12-17   967  	int ret;
433665c9d110d78 Patrick McHardy   2007-12-17   968  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03   969  	if (*len != sizeof(struct ip6t_getinfo))
433665c9d110d78 Patrick McHardy   2007-12-17   970  		return -EINVAL;
433665c9d110d78 Patrick McHardy   2007-12-17   971  
433665c9d110d78 Patrick McHardy   2007-12-17   972  	if (copy_from_user(name, user, sizeof(name)) != 0)
433665c9d110d78 Patrick McHardy   2007-12-17   973  		return -EFAULT;
433665c9d110d78 Patrick McHardy   2007-12-17   974  
12b00c2c025b8af Jan Engelhardt    2010-10-13   975  	name[XT_TABLE_MAXNAMELEN-1] = '\0';
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   976  #ifdef CONFIG_COMPAT
f415e76fd723594 Christoph Hellwig 2020-07-17   977  	if (in_compat_syscall())
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   978  		xt_compat_lock(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   979  #endif
03d13b6868a261f Florian Westphal  2017-12-08   980  	t = xt_request_find_table_lock(net, AF_INET6, name);
03d13b6868a261f Florian Westphal  2017-12-08   981  	if (!IS_ERR(t)) {
433665c9d110d78 Patrick McHardy   2007-12-17   982  		struct ip6t_getinfo info;
5452e425adfdfc4 Jan Engelhardt    2008-04-14  @983  		const struct xt_table_info *private = t->private;
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   984  #ifdef CONFIG_COMPAT
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   985  		struct xt_table_info tmp;
14c7dbe043d01a8 Alexey Dobriyan   2010-02-08   986  
f415e76fd723594 Christoph Hellwig 2020-07-17   987  		if (in_compat_syscall()) {
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   988  			ret = compat_table_info(private, &tmp);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   989  			xt_compat_flush_offsets(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   990  			private = &tmp;
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   991  		}
3bc3fe5eed5e866 Patrick McHardy   2007-12-17   992  #endif
cccbe5ef8528462 Jan Engelhardt    2010-11-03   993  		memset(&info, 0, sizeof(info));
433665c9d110d78 Patrick McHardy   2007-12-17   994  		info.valid_hooks = t->valid_hooks;
433665c9d110d78 Patrick McHardy   2007-12-17   995  		memcpy(info.hook_entry, private->hook_entry,
433665c9d110d78 Patrick McHardy   2007-12-17   996  		       sizeof(info.hook_entry));
433665c9d110d78 Patrick McHardy   2007-12-17   997  		memcpy(info.underflow, private->underflow,
433665c9d110d78 Patrick McHardy   2007-12-17   998  		       sizeof(info.underflow));
433665c9d110d78 Patrick McHardy   2007-12-17   999  		info.num_entries = private->number;
433665c9d110d78 Patrick McHardy   2007-12-17  1000  		info.size = private->size;
b5dd674b2a1de59 Patrick McHardy   2007-12-17  1001  		strcpy(info.name, name);
433665c9d110d78 Patrick McHardy   2007-12-17  1002  
433665c9d110d78 Patrick McHardy   2007-12-17  1003  		if (copy_to_user(user, &info, *len) != 0)
433665c9d110d78 Patrick McHardy   2007-12-17  1004  			ret = -EFAULT;
433665c9d110d78 Patrick McHardy   2007-12-17  1005  		else
433665c9d110d78 Patrick McHardy   2007-12-17  1006  			ret = 0;
433665c9d110d78 Patrick McHardy   2007-12-17  1007  
433665c9d110d78 Patrick McHardy   2007-12-17  1008  		xt_table_unlock(t);
433665c9d110d78 Patrick McHardy   2007-12-17  1009  		module_put(t->me);
433665c9d110d78 Patrick McHardy   2007-12-17  1010  	} else
03d13b6868a261f Florian Westphal  2017-12-08  1011  		ret = PTR_ERR(t);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1012  #ifdef CONFIG_COMPAT
f415e76fd723594 Christoph Hellwig 2020-07-17  1013  	if (in_compat_syscall())
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1014  		xt_compat_unlock(AF_INET6);
3bc3fe5eed5e866 Patrick McHardy   2007-12-17  1015  #endif
433665c9d110d78 Patrick McHardy   2007-12-17  1016  	return ret;
433665c9d110d78 Patrick McHardy   2007-12-17  1017  }
433665c9d110d78 Patrick McHardy   2007-12-17  1018  
^1da177e4c3f415 Linus Torvalds    2005-04-16  1019  static int
d5d1baa15f5b05e Jan Engelhardt    2009-06-26  1020  get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
d5d1baa15f5b05e Jan Engelhardt    2009-06-26  1021  	    const int *len)
^1da177e4c3f415 Linus Torvalds    2005-04-16  1022  {
^1da177e4c3f415 Linus Torvalds    2005-04-16  1023  	int ret;
d924357c50d83e7 Patrick McHardy   2007-12-17  1024  	struct ip6t_get_entries get;
2e4e6a17af35be3 Harald Welte      2006-01-12  1025  	struct xt_table *t;
^1da177e4c3f415 Linus Torvalds    2005-04-16  1026  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1027  	if (*len < sizeof(get))
d924357c50d83e7 Patrick McHardy   2007-12-17  1028  		return -EINVAL;
d924357c50d83e7 Patrick McHardy   2007-12-17  1029  	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
d924357c50d83e7 Patrick McHardy   2007-12-17  1030  		return -EFAULT;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1031  	if (*len != sizeof(struct ip6t_get_entries) + get.size)
d924357c50d83e7 Patrick McHardy   2007-12-17  1032  		return -EINVAL;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1033  
b301f2538759933 Pablo Neira Ayuso 2016-03-24  1034  	get.name[sizeof(get.name) - 1] = '\0';
d924357c50d83e7 Patrick McHardy   2007-12-17  1035  
336b517fdc0f92f Alexey Dobriyan   2008-01-31  1036  	t = xt_find_table_lock(net, AF_INET6, get.name);
03d13b6868a261f Florian Westphal  2017-12-08  1037  	if (!IS_ERR(t)) {
2e4e6a17af35be3 Harald Welte      2006-01-12 @1038  		struct xt_table_info *private = t->private;
d924357c50d83e7 Patrick McHardy   2007-12-17  1039  		if (get.size == private->size)
2e4e6a17af35be3 Harald Welte      2006-01-12  1040  			ret = copy_entries_to_user(private->size,
^1da177e4c3f415 Linus Torvalds    2005-04-16  1041  						   t, uptr->entrytable);
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1042  		else
544473c1664f3a6 Patrick McHardy   2008-04-14  1043  			ret = -EAGAIN;
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  1044  
6b7d31fcdda5938 Harald Welte      2005-10-26  1045  		module_put(t->me);
2e4e6a17af35be3 Harald Welte      2006-01-12  1046  		xt_table_unlock(t);
^1da177e4c3f415 Linus Torvalds    2005-04-16  1047  	} else
03d13b6868a261f Florian Westphal  2017-12-08  1048  		ret = PTR_ERR(t);
^1da177e4c3f415 Linus Torvalds    2005-04-16  1049  
^1da177e4c3f415 Linus Torvalds    2005-04-16  1050  	return ret;
^1da177e4c3f415 Linus Torvalds    2005-04-16  1051  }
^1da177e4c3f415 Linus Torvalds    2005-04-16  1052  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 36080 bytes --]

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
  2020-11-22 19:17 [PATCH nf] netfilter: x_tables: Switch synchronization to RCU Subash Abhinov Kasiviswanathan
@ 2020-11-25  3:40   ` kernel test robot
  2020-11-22 20:58   ` kernel test robot
  2020-11-25  3:40   ` kernel test robot
  2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2020-11-25  3:40 UTC (permalink / raw)
  To: Subash Abhinov Kasiviswanathan, will, pablo, stranche,
	netfilter-devel, tglx, fw, peterz
  Cc: kbuild-all, Subash Abhinov Kasiviswanathan

[-- Attachment #1: Type: text/plain, Size: 7127 bytes --]

Hi Subash,

I love your patch! Perhaps something to improve:

[auto build test WARNING on nf/master]

url:    https://github.com/0day-ci/linux/commits/Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
config: i386-randconfig-s002-20201125 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-151-g540c2c4b-dirty
        # https://github.com/0day-ci/linux/commit/2d87a7da9e77a1c31af435d23238e60d0067aac0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
        git checkout 2d87a7da9e77a1c31af435d23238e60d0067aac0
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse:     expected struct xt_table_info const *private
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv4/netfilter/arp_tables.c:863:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv4/netfilter/arp_tables.c:863:56: sparse:     expected struct xt_table_info const *private
   net/ipv4/netfilter/arp_tables.c:863:56: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv4/netfilter/arp_tables.c:1020:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv4/netfilter/arp_tables.c:1020:17: sparse:     expected struct xt_table_info const *private
   net/ipv4/netfilter/arp_tables.c:1020:17: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv4/netfilter/arp_tables.c:40:16: sparse: sparse: Initializer entry defined twice
   net/ipv4/netfilter/arp_tables.c:40:16: sparse:   also defined here
   net/ipv4/netfilter/arp_tables.c:40:16: sparse: sparse: Initializer entry defined twice
   net/ipv4/netfilter/arp_tables.c:40:16: sparse:   also defined here

vim +810 net/ipv4/netfilter/arp_tables.c

d6a2ba07c31b049 Patrick McHardy   2007-12-17  789  
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  790  static int get_info(struct net *net, void __user *user, const int *len)
41acd975b954ad6 Patrick McHardy   2007-12-17  791  {
12b00c2c025b8af Jan Engelhardt    2010-10-13  792  	char name[XT_TABLE_MAXNAMELEN];
4abff0775d5e4fe Jan Engelhardt    2008-04-14  793  	struct xt_table *t;
41acd975b954ad6 Patrick McHardy   2007-12-17  794  	int ret;
41acd975b954ad6 Patrick McHardy   2007-12-17  795  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  796  	if (*len != sizeof(struct arpt_getinfo))
41acd975b954ad6 Patrick McHardy   2007-12-17  797  		return -EINVAL;
41acd975b954ad6 Patrick McHardy   2007-12-17  798  
41acd975b954ad6 Patrick McHardy   2007-12-17  799  	if (copy_from_user(name, user, sizeof(name)) != 0)
41acd975b954ad6 Patrick McHardy   2007-12-17  800  		return -EFAULT;
41acd975b954ad6 Patrick McHardy   2007-12-17  801  
12b00c2c025b8af Jan Engelhardt    2010-10-13  802  	name[XT_TABLE_MAXNAMELEN-1] = '\0';
d6a2ba07c31b049 Patrick McHardy   2007-12-17  803  #ifdef CONFIG_COMPAT
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  804  	if (in_compat_syscall())
ee999d8b9573df1 Jan Engelhardt    2008-10-08  805  		xt_compat_lock(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  806  #endif
03d13b6868a261f Florian Westphal  2017-12-08  807  	t = xt_request_find_table_lock(net, NFPROTO_ARP, name);
03d13b6868a261f Florian Westphal  2017-12-08  808  	if (!IS_ERR(t)) {
41acd975b954ad6 Patrick McHardy   2007-12-17  809  		struct arpt_getinfo info;
5452e425adfdfc4 Jan Engelhardt    2008-04-14 @810  		const struct xt_table_info *private = t->private;
d6a2ba07c31b049 Patrick McHardy   2007-12-17  811  #ifdef CONFIG_COMPAT
d6a2ba07c31b049 Patrick McHardy   2007-12-17  812  		struct xt_table_info tmp;
14c7dbe043d01a8 Alexey Dobriyan   2010-02-08  813  
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  814  		if (in_compat_syscall()) {
d6a2ba07c31b049 Patrick McHardy   2007-12-17  815  			ret = compat_table_info(private, &tmp);
ee999d8b9573df1 Jan Engelhardt    2008-10-08  816  			xt_compat_flush_offsets(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  817  			private = &tmp;
d6a2ba07c31b049 Patrick McHardy   2007-12-17  818  		}
d6a2ba07c31b049 Patrick McHardy   2007-12-17  819  #endif
1a8b7a67224eb0c Vasiliy Kulikov   2010-11-03  820  		memset(&info, 0, sizeof(info));
41acd975b954ad6 Patrick McHardy   2007-12-17  821  		info.valid_hooks = t->valid_hooks;
41acd975b954ad6 Patrick McHardy   2007-12-17  822  		memcpy(info.hook_entry, private->hook_entry,
41acd975b954ad6 Patrick McHardy   2007-12-17  823  		       sizeof(info.hook_entry));
41acd975b954ad6 Patrick McHardy   2007-12-17  824  		memcpy(info.underflow, private->underflow,
41acd975b954ad6 Patrick McHardy   2007-12-17  825  		       sizeof(info.underflow));
41acd975b954ad6 Patrick McHardy   2007-12-17  826  		info.num_entries = private->number;
41acd975b954ad6 Patrick McHardy   2007-12-17  827  		info.size = private->size;
41acd975b954ad6 Patrick McHardy   2007-12-17  828  		strcpy(info.name, name);
41acd975b954ad6 Patrick McHardy   2007-12-17  829  
41acd975b954ad6 Patrick McHardy   2007-12-17  830  		if (copy_to_user(user, &info, *len) != 0)
41acd975b954ad6 Patrick McHardy   2007-12-17  831  			ret = -EFAULT;
41acd975b954ad6 Patrick McHardy   2007-12-17  832  		else
41acd975b954ad6 Patrick McHardy   2007-12-17  833  			ret = 0;
41acd975b954ad6 Patrick McHardy   2007-12-17  834  		xt_table_unlock(t);
41acd975b954ad6 Patrick McHardy   2007-12-17  835  		module_put(t->me);
41acd975b954ad6 Patrick McHardy   2007-12-17  836  	} else
03d13b6868a261f Florian Westphal  2017-12-08  837  		ret = PTR_ERR(t);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  838  #ifdef CONFIG_COMPAT
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  839  	if (in_compat_syscall())
ee999d8b9573df1 Jan Engelhardt    2008-10-08  840  		xt_compat_unlock(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  841  #endif
41acd975b954ad6 Patrick McHardy   2007-12-17  842  	return ret;
41acd975b954ad6 Patrick McHardy   2007-12-17  843  }
41acd975b954ad6 Patrick McHardy   2007-12-17  844  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 40421 bytes --]

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
@ 2020-11-25  3:40   ` kernel test robot
  0 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2020-11-25  3:40 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 7230 bytes --]

Hi Subash,

I love your patch! Perhaps something to improve:

[auto build test WARNING on nf/master]

url:    https://github.com/0day-ci/linux/commits/Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
config: i386-randconfig-s002-20201125 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-151-g540c2c4b-dirty
        # https://github.com/0day-ci/linux/commit/2d87a7da9e77a1c31af435d23238e60d0067aac0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Subash-Abhinov-Kasiviswanathan/netfilter-x_tables-Switch-synchronization-to-RCU/20201123-032122
        git checkout 2d87a7da9e77a1c31af435d23238e60d0067aac0
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse:     expected struct xt_table_info const *private
>> net/ipv4/netfilter/arp_tables.c:810:56: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv4/netfilter/arp_tables.c:863:56: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv4/netfilter/arp_tables.c:863:56: sparse:     expected struct xt_table_info const *private
   net/ipv4/netfilter/arp_tables.c:863:56: sparse:     got struct xt_table_info [noderef] __rcu *private
>> net/ipv4/netfilter/arp_tables.c:1020:17: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct xt_table_info const *private @@     got struct xt_table_info [noderef] __rcu *private @@
   net/ipv4/netfilter/arp_tables.c:1020:17: sparse:     expected struct xt_table_info const *private
   net/ipv4/netfilter/arp_tables.c:1020:17: sparse:     got struct xt_table_info [noderef] __rcu *private
   net/ipv4/netfilter/arp_tables.c:40:16: sparse: sparse: Initializer entry defined twice
   net/ipv4/netfilter/arp_tables.c:40:16: sparse:   also defined here
   net/ipv4/netfilter/arp_tables.c:40:16: sparse: sparse: Initializer entry defined twice
   net/ipv4/netfilter/arp_tables.c:40:16: sparse:   also defined here

vim +810 net/ipv4/netfilter/arp_tables.c

d6a2ba07c31b049 Patrick McHardy   2007-12-17  789  
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  790  static int get_info(struct net *net, void __user *user, const int *len)
41acd975b954ad6 Patrick McHardy   2007-12-17  791  {
12b00c2c025b8af Jan Engelhardt    2010-10-13  792  	char name[XT_TABLE_MAXNAMELEN];
4abff0775d5e4fe Jan Engelhardt    2008-04-14  793  	struct xt_table *t;
41acd975b954ad6 Patrick McHardy   2007-12-17  794  	int ret;
41acd975b954ad6 Patrick McHardy   2007-12-17  795  
d7cdf81657776ca Pablo Neira Ayuso 2016-05-03  796  	if (*len != sizeof(struct arpt_getinfo))
41acd975b954ad6 Patrick McHardy   2007-12-17  797  		return -EINVAL;
41acd975b954ad6 Patrick McHardy   2007-12-17  798  
41acd975b954ad6 Patrick McHardy   2007-12-17  799  	if (copy_from_user(name, user, sizeof(name)) != 0)
41acd975b954ad6 Patrick McHardy   2007-12-17  800  		return -EFAULT;
41acd975b954ad6 Patrick McHardy   2007-12-17  801  
12b00c2c025b8af Jan Engelhardt    2010-10-13  802  	name[XT_TABLE_MAXNAMELEN-1] = '\0';
d6a2ba07c31b049 Patrick McHardy   2007-12-17  803  #ifdef CONFIG_COMPAT
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  804  	if (in_compat_syscall())
ee999d8b9573df1 Jan Engelhardt    2008-10-08  805  		xt_compat_lock(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  806  #endif
03d13b6868a261f Florian Westphal  2017-12-08  807  	t = xt_request_find_table_lock(net, NFPROTO_ARP, name);
03d13b6868a261f Florian Westphal  2017-12-08  808  	if (!IS_ERR(t)) {
41acd975b954ad6 Patrick McHardy   2007-12-17  809  		struct arpt_getinfo info;
5452e425adfdfc4 Jan Engelhardt    2008-04-14 @810  		const struct xt_table_info *private = t->private;
d6a2ba07c31b049 Patrick McHardy   2007-12-17  811  #ifdef CONFIG_COMPAT
d6a2ba07c31b049 Patrick McHardy   2007-12-17  812  		struct xt_table_info tmp;
14c7dbe043d01a8 Alexey Dobriyan   2010-02-08  813  
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  814  		if (in_compat_syscall()) {
d6a2ba07c31b049 Patrick McHardy   2007-12-17  815  			ret = compat_table_info(private, &tmp);
ee999d8b9573df1 Jan Engelhardt    2008-10-08  816  			xt_compat_flush_offsets(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  817  			private = &tmp;
d6a2ba07c31b049 Patrick McHardy   2007-12-17  818  		}
d6a2ba07c31b049 Patrick McHardy   2007-12-17  819  #endif
1a8b7a67224eb0c Vasiliy Kulikov   2010-11-03  820  		memset(&info, 0, sizeof(info));
41acd975b954ad6 Patrick McHardy   2007-12-17  821  		info.valid_hooks = t->valid_hooks;
41acd975b954ad6 Patrick McHardy   2007-12-17  822  		memcpy(info.hook_entry, private->hook_entry,
41acd975b954ad6 Patrick McHardy   2007-12-17  823  		       sizeof(info.hook_entry));
41acd975b954ad6 Patrick McHardy   2007-12-17  824  		memcpy(info.underflow, private->underflow,
41acd975b954ad6 Patrick McHardy   2007-12-17  825  		       sizeof(info.underflow));
41acd975b954ad6 Patrick McHardy   2007-12-17  826  		info.num_entries = private->number;
41acd975b954ad6 Patrick McHardy   2007-12-17  827  		info.size = private->size;
41acd975b954ad6 Patrick McHardy   2007-12-17  828  		strcpy(info.name, name);
41acd975b954ad6 Patrick McHardy   2007-12-17  829  
41acd975b954ad6 Patrick McHardy   2007-12-17  830  		if (copy_to_user(user, &info, *len) != 0)
41acd975b954ad6 Patrick McHardy   2007-12-17  831  			ret = -EFAULT;
41acd975b954ad6 Patrick McHardy   2007-12-17  832  		else
41acd975b954ad6 Patrick McHardy   2007-12-17  833  			ret = 0;
41acd975b954ad6 Patrick McHardy   2007-12-17  834  		xt_table_unlock(t);
41acd975b954ad6 Patrick McHardy   2007-12-17  835  		module_put(t->me);
41acd975b954ad6 Patrick McHardy   2007-12-17  836  	} else
03d13b6868a261f Florian Westphal  2017-12-08  837  		ret = PTR_ERR(t);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  838  #ifdef CONFIG_COMPAT
983094b4fc2d6a0 Christoph Hellwig 2020-07-17  839  	if (in_compat_syscall())
ee999d8b9573df1 Jan Engelhardt    2008-10-08  840  		xt_compat_unlock(NFPROTO_ARP);
d6a2ba07c31b049 Patrick McHardy   2007-12-17  841  #endif
41acd975b954ad6 Patrick McHardy   2007-12-17  842  	return ret;
41acd975b954ad6 Patrick McHardy   2007-12-17  843  }
41acd975b954ad6 Patrick McHardy   2007-12-17  844  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 40421 bytes --]

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

* Re: [PATCH nf] netfilter: x_tables: Switch synchronization to RCU
  2020-11-22 19:55   ` subashab
@ 2020-11-25  6:25     ` subashab
  0 siblings, 0 replies; 8+ messages in thread
From: subashab @ 2020-11-25  6:25 UTC (permalink / raw)
  To: Florian Westphal; +Cc: will, pablo, stranche, netfilter-devel, tglx, peterz

>> Did you test it with PROVE_LOCKING enabled?
>> 
>> The placement/use of rcu_dereference and the _protected version
>> looks correct, I would not expect splats.
> 

I've tested it now with CONFIG_PROVE_LOCKING=y along with concurrent 
packet
transfer and addition and removal of rules. I haven't observed any
crashes or warnings so far.

I have also fixed the sparse warnings reported by kbuilt test robot.
Here is the updated patch-

diff --git a/include/linux/netfilter/x_tables.h 
b/include/linux/netfilter/x_tables.h
index 5deb099..8ebb641 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;
@@ -448,6 +448,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, 
unsigned int cpu)

  struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, 
nf_hookfn *);

+struct xt_table_info
+*xt_table_get_private_protected(const struct xt_table *table);
+
  #ifdef CONFIG_COMPAT
  #include <net/compat.h>

diff --git a/net/ipv4/netfilter/arp_tables.c 
b/net/ipv4/netfilter/arp_tables.c
index d1e04d2..563b62b 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);
  	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 = 
xt_table_get_private_protected(table);

  	/* We need atomic snapshot of counters: rest doesn't change
  	 * (other than comefrom, which userspace doesn't care
@@ -673,7 +673,7 @@ static int copy_entries_to_user(unsigned int 
total_size,
  	unsigned int off, num;
  	const struct arpt_entry *e;
  	struct xt_counters *counters;
-	struct xt_table_info *private = table->private;
+	struct xt_table_info *private = xt_table_get_private_protected(table);
  	int ret = 0;
  	void *loc_cpu_entry;

@@ -807,7 +807,7 @@ static int get_info(struct net *net, void __user 
*user, const int *len)
  	t = xt_request_find_table_lock(net, NFPROTO_ARP, name);
  	if (!IS_ERR(t)) {
  		struct arpt_getinfo info;
-		const struct xt_table_info *private = t->private;
+		const struct xt_table_info *private = 
xt_table_get_private_protected(t);
  #ifdef CONFIG_COMPAT
  		struct xt_table_info tmp;

@@ -860,7 +860,7 @@ static int get_entries(struct net *net, struct 
arpt_get_entries __user *uptr,

  	t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
  	if (!IS_ERR(t)) {
-		const struct xt_table_info *private = t->private;
+		const struct xt_table_info *private = 
xt_table_get_private_protected(t);

  		if (get.size == private->size)
  			ret = copy_entries_to_user(private->size,
@@ -1017,7 +1017,7 @@ static int do_add_counters(struct net *net, 
sockptr_t arg, unsigned int len)
  	}

  	local_bh_disable();
-	private = t->private;
+	private = xt_table_get_private_protected(t);
  	if (private->number != tmp.num_counters) {
  		ret = -EINVAL;
  		goto unlock_up_free;
@@ -1330,7 +1330,7 @@ static int compat_copy_entries_to_user(unsigned 
int total_size,
  				       void __user *userptr)
  {
  	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = 
xt_table_get_private_protected(table);
  	void __user *pos;
  	unsigned int size;
  	int ret = 0;
diff --git a/net/ipv4/netfilter/ip_tables.c 
b/net/ipv4/netfilter/ip_tables.c
index f15bc21..6e2851f 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -258,7 +258,7 @@ ipt_do_table(struct sk_buff *skb,
  	WARN_ON(!(table->valid_hooks & (1 << hook)));
  	local_bh_disable();
  	addend = xt_write_recseq_begin();
-	private = READ_ONCE(table->private); /* Address dependency. */
+	private = rcu_access_pointer(table->private);
  	cpu        = smp_processor_id();
  	table_base = private->entries;
  	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
@@ -791,7 +791,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 = 
xt_table_get_private_protected(table);

  	/* We need atomic snapshot of counters: rest doesn't change
  	   (other than comefrom, which userspace doesn't care
@@ -815,7 +815,7 @@ copy_entries_to_user(unsigned int total_size,
  	unsigned int off, num;
  	const struct ipt_entry *e;
  	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = 
xt_table_get_private_protected(table);
  	int ret = 0;
  	const void *loc_cpu_entry;

@@ -964,7 +964,7 @@ static int get_info(struct net *net, void __user 
*user, const int *len)
  	t = xt_request_find_table_lock(net, AF_INET, name);
  	if (!IS_ERR(t)) {
  		struct ipt_getinfo info;
-		const struct xt_table_info *private = t->private;
+		const struct xt_table_info *private = 
xt_table_get_private_protected(t);
  #ifdef CONFIG_COMPAT
  		struct xt_table_info tmp;

@@ -1018,7 +1018,7 @@ get_entries(struct net *net, struct 
ipt_get_entries __user *uptr,

  	t = xt_find_table_lock(net, AF_INET, get.name);
  	if (!IS_ERR(t)) {
-		const struct xt_table_info *private = t->private;
+		const struct xt_table_info *private = 
xt_table_get_private_protected(t);
  		if (get.size == private->size)
  			ret = copy_entries_to_user(private->size,
  						   t, uptr->entrytable);
@@ -1173,7 +1173,7 @@ do_add_counters(struct net *net, sockptr_t arg, 
unsigned int len)
  	}

  	local_bh_disable();
-	private = t->private;
+	private = xt_table_get_private_protected(t);
  	if (private->number != tmp.num_counters) {
  		ret = -EINVAL;
  		goto unlock_up_free;
@@ -1543,7 +1543,7 @@ compat_copy_entries_to_user(unsigned int 
total_size, struct xt_table *table,
  			    void __user *userptr)
  {
  	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = 
xt_table_get_private_protected(table);
  	void __user *pos;
  	unsigned int size;
  	int ret = 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c 
b/net/ipv6/netfilter/ip6_tables.c
index 2e2119b..c4f532f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -280,7 +280,7 @@ ip6t_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);
  	cpu        = smp_processor_id();
  	table_base = private->entries;
  	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
@@ -807,7 +807,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 = 
xt_table_get_private_protected(table);

  	/* We need atomic snapshot of counters: rest doesn't change
  	   (other than comefrom, which userspace doesn't care
@@ -831,7 +831,7 @@ copy_entries_to_user(unsigned int total_size,
  	unsigned int off, num;
  	const struct ip6t_entry *e;
  	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = 
xt_table_get_private_protected(table);
  	int ret = 0;
  	const void *loc_cpu_entry;

@@ -980,7 +980,7 @@ static int get_info(struct net *net, void __user 
*user, const int *len)
  	t = xt_request_find_table_lock(net, AF_INET6, name);
  	if (!IS_ERR(t)) {
  		struct ip6t_getinfo info;
-		const struct xt_table_info *private = t->private;
+		const struct xt_table_info *private = 
xt_table_get_private_protected(t);
  #ifdef CONFIG_COMPAT
  		struct xt_table_info tmp;

@@ -1035,7 +1035,7 @@ get_entries(struct net *net, struct 
ip6t_get_entries __user *uptr,

  	t = xt_find_table_lock(net, AF_INET6, get.name);
  	if (!IS_ERR(t)) {
-		struct xt_table_info *private = t->private;
+		struct xt_table_info *private = xt_table_get_private_protected(t);
  		if (get.size == private->size)
  			ret = copy_entries_to_user(private->size,
  						   t, uptr->entrytable);
@@ -1189,7 +1189,7 @@ do_add_counters(struct net *net, sockptr_t arg, 
unsigned int len)
  	}

  	local_bh_disable();
-	private = t->private;
+	private = xt_table_get_private_protected(t);
  	if (private->number != tmp.num_counters) {
  		ret = -EINVAL;
  		goto unlock_up_free;
@@ -1552,7 +1552,7 @@ compat_copy_entries_to_user(unsigned int 
total_size, struct xt_table *table,
  			    void __user *userptr)
  {
  	struct xt_counters *counters;
-	const struct xt_table_info *private = table->private;
+	const struct xt_table_info *private = 
xt_table_get_private_protected(table);
  	void __user *pos;
  	unsigned int size;
  	int ret = 0;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index af22dbe..acce622 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1349,6 +1349,14 @@ struct xt_counters *xt_counters_alloc(unsigned 
int counters)
  }
  EXPORT_SYMBOL(xt_counters_alloc);

+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);
+
  struct xt_table_info *
  xt_replace_table(struct xt_table *table,
  	      unsigned int num_counters,
@@ -1356,7 +1364,6 @@ xt_replace_table(struct xt_table *table,
  	      int *error)
  {
  	struct xt_table_info *private;
-	unsigned int cpu;
  	int ret;

  	ret = xt_jumpstack_alloc(newinfo);
@@ -1366,47 +1373,20 @@ xt_replace_table(struct xt_table *table,
  	}

  	/* Do the substitution. */
-	local_bh_disable();
-	private = table->private;
+	private = xt_table_get_private_protected(table);

  	/* Check inside lock: is the old number correct? */
  	if (num_counters != private->number) {
  		pr_debug("num_counters != table->private->number (%u/%u)\n",
  			 num_counters, private->number);
-		local_bh_enable();
  		*error = -EAGAIN;
  		return NULL;
  	}

  	newinfo->initial_entries = private->initial_entries;
-	/*
-	 * Ensure contents of newinfo are visible before assigning to
-	 * private.
-	 */
-	smp_wmb();
-	table->private = newinfo;
-
-	/* make sure all cpus see new ->private value */
-	smp_wmb();

-	/*
-	 * Even though table entries have now been swapped, other CPU's
-	 * may still be using the old entries...
-	 */
-	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));
-		}
-	}
+	rcu_assign_pointer(table->private, newinfo);
+	synchronize_rcu();

  	audit_log_nfcfg(table->name, table->af, private->number,
  			!private->number ? AUDIT_XT_OP_REGISTER :
@@ -1442,12 +1422,12 @@ struct xt_table *xt_register_table(struct net 
*net,
  	}

  	/* Simplifies replace_table code. */
-	table->private = bootstrap;
+	rcu_assign_pointer(table->private, bootstrap);

  	if (!xt_replace_table(table, 0, newinfo, &ret))
  		goto unlock;

-	private = table->private;
+	private = xt_table_get_private_protected(table);
  	pr_debug("table->private->number = %u\n", private->number);

  	/* save number of initial entries */
@@ -1470,7 +1450,8 @@ void *xt_unregister_table(struct xt_table *table)
  	struct xt_table_info *private;

  	mutex_lock(&xt[table->af].mutex);
-	private = table->private;
+	private = xt_table_get_private_protected(table);
+	RCU_INIT_POINTER(table->private, NULL);
  	list_del(&table->list);
  	mutex_unlock(&xt[table->af].mutex);
  	audit_log_nfcfg(table->name, table->af, private->number,


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

end of thread, other threads:[~2020-11-25  6:25 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-22 19:17 [PATCH nf] netfilter: x_tables: Switch synchronization to RCU Subash Abhinov Kasiviswanathan
2020-11-22 19:35 ` Florian Westphal
2020-11-22 19:55   ` subashab
2020-11-25  6:25     ` subashab
2020-11-22 20:58 ` kernel test robot
2020-11-22 20:58   ` kernel test robot
2020-11-25  3:40 ` kernel test robot
2020-11-25  3:40   ` kernel test robot

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.