1
0
Fork 0
alistair23-linux/net/ipv6/netfilter
Will Deacon b416c144f4 netfilter: x_tables: fix ordering of jumpstack allocation and table update
During kernel stability testing on an SMP ARMv7 system, Yalin Wang
reported the following panic from the netfilter code:

  1fe0: 0000001c 5e2d3b10 4007e779 4009e110 60000010 00000032 ff565656 ff545454
  [<c06c48dc>] (ipt_do_table+0x448/0x584) from [<c0655ef0>] (nf_iterate+0x48/0x7c)
  [<c0655ef0>] (nf_iterate+0x48/0x7c) from [<c0655f7c>] (nf_hook_slow+0x58/0x104)
  [<c0655f7c>] (nf_hook_slow+0x58/0x104) from [<c0683bbc>] (ip_local_deliver+0x88/0xa8)
  [<c0683bbc>] (ip_local_deliver+0x88/0xa8) from [<c0683718>] (ip_rcv_finish+0x418/0x43c)
  [<c0683718>] (ip_rcv_finish+0x418/0x43c) from [<c062b1c4>] (__netif_receive_skb+0x4cc/0x598)
  [<c062b1c4>] (__netif_receive_skb+0x4cc/0x598) from [<c062b314>] (process_backlog+0x84/0x158)
  [<c062b314>] (process_backlog+0x84/0x158) from [<c062de84>] (net_rx_action+0x70/0x1dc)
  [<c062de84>] (net_rx_action+0x70/0x1dc) from [<c0088230>] (__do_softirq+0x11c/0x27c)
  [<c0088230>] (__do_softirq+0x11c/0x27c) from [<c008857c>] (do_softirq+0x44/0x50)
  [<c008857c>] (do_softirq+0x44/0x50) from [<c0088614>] (local_bh_enable_ip+0x8c/0xd0)
  [<c0088614>] (local_bh_enable_ip+0x8c/0xd0) from [<c06b0330>] (inet_stream_connect+0x164/0x298)
  [<c06b0330>] (inet_stream_connect+0x164/0x298) from [<c061d68c>] (sys_connect+0x88/0xc8)
  [<c061d68c>] (sys_connect+0x88/0xc8) from [<c000e340>] (ret_fast_syscall+0x0/0x30)
  Code: 2a000021 e59d2028 e59de01c e59f011c (e7824103)
  ---[ end trace da227214a82491bd ]---
  Kernel panic - not syncing: Fatal exception in interrupt

This comes about because CPU1 is executing xt_replace_table in response
to a setsockopt syscall, resulting in:

	ret = xt_jumpstack_alloc(newinfo);
		--> newinfo->jumpstack = kzalloc(size, GFP_KERNEL);

	[...]

	table->private = newinfo;
	newinfo->initial_entries = private->initial_entries;

Meanwhile, CPU0 is handling the network receive path and ends up in
ipt_do_table, resulting in:

	private = table->private;

	[...]

	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];

On weakly ordered memory architectures, the writes to table->private
and newinfo->jumpstack from CPU1 can be observed out of order by CPU0.
Furthermore, on architectures which don't respect ordering of address
dependencies (i.e. Alpha), the reads from CPU0 can also be re-ordered.

This patch adds an smp_wmb() before the assignment to table->private
(which is essentially publishing newinfo) to ensure that all writes to
newinfo will be observed before plugging it into the table structure.
A dependent-read barrier is also added on the consumer sides, to ensure
the same ordering requirements are also respected there.

Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reported-by: Wang, Yalin <Yalin.Wang@sonymobile.com>
Tested-by: Wang, Yalin <Yalin.Wang@sonymobile.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-22 10:11:29 +02:00
..
Kconfig netfilter: add IPv6 SYNPROXY target 2013-08-28 00:28:13 +02:00
Makefile netfilter: add IPv6 SYNPROXY target 2013-08-28 00:28:13 +02:00
ip6_tables.c netfilter: x_tables: fix ordering of jumpstack allocation and table update 2013-10-22 10:11:29 +02:00
ip6t_MASQUERADE.c netfilter: nf_conntrack: don't send destroy events from iterator 2013-08-09 12:03:33 +02:00
ip6t_NPT.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2013-04-07 18:37:01 -04:00
ip6t_REJECT.c netfilter: ip[6]t_REJECT: tcp-reset using wrong MAC source if bridged 2013-08-28 00:13:12 +02:00
ip6t_SYNPROXY.c netfilter: synproxy: fix BUG_ON triggered by corrupt TCP packets 2013-09-30 12:44:38 +02:00
ip6t_ah.c netfilter: ip6_tables: add flags parameter to ipv6_find_hdr() 2012-05-09 12:53:47 +02:00
ip6t_eui64.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
ip6t_frag.c netfilter: ip6_tables: add flags parameter to ipv6_find_hdr() 2012-05-09 12:53:47 +02:00
ip6t_hbh.c netfilter: ip6_tables: add flags parameter to ipv6_find_hdr() 2012-05-09 12:53:47 +02:00
ip6t_ipv6header.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
ip6t_mh.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
ip6t_rpfilter.c netfilter: xt_rpfilter: skip locally generated broadcast/multicast, too 2013-04-19 00:11:59 +02:00
ip6t_rt.c netfilter: ip6_tables: add flags parameter to ipv6_find_hdr() 2012-05-09 12:53:47 +02:00
ip6table_filter.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
ip6table_mangle.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
ip6table_nat.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
ip6table_raw.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
ip6table_security.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
nf_conntrack_l3proto_ipv6.c netfilter: nf_conntrack: make sequence number adjustments usuable without NAT 2013-08-28 00:26:48 +02:00
nf_conntrack_proto_icmpv6.c netfilter: nf_log: prepare net namespace support for loggers 2013-04-05 20:12:54 +02:00
nf_conntrack_reasm.c netfilter: implement RFC3168 5.3 (ecn protection) for ipv6 fragmentation handling 2013-04-06 13:06:37 +02:00
nf_defrag_ipv6_hooks.c ipv6: use IS_ENABLED() 2012-11-01 12:41:35 -04:00
nf_nat_l3proto_ipv6.c netfilter: ipv6: using csum_ipv6_magic requires net/ip6_checksum.h 2012-09-05 17:46:06 -04:00
nf_nat_proto_icmpv6.c netfilter: nf_nat_proto_icmpv6:: fix wrong comparison in icmpv6_manip_pkt 2013-09-13 11:58:48 +02:00