Re: [PATCH nf 1/2] netfilter: nf_conncount: use spin_lock_bh instead of spin_lock

2018-10-30 Thread Taehee Yoo
Thanks to all reviewer!

On Tue, 30 Oct 2018 at 08:41, Florian Westphal  wrote:
>
> Pablo Neira Ayuso  wrote:
> > On Thu, Oct 25, 2018 at 11:56:12PM +0900, Taehee Yoo wrote:
> > > conn_free() holds lock with spin_lock(). and it is called by both
> > > nf_conncount_lookup() and nf_conncount_gc_list().
> > > nf_conncount_lookup() is bottom-half context and nf_conncount_gc_list()
> > > is process context. so that spin_lock() is not safe.
> > > Hence conn_free() should use spin_lock_bh() instead of spin_lock().
> > >
> > > test commands:
> > >%nft add table ip filter
> > >%nft add chain ip filter input { type filter hook input priority 0\; }
> > >%nft add rule filter input meter test { ip saddr ct count over 2 } \
> > >counter
> > >
> > > splat looks like:
> > > [  461.996507] 
> > > [  461.998999] WARNING: inconsistent lock state
> > > [  461.998999] 4.19.0-rc6+ #22 Not tainted
> > > [  461.998999] 
> > > [  461.998999] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
> > > [  461.998999] kworker/0:2/134 [HC0[0]:SC0[0]:HE1:SE1] takes:
> > > [  461.998999] a71a559a (&(>list_lock)->rlock){+.?.}, at: 
> > > conn_free+0x69/0x2b0 [nf_conncount]
> > > [  461.998999] {IN-SOFTIRQ-W} state was registered at:
> > > [  461.998999]   _raw_spin_lock+0x30/0x70
> > > [  461.998999]   nf_conncount_add+0x28a/0x520 [nf_conncount]
> > > [  461.998999]   nft_connlimit_eval+0x401/0x580 [nft_connlimit]
> > > [  461.998999]   nft_dynset_eval+0x32b/0x590 [nf_tables]
> > > [  461.998999]   nft_do_chain+0x497/0x1430 [nf_tables]
> > > [  461.998999]   nft_do_chain_ipv4+0x255/0x330 [nf_tables]
> > > [  461.998999]   nf_hook_slow+0xb1/0x160
> > > [ ... ]
> > > [  461.998999] other info that might help us debug this:
> > > [  461.998999]  Possible unsafe locking scenario:
> > > [  461.998999]
> > > [  461.998999]CPU0
> > > [  461.998999]
> > > [  461.998999]   lock(&(>list_lock)->rlock);
> > > [  461.998999]   
> > > [  461.998999] lock(&(>list_lock)->rlock);
> > > [  461.998999]
> > > [  461.998999]  *** DEADLOCK ***
> > > [  461.998999]
> > > [ ... ]
> >
> > nf_conncount_add() also holds spin_lock while allocate from there is
> > GFP_ATOMIC given this is called from packet path.
>
> Good catch, yes, this needs spin_lock_bh variant too.
>
> > tree_nodes_free() is also called from user context without _bh
> > disabled.
>
> This one is fine, both call sites hold spin_lock_bh(_conncount_locks[x]).

I will test then I will send v2 patch!

Thanks!


Re: [PATCH nf 1/2] netfilter: nf_conncount: use spin_lock_bh instead of spin_lock

2018-10-29 Thread Florian Westphal
Pablo Neira Ayuso  wrote:
> On Thu, Oct 25, 2018 at 11:56:12PM +0900, Taehee Yoo wrote:
> > conn_free() holds lock with spin_lock(). and it is called by both
> > nf_conncount_lookup() and nf_conncount_gc_list().
> > nf_conncount_lookup() is bottom-half context and nf_conncount_gc_list()
> > is process context. so that spin_lock() is not safe.
> > Hence conn_free() should use spin_lock_bh() instead of spin_lock().
> > 
> > test commands:
> >%nft add table ip filter
> >%nft add chain ip filter input { type filter hook input priority 0\; }
> >%nft add rule filter input meter test { ip saddr ct count over 2 } \
> >counter
> > 
> > splat looks like:
> > [  461.996507] 
> > [  461.998999] WARNING: inconsistent lock state
> > [  461.998999] 4.19.0-rc6+ #22 Not tainted
> > [  461.998999] 
> > [  461.998999] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
> > [  461.998999] kworker/0:2/134 [HC0[0]:SC0[0]:HE1:SE1] takes:
> > [  461.998999] a71a559a (&(>list_lock)->rlock){+.?.}, at: 
> > conn_free+0x69/0x2b0 [nf_conncount]
> > [  461.998999] {IN-SOFTIRQ-W} state was registered at:
> > [  461.998999]   _raw_spin_lock+0x30/0x70
> > [  461.998999]   nf_conncount_add+0x28a/0x520 [nf_conncount]
> > [  461.998999]   nft_connlimit_eval+0x401/0x580 [nft_connlimit]
> > [  461.998999]   nft_dynset_eval+0x32b/0x590 [nf_tables]
> > [  461.998999]   nft_do_chain+0x497/0x1430 [nf_tables]
> > [  461.998999]   nft_do_chain_ipv4+0x255/0x330 [nf_tables]
> > [  461.998999]   nf_hook_slow+0xb1/0x160
> > [ ... ]
> > [  461.998999] other info that might help us debug this:
> > [  461.998999]  Possible unsafe locking scenario:
> > [  461.998999]
> > [  461.998999]CPU0
> > [  461.998999]
> > [  461.998999]   lock(&(>list_lock)->rlock);
> > [  461.998999]   
> > [  461.998999] lock(&(>list_lock)->rlock);
> > [  461.998999]
> > [  461.998999]  *** DEADLOCK ***
> > [  461.998999]
> > [ ... ]
> 
> nf_conncount_add() also holds spin_lock while allocate from there is
> GFP_ATOMIC given this is called from packet path.

Good catch, yes, this needs spin_lock_bh variant too.

> tree_nodes_free() is also called from user context without _bh
> disabled.

This one is fine, both call sites hold spin_lock_bh(_conncount_locks[x]).


Re: [PATCH nf 1/2] netfilter: nf_conncount: use spin_lock_bh instead of spin_lock

2018-10-29 Thread Pablo Neira Ayuso
On Thu, Oct 25, 2018 at 11:56:12PM +0900, Taehee Yoo wrote:
> conn_free() holds lock with spin_lock(). and it is called by both
> nf_conncount_lookup() and nf_conncount_gc_list().
> nf_conncount_lookup() is bottom-half context and nf_conncount_gc_list()
> is process context. so that spin_lock() is not safe.
> Hence conn_free() should use spin_lock_bh() instead of spin_lock().
> 
> test commands:
>%nft add table ip filter
>%nft add chain ip filter input { type filter hook input priority 0\; }
>%nft add rule filter input meter test { ip saddr ct count over 2 } \
>  counter
> 
> splat looks like:
> [  461.996507] 
> [  461.998999] WARNING: inconsistent lock state
> [  461.998999] 4.19.0-rc6+ #22 Not tainted
> [  461.998999] 
> [  461.998999] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
> [  461.998999] kworker/0:2/134 [HC0[0]:SC0[0]:HE1:SE1] takes:
> [  461.998999] a71a559a (&(>list_lock)->rlock){+.?.}, at: 
> conn_free+0x69/0x2b0 [nf_conncount]
> [  461.998999] {IN-SOFTIRQ-W} state was registered at:
> [  461.998999]   _raw_spin_lock+0x30/0x70
> [  461.998999]   nf_conncount_add+0x28a/0x520 [nf_conncount]
> [  461.998999]   nft_connlimit_eval+0x401/0x580 [nft_connlimit]
> [  461.998999]   nft_dynset_eval+0x32b/0x590 [nf_tables]
> [  461.998999]   nft_do_chain+0x497/0x1430 [nf_tables]
> [  461.998999]   nft_do_chain_ipv4+0x255/0x330 [nf_tables]
> [  461.998999]   nf_hook_slow+0xb1/0x160
> [ ... ]
> [  461.998999] other info that might help us debug this:
> [  461.998999]  Possible unsafe locking scenario:
> [  461.998999]
> [  461.998999]CPU0
> [  461.998999]
> [  461.998999]   lock(&(>list_lock)->rlock);
> [  461.998999]   
> [  461.998999] lock(&(>list_lock)->rlock);
> [  461.998999]
> [  461.998999]  *** DEADLOCK ***
> [  461.998999]
> [ ... ]

nf_conncount_add() also holds spin_lock while allocate from there is
GFP_ATOMIC given this is called from packet path.

tree_nodes_free() is also called from user context without _bh
disabled.

Is this fix complete?


Re: [PATCH nf 1/2] netfilter: nf_conncount: use spin_lock_bh instead of spin_lock

2018-10-29 Thread Yi-Hung Wei
On Thu, Oct 25, 2018 at 7:56 AM Taehee Yoo  wrote:
>
> conn_free() holds lock with spin_lock(). and it is called by both
> nf_conncount_lookup() and nf_conncount_gc_list().
> nf_conncount_lookup() is bottom-half context and nf_conncount_gc_list()
> is process context. so that spin_lock() is not safe.
> Hence conn_free() should use spin_lock_bh() instead of spin_lock().
>
> test commands:
>%nft add table ip filter
>%nft add chain ip filter input { type filter hook input priority 0\; }
>%nft add rule filter input meter test { ip saddr ct count over 2 } \
>counter
>
> Fixes: 5c789e131cbb ("netfilter: nf_conncount: Add list lock and gc worker, 
> and RCU for init tree search")
> Signed-off-by: Taehee Yoo 

Thanks for the fix.
Acked-by: Yi-Hung Wei