linux/net/ipv4/netfilter
Taehee Yoo 095faf45e6 netfilter: nat: fix double register in masquerade modules
There is a reference counter to ensure that masquerade modules register
notifiers only once. However, the existing reference counter approach is
not safe, test commands are:

   while :
   do
   	   modprobe ip6t_MASQUERADE &
	   modprobe nft_masq_ipv6 &
	   modprobe -rv ip6t_MASQUERADE &
	   modprobe -rv nft_masq_ipv6 &
   done

numbers below represent the reference counter.
--------------------------------------------------------
CPU0        CPU1        CPU2        CPU3        CPU4
[insmod]    [insmod]    [rmmod]     [rmmod]     [insmod]
--------------------------------------------------------
0->1
register    1->2
            returns     2->1
			returns     1->0
                                                0->1
                                                register <--
                                    unregister
--------------------------------------------------------

The unregistation of CPU3 should be processed before the
registration of CPU4.

In order to fix this, use a mutex instead of reference counter.

splat looks like:
[  323.869557] watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [modprobe:1381]
[  323.869574] Modules linked in: nf_tables(+) nf_nat_ipv6(-) nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 n]
[  323.869574] irq event stamp: 194074
[  323.898930] hardirqs last  enabled at (194073): [<ffffffff90004a0d>] trace_hardirqs_on_thunk+0x1a/0x1c
[  323.898930] hardirqs last disabled at (194074): [<ffffffff90004a29>] trace_hardirqs_off_thunk+0x1a/0x1c
[  323.898930] softirqs last  enabled at (182132): [<ffffffff922006ec>] __do_softirq+0x6ec/0xa3b
[  323.898930] softirqs last disabled at (182109): [<ffffffff90193426>] irq_exit+0x1a6/0x1e0
[  323.898930] CPU: 0 PID: 1381 Comm: modprobe Not tainted 4.20.0-rc2+ #27
[  323.898930] RIP: 0010:raw_notifier_chain_register+0xea/0x240
[  323.898930] Code: 3c 03 0f 8e f2 00 00 00 44 3b 6b 10 7f 4d 49 bc 00 00 00 00 00 fc ff df eb 22 48 8d 7b 10 488
[  323.898930] RSP: 0018:ffff888101597218 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff13
[  323.898930] RAX: 0000000000000000 RBX: ffffffffc04361c0 RCX: 0000000000000000
[  323.898930] RDX: 1ffffffff26132ae RSI: ffffffffc04aa3c0 RDI: ffffffffc04361d0
[  323.898930] RBP: ffffffffc04361c8 R08: 0000000000000000 R09: 0000000000000001
[  323.898930] R10: ffff8881015972b0 R11: fffffbfff26132c4 R12: dffffc0000000000
[  323.898930] R13: 0000000000000000 R14: 1ffff110202b2e44 R15: ffffffffc04aa3c0
[  323.898930] FS:  00007f813ed41540(0000) GS:ffff88811ae00000(0000) knlGS:0000000000000000
[  323.898930] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  323.898930] CR2: 0000559bf2c9f120 CR3: 000000010bc80000 CR4: 00000000001006f0
[  323.898930] Call Trace:
[  323.898930]  ? atomic_notifier_chain_register+0x2d0/0x2d0
[  323.898930]  ? down_read+0x150/0x150
[  323.898930]  ? sched_clock_cpu+0x126/0x170
[  323.898930]  ? nf_tables_core_module_init+0xe4/0xe4 [nf_tables]
[  323.898930]  ? nf_tables_core_module_init+0xe4/0xe4 [nf_tables]
[  323.898930]  register_netdevice_notifier+0xbb/0x790
[  323.898930]  ? __dev_close_many+0x2d0/0x2d0
[  323.898930]  ? __mutex_unlock_slowpath+0x17f/0x740
[  323.898930]  ? wait_for_completion+0x710/0x710
[  323.898930]  ? nf_tables_core_module_init+0xe4/0xe4 [nf_tables]
[  323.898930]  ? up_write+0x6c/0x210
[  323.898930]  ? nf_tables_core_module_init+0xe4/0xe4 [nf_tables]
[  324.127073]  ? nf_tables_core_module_init+0xe4/0xe4 [nf_tables]
[  324.127073]  nft_chain_filter_init+0x1e/0xe8a [nf_tables]
[  324.127073]  nf_tables_module_init+0x37/0x92 [nf_tables]
[ ... ]

Fixes: 8dd33cc93e ("netfilter: nf_nat: generalize IPv4 masquerading support for nf_tables")
Fixes: be6b635cd6 ("netfilter: nf_nat: generalize IPv6 masquerading support for nf_tables")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2018-11-27 00:36:46 +01:00
..
arp_tables.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next 2018-03-30 11:41:18 -04:00
arpt_mangle.c
arptable_filter.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
ip_tables.c netfilter: x_tables: set module owner for icmp(6) matches 2018-07-05 11:45:11 +02:00
ipt_ah.c netfilter: ipt_ah: return boolean instead of integer 2018-03-05 23:15:43 +01:00
ipt_CLUSTERIP.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
ipt_ECN.c netfilter: x_tables: use pr ratelimiting in all remaining spots 2018-02-14 21:05:38 +01:00
ipt_MASQUERADE.c netfilter: add missing error handling code for register functions 2018-11-27 00:35:19 +01:00
ipt_REJECT.c netfilter: x_tables: use pr ratelimiting in all remaining spots 2018-02-14 21:05:38 +01:00
ipt_rpfilter.c netfilter: rpfilter: Convert rpfilter_lookup_reverse to new dev helper 2018-09-20 20:01:52 -07:00
ipt_SYNPROXY.c netfilter: ctnetlink: synproxy support 2018-03-20 14:39:31 +01:00
iptable_filter.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
iptable_mangle.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
iptable_nat.c netfilter: nf_nat: add nat type hooks to nat core 2018-05-23 09:14:06 +02:00
iptable_raw.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
iptable_security.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
Kconfig netfilter: kconfig: nat related expression depend on nftables core 2018-08-31 19:07:10 +02:00
Makefile netfilter: conntrack: remove l3proto abstraction 2018-07-17 15:27:49 +02:00
nf_defrag_ipv4.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
nf_dup_ipv4.c netfilter: kill the fake untracked conntrack objects 2017-04-15 11:47:57 +02:00
nf_flow_table_ipv4.c netfilter: nf_flow_table: move init code to nf_flow_table_core.c 2018-04-24 10:28:45 +02:00
nf_log_arp.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
nf_log_ipv4.c netfilter: check if the socket netns is correct. 2018-06-28 22:21:32 +09:00
nf_nat_h323.c netfilter: add NAT support for shifted portmap ranges 2018-04-24 10:29:12 +02:00
nf_nat_l3proto_ipv4.c netfilter: nf_nat_ipv4: remove obsolete EXPORT_SYMBOL 2018-09-17 16:11:13 +02:00
nf_nat_masquerade_ipv4.c netfilter: nat: fix double register in masquerade modules 2018-11-27 00:36:46 +01:00
nf_nat_pptp.c netfilter: add NAT support for shifted portmap ranges 2018-04-24 10:29:12 +02:00
nf_nat_proto_gre.c netfilter: add NAT support for shifted portmap ranges 2018-04-24 10:29:12 +02:00
nf_nat_proto_icmp.c netfilter: add NAT support for shifted portmap ranges 2018-04-24 10:29:12 +02:00
nf_nat_snmp_basic_main.c netfilter: nf_nat_snmp_basic: add missing helper alias name 2018-10-16 10:01:50 +02:00
nf_nat_snmp_basic.asn1 netfilter: nf_nat_snmp_basic: use asn1 decoder library 2018-01-19 13:59:07 +01:00
nf_reject_ipv4.c netfilter: nf_reject_ipv4: Fix use-after-free in send_reset 2017-11-01 12:15:29 +01:00
nf_socket_ipv4.c netfilter: nf_socket: Fix out of bounds access in nf_sk_lookup_slow_v{4,6} 2018-03-24 21:17:14 +01:00
nf_tproxy_ipv4.c netfilter: nf_tproxy: fix possible non-linear access to transport header 2018-07-06 14:32:44 +02:00
nft_chain_nat_ipv4.c netfilter: nf_nat: add nat type hooks to nat core 2018-05-23 09:14:06 +02:00
nft_chain_route_ipv4.c netfilter: nf_tables: nft_register_chain_type() returns void 2018-03-30 11:29:18 +02:00
nft_dup_ipv4.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2016-11-15 10:54:36 -05:00
nft_fib_ipv4.c netfilter: nft_fib: Convert nft_fib4_eval to new dev helper 2018-09-20 20:01:53 -07:00
nft_masq_ipv4.c netfilter: add missing error handling code for register functions 2018-11-27 00:35:19 +01:00
nft_redir_ipv4.c netfilter: nf_tables: fix mismatch in big-endian system 2017-03-13 13:30:28 +01:00
nft_reject_ipv4.c netfilter: nf_tables: use hook state from xt_action_param structure 2016-11-03 11:52:34 +01:00