linux/net/ipv6
Benjamin Block 793c3b4000 net: ipv6: fib: don't sleep inside atomic lock
The function fib6_commit_metrics() allocates a piece of memory in mode
GFP_KERNEL while holding an atomic lock from higher up in the stack, in
the function __ip6_ins_rt(). This produces the following BUG:

> BUG: sleeping function called from invalid context at mm/slub.c:1250
> in_atomic(): 1, irqs_disabled(): 0, pid: 2909, name: dhcpcd
> 2 locks held by dhcpcd/2909:
>  #0:  (rtnl_mutex){+.+.+.}, at: [<ffffffff81978e67>] rtnl_lock+0x17/0x20
>  #1:  (&tb->tb6_lock){++--+.}, at: [<ffffffff81a6951a>] ip6_route_add+0x65a/0x800
> CPU: 1 PID: 2909 Comm: dhcpcd Not tainted 3.17.0-rc1 #1
> Hardware name: ASUS All Series/Q87T, BIOS 0216 10/16/2013
>  0000000000000008 ffff8800c8f13858 ffffffff81af135a 0000000000000000
>  ffff880212202430 ffff8800c8f13878 ffffffff810f8d3a ffff880212202c98
>  0000000000000010 ffff8800c8f138c8 ffffffff8121ad0e 0000000000000001
> Call Trace:
>  [<ffffffff81af135a>] dump_stack+0x4e/0x68
>  [<ffffffff810f8d3a>] __might_sleep+0x10a/0x120
>  [<ffffffff8121ad0e>] kmem_cache_alloc_trace+0x4e/0x190
>  [<ffffffff81a6bcd6>] ? fib6_commit_metrics+0x66/0x110
>  [<ffffffff81a6bcd6>] fib6_commit_metrics+0x66/0x110
>  [<ffffffff81a6cbf3>] fib6_add+0x883/0xa80
>  [<ffffffff81a6951a>] ? ip6_route_add+0x65a/0x800
>  [<ffffffff81a69535>] ip6_route_add+0x675/0x800
>  [<ffffffff81a68f2a>] ? ip6_route_add+0x6a/0x800
>  [<ffffffff81a6990c>] inet6_rtm_newroute+0x5c/0x80
>  [<ffffffff8197cf01>] rtnetlink_rcv_msg+0x211/0x260
>  [<ffffffff81978e67>] ? rtnl_lock+0x17/0x20
>  [<ffffffff81119708>] ? lock_release_holdtime+0x28/0x180
>  [<ffffffff81978e67>] ? rtnl_lock+0x17/0x20
>  [<ffffffff8197ccf0>] ? __rtnl_unlock+0x20/0x20
>  [<ffffffff819a989e>] netlink_rcv_skb+0x6e/0xd0
>  [<ffffffff81978ee5>] rtnetlink_rcv+0x25/0x40
>  [<ffffffff819a8e59>] netlink_unicast+0xd9/0x180
>  [<ffffffff819a9600>] netlink_sendmsg+0x700/0x770
>  [<ffffffff81103735>] ? local_clock+0x25/0x30
>  [<ffffffff8194e83c>] sock_sendmsg+0x6c/0x90
>  [<ffffffff811f98e3>] ? might_fault+0xa3/0xb0
>  [<ffffffff8195ca6d>] ? verify_iovec+0x7d/0xf0
>  [<ffffffff8194ec3e>] ___sys_sendmsg+0x37e/0x3b0
>  [<ffffffff8111ef15>] ? trace_hardirqs_on_caller+0x185/0x220
>  [<ffffffff81af979e>] ? mutex_unlock+0xe/0x10
>  [<ffffffff819a55ec>] ? netlink_insert+0xbc/0xe0
>  [<ffffffff819a65e5>] ? netlink_autobind.isra.30+0x125/0x150
>  [<ffffffff819a6520>] ? netlink_autobind.isra.30+0x60/0x150
>  [<ffffffff819a84f9>] ? netlink_bind+0x159/0x230
>  [<ffffffff811f989a>] ? might_fault+0x5a/0xb0
>  [<ffffffff8194f25e>] ? SYSC_bind+0x7e/0xd0
>  [<ffffffff8194f8cd>] __sys_sendmsg+0x4d/0x80
>  [<ffffffff8194f912>] SyS_sendmsg+0x12/0x20
>  [<ffffffff81afc692>] system_call_fastpath+0x16/0x1b

Fixing this by replacing the mode GFP_KERNEL with GFP_ATOMIC.

Signed-off-by: Benjamin Block <bebl@mageta.org>
Acked-by: David Rientjes <rientjes@google.com>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-22 10:54:49 -07:00
..
netfilter inet: frags: use kmem_cache for inet_frag_queue 2014-08-02 15:31:31 -07:00
addrconf_core.c net: clean up snmp stats code 2014-05-07 16:06:05 -04:00
addrconf.c ipv6: fail early when creating netdev named all or default 2014-07-29 11:43:50 -07:00
addrlabel.c list: fix order of arguments for hlist_add_after(_rcu) 2014-08-06 18:01:24 -07:00
af_inet6.c ipv6: Implement automatic flow label generation on transmit 2014-07-07 21:14:21 -07:00
ah6.c ah6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
anycast.c
datagram.c net: Save TX flow hash in sock and set in skbuf on xmit 2014-07-07 21:14:21 -07:00
esp6.c esp6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
exthdrs_core.c ipv6: ipv6_find_hdr restore prev functionality 2014-02-27 18:27:26 -05:00
exthdrs_offload.c ipv6: Fix exthdrs offload registration. 2014-03-06 16:35:55 -05:00
exthdrs.c
fib6_rules.c
icmp.c net: fix the counter ICMP_MIB_INERRORS/ICMP6_MIB_INERRORS 2014-07-31 22:04:18 -07:00
inet6_connection_sock.c net: support marking accepting TCP sockets 2014-05-13 18:35:09 -04:00
inet6_hashtables.c
ip6_checksum.c udp: Generic functions to set checksum 2014-06-04 22:46:38 -07:00
ip6_fib.c net: ipv6: fib: don't sleep inside atomic lock 2014-08-22 10:54:49 -07:00
ip6_flowlabel.c net: ipv6: Introduce ip6_sk_dst_hoplimit. 2014-04-30 13:31:26 -04:00
ip6_gre.c net: set name_assign_type in alloc_netdev() 2014-07-15 16:12:48 -07:00
ip6_icmp.c
ip6_input.c
ip6_offload.c gre: Call gso_make_checksum 2014-06-04 22:46:38 -07:00
ip6_offload.h
ip6_output.c net-timestamp: add key to disambiguate concurrent datagrams 2014-08-05 16:35:54 -07:00
ip6_tunnel.c net: set name_assign_type in alloc_netdev() 2014-07-15 16:12:48 -07:00
ip6_vti.c Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next 2014-07-30 20:05:54 -07:00
ip6mr.c net: set name_assign_type in alloc_netdev() 2014-07-15 16:12:48 -07:00
ipcomp6.c ipcomp6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
ipv6_sockglue.c ipv6: remove unnecessary break after return 2014-07-15 16:27:01 -07: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 ipv6: Fix MLD Query message check 2014-06-27 00:21:50 -07:00
mip6.c
ndisc.c neigh: remove exceptional & on function name 2014-07-24 23:23:31 -07: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 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2014-06-11 16:02:55 -07:00
ping.c net: Eliminate no_check from protosw 2014-05-23 16:28:53 -04:00
proc.c inet: frag: don't account number of fragment queues 2014-07-27 22:34:36 -07:00
protocol.c
raw.c net: use inet6_iif instead of IP6CB()->iif 2014-07-31 22:37:06 -07:00
reassembly.c inet: frags: use kmem_cache for inet_frag_queue 2014-08-02 15:31:31 -07:00
route.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2014-05-24 00:32:30 -04:00
sit.c sit: Fix ipip6_tunnel_lookup device matching criteria 2014-08-14 14:38:54 -07:00
syncookies.c net: remove inet6_reqsk_alloc 2014-06-27 15:53:35 -07:00
sysctl_net_ipv6.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2014-08-05 18:46:26 -07:00
tcp_ipv6.c tcp: fix tcp_release_cb() to dispatch via address family for mtu_reduced() 2014-08-14 14:38:54 -07: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
udp_impl.h
udp_offload.c gre: Call gso_make_checksum 2014-06-04 22:46:38 -07:00
udp.c net: use inet6_iif instead of IP6CB()->iif 2014-07-31 22:37:06 -07:00
udplite.c net: Eliminate no_check from protosw 2014-05-23 16:28:53 -04:00
xfrm6_input.c
xfrm6_mode_beet.c
xfrm6_mode_ro.c
xfrm6_mode_transport.c
xfrm6_mode_tunnel.c xfrm6: Remove xfrm_tunnel_notifier 2014-03-14 07:28:08 +01:00
xfrm6_output.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2014-05-24 00:32:30 -04:00
xfrm6_policy.c xfrm6: Add IPsec protocol multiplexer 2014-03-14 07:28:07 +01:00
xfrm6_protocol.c xfrm6: Properly handle unsupported protocols 2014-05-06 07:08:38 +02:00
xfrm6_state.c
xfrm6_tunnel.c