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] 00000000a71a559a (&(&list->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->list_lock)->rlock); > [ 461.998999] <Interrupt> > [ 461.998999] lock(&(&list->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?