linux/net/ipv6
Ido Schimmel 98afbb3781 ip6mr: Do not call __IP6_INC_STATS() from preemptible context
commit 87c11f1ddb upstream.

Similar to commit 44f49dd8b5 ("ipmr: fix possible race resulting from
improper usage of IP_INC_STATS_BH() in preemptible context."), we cannot
assume preemption is disabled when incrementing the counter and
accessing a per-CPU variable.

Preemption can be enabled when we add a route in process context that
corresponds to packets stored in the unresolved queue, which are then
forwarded using this route [1].

Fix this by using IP6_INC_STATS() which takes care of disabling
preemption on architectures where it is needed.

[1]
[  157.451447] BUG: using __this_cpu_add() in preemptible [00000000] code: smcrouted/2314
[  157.460409] caller is ip6mr_forward2+0x73e/0x10e0
[  157.460434] CPU: 3 PID: 2314 Comm: smcrouted Not tainted 5.0.0-rc7-custom-03635-g22f2712113f1 #1336
[  157.460449] Hardware name: Mellanox Technologies Ltd. MSN2100-CB2FO/SA001017, BIOS 5.6.5 06/07/2016
[  157.460461] Call Trace:
[  157.460486]  dump_stack+0xf9/0x1be
[  157.460553]  check_preemption_disabled+0x1d6/0x200
[  157.460576]  ip6mr_forward2+0x73e/0x10e0
[  157.460705]  ip6_mr_forward+0x9a0/0x1510
[  157.460771]  ip6mr_mfc_add+0x16b3/0x1e00
[  157.461155]  ip6_mroute_setsockopt+0x3cb/0x13c0
[  157.461384]  do_ipv6_setsockopt.isra.8+0x348/0x4060
[  157.462013]  ipv6_setsockopt+0x90/0x110
[  157.462036]  rawv6_setsockopt+0x4a/0x120
[  157.462058]  __sys_setsockopt+0x16b/0x340
[  157.462198]  __x64_sys_setsockopt+0xbf/0x160
[  157.462220]  do_syscall_64+0x14d/0x610
[  157.462349]  entry_SYSCALL_64_after_hwframe+0x49/0xbe

Fixes: 0912ea38de ("[IPV6] MROUTE: Add stats in multicast routing module method ip6_mr_forward().")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reported-by: Amit Cohen <amitc@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2019-07-09 22:04:11 +01:00
..
netfilter netfilter: ipv6: nf_defrag: reduce struct net memory waste 2018-11-20 18:05:17 +00:00
addrconf.c net: fix IPv6 prefix route residue 2019-05-02 21:41:51 +01:00
addrconf_core.c ipv6: remove rt6i_genid 2014-10-15 12:05:29 +02:00
addrlabel.c ipv6/addrlabel: fix ip6addrlbl_get() 2016-01-25 10:44:00 +00:00
af_inet6.c ipv6: fix cleanup ordering for pingv6 registration 2018-12-16 22:08:57 +00:00
ah6.c ah6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
anycast.c ipv6: restore the behavior of ipv6_sock_ac_drop() 2014-10-15 12:05:28 +02:00
datagram.c ipv6/udp: use sticky pktinfo egress ifindex on connect() 2016-03-09 10:38:49 +00:00
esp6.c xfrm: Return error on unknown encap_type in init_state 2018-03-03 15:52:15 +00:00
exthdrs.c ipv6: Need to export ipv6_push_frag_opts for tunneling now. 2017-08-26 02:14:43 +01:00
exthdrs_core.c ipv6: re-enable fragment header matching in ipv6_find_hdr 2016-03-24 10:01:14 +00:00
exthdrs_offload.c ipv6: fix exthdrs offload registration in out_rt path 2015-09-30 13:20:50 +01:00
fib6_rules.c ipv6: Do not leak throw route references 2017-09-15 18:30:13 +01:00
icmp.c ipv6: fix endianness error in icmpv6_err 2016-08-22 22:38:15 +01:00
inet6_connection_sock.c ipv6: add complete rcu protection around np->opt 2015-12-18 16:06:24 +00:00
inet6_hashtables.c inet: convert inet_ehash_secret and ipv6_hash_secret to net_get_random_once 2013-10-19 19:45:35 -04:00
ip6_checksum.c udplite: fix partial checksum initialization 2018-06-16 22:22:18 +01:00
ip6_fib.c ipv6: Fix another sparse warning on rt6i_node 2019-02-11 17:53:13 +00:00
ip6_flowlabel.c ipv6: fix a lockdep splat 2016-02-25 10:51:01 +00:00
ip6_gre.c ip6_gre: better validate user provided tunnel names 2018-10-21 08:45:15 +01:00
ip6_icmp.c ipv6: Kill ipv6 dependency of icmpv6_send(). 2013-04-29 13:54:36 -04:00
ip6_input.c ipv6: Make MLD packets to only be processed locally 2015-08-10 17:10:15 +01:00
ip6_offload.c ipv6: Fix leak in ipv6_gso_segment(). 2017-09-15 18:29:56 +01:00
ip6_offload.h ipv6: Pull IPv6 GSO registration out of the module 2012-11-15 17:39:24 -05:00
ip6_output.c inet: update the IP ID generation algorithm to higher standards. 2019-05-11 15:22:47 +01:00
ip6_tunnel.c ip6_tunnel: be careful when accessing the inner header 2018-12-16 22:09:21 +00:00
ip6_vti.c ipv6: tunnels: fix two use-after-free 2019-02-11 17:54:31 +00:00
ip6mr.c ip6mr: Do not call __IP6_INC_STATS() from preemptible context 2019-07-09 22:04:11 +01:00
ipcomp6.c ipcomp6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
ipv6_sockglue.c netfilter: drop outermost socket lock in getsockopt() 2018-06-16 22:22:14 +01:00
Kconfig ip6_vti: Fix build when NET_IP_TUNNEL is not set. 2014-02-20 14:29:49 +01:00
Makefile xfrm6: Add IPsec protocol multiplexer 2014-03-14 07:28:07 +01:00
mcast.c multicast: do not restore deleted record source filter mode to new one 2018-11-20 18:05:46 +00:00
mip6.c ipv4/ipv6: Fix FSF address in file headers 2013-12-06 12:37:56 -05:00
ndisc.c ipv6/ndisc: Preserve IPv6 control buffer if protocol error handlers are called 2019-02-11 17:53:42 +00:00
netfilter.c netfilter: Fix potential use after free in ip6_route_me_harder() 2014-05-09 02:36:39 +02:00
output_core.c ipv6: accept 64k - 1 packet length in ip6_find_1stfragopt() 2017-11-11 13:33:24 +00:00
ping.c net: ping: do not abuse udp_poll() 2017-09-15 18:29:56 +01:00
proc.c snmp: fix some left over of snmp stats 2014-05-14 15:33:47 -04:00
protocol.c net: remove outdated comment for ipv4 and ipv6 protocol handler 2013-11-28 18:47:51 -05:00
raw.c ipv6: take rcu lock in rawv6_send_hdrinc() 2018-12-16 22:09:36 +00:00
reassembly.c ipv6: distinguish frag queues by device for multicast and link-local packets 2015-12-18 16:06:23 +00:00
route.c ipv6: add RTA_TABLE and RTA_PREFSRC to rtm_ipv6_policy 2018-10-21 08:45:40 +01:00
sit.c sit: check if IPv6 enabled before calling ip6_err_gen_icmpv6_unreach() 2019-05-02 21:41:49 +01:00
syncookies.c ipv6: add complete rcu protection around np->opt 2015-12-18 16:06:24 +00:00
sysctl_net_ipv6.c net: add a sysctl to reflect the fwmark on replies 2014-05-13 18:35:08 -04:00
tcp_ipv6.c tcp md5sig: Use skb's saddr when replying to an incoming segment 2018-03-03 15:51:53 +00:00
tcpv6_offload.c net-gre-gro: Fix a bug that breaks the forwarding path 2014-07-16 14:45:26 -07:00
tunnel6.c ipv6: fix tunnel error handling 2015-12-13 17:49:43 +00:00
udp.c udp: prevent skbs lingering in tunnel socket queues 2017-03-16 02:27:17 +00:00
udp_impl.h net: ipv4/ipv6: Remove extern from function prototypes 2013-10-19 19:12:11 -04:00
udp_offload.c net: avoid skb_warn_bad_offload false positives on UFO 2017-11-11 13:33:18 +00:00
udplite.c net: Eliminate no_check from protosw 2014-05-23 16:28:53 -04:00
xfrm6_input.c xfrm: Reinject transport-mode packets through tasklet 2018-03-03 15:52:02 +00:00
xfrm6_mode_beet.c ipsec: be careful of non existing mac headers 2012-02-23 16:50:45 -05:00
xfrm6_mode_ro.c ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() 2017-09-15 18:29:54 +01:00
xfrm6_mode_transport.c ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() 2017-09-15 18:29:54 +01:00
xfrm6_mode_tunnel.c ipv6: update skb->csum when CE mark is propagated 2016-01-28 11:06:06 +00:00
xfrm6_output.c xfrm6: call kfree_skb when skb is toobig 2018-12-16 22:09:01 +00:00
xfrm6_policy.c xfrm6: avoid potential infinite loop in _decode_session6() 2018-10-21 08:46:04 +01:00
xfrm6_protocol.c xfrm6: Properly handle unsupported protocols 2014-05-06 07:08:38 +02:00
xfrm6_state.c xfrm: make local error reporting more robust 2013-08-14 13:07:12 +02:00
xfrm6_tunnel.c ipv4/ipv6: Fix FSF address in file headers 2013-12-06 12:37:56 -05:00