• Nikolay Aleksandrov's avatar
    ipmr, ip6mr: fix scheduling while atomic and a deadlock with ipmr_get_route · 2cf75070
    Nikolay Aleksandrov authored
    Since the commit below the ipmr/ip6mr rtnl_unicast() code uses the portid
    instead of the previous dst_pid which was copied from in_skb's portid.
    Since the skb is new the portid is 0 at that point so the packets are sent
    to the kernel and we get scheduling while atomic or a deadlock (depending
    on where it happens) by trying to acquire rtnl two times.
    Also since this is RTM_GETROUTE, it can be triggered by a normal user.
    
    Here's the sleeping while atomic trace:
    [ 7858.212557] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:620
    [ 7858.212748] in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper/0
    [ 7858.212881] 2 locks held by swapper/0/0:
    [ 7858.213013]  #0:  (((&mrt->ipmr_expire_timer))){+.-...}, at: [<ffffffff810fbbf5>] call_timer_fn+0x5/0x350
    [ 7858.213422]  #1:  (mfc_unres_lock){+.....}, at: [<ffffffff8161e005>] ipmr_expire_process+0x25/0x130
    [ 7858.213807] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.8.0-rc7+ #179
    [ 7858.213934] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
    [ 7858.214108]  0000000000000000 ffff88005b403c50 ffffffff813a7804 0000000000000000
    [ 7858.214412]  ffffffff81a1338e ffff88005b403c78 ffffffff810a4a72 ffffffff81a1338e
    [ 7858.214716]  000000000000026c 0000000000000000 ffff88005b403ca8 ffffffff810a4b9f
    [ 7858.215251] Call Trace:
    [ 7858.215412]  <IRQ>  [<ffffffff813a7804>] dump_stack+0x85/0xc1
    [ 7858.215662]  [<ffffffff810a4a72>] ___might_sleep+0x192/0x250
    [ 7858.215868]  [<ffffffff810a4b9f>] __might_sleep+0x6f/0x100
    [ 7858.216072]  [<ffffffff8165bea3>] mutex_lock_nested+0x33/0x4d0
    [ 7858.216279]  [<ffffffff815a7a5f>] ? netlink_lookup+0x25f/0x460
    [ 7858.216487]  [<ffffffff8157474b>] rtnetlink_rcv+0x1b/0x40
    [ 7858.216687]  [<ffffffff815a9a0c>] netlink_unicast+0x19c/0x260
    [ 7858.216900]  [<ffffffff81573c70>] rtnl_unicast+0x20/0x30
    [ 7858.217128]  [<ffffffff8161cd39>] ipmr_destroy_unres+0xa9/0xf0
    [ 7858.217351]  [<ffffffff8161e06f>] ipmr_expire_process+0x8f/0x130
    [ 7858.217581]  [<ffffffff8161dfe0>] ? ipmr_net_init+0x180/0x180
    [ 7858.217785]  [<ffffffff8161dfe0>] ? ipmr_net_init+0x180/0x180
    [ 7858.217990]  [<ffffffff810fbc95>] call_timer_fn+0xa5/0x350
    [ 7858.218192]  [<ffffffff810fbbf5>] ? call_timer_fn+0x5/0x350
    [ 7858.218415]  [<ffffffff8161dfe0>] ? ipmr_net_init+0x180/0x180
    [ 7858.218656]  [<ffffffff810fde10>] run_timer_softirq+0x260/0x640
    [ 7858.218865]  [<ffffffff8166379b>] ? __do_softirq+0xbb/0x54f
    [ 7858.219068]  [<ffffffff816637c8>] __do_softirq+0xe8/0x54f
    [ 7858.219269]  [<ffffffff8107a948>] irq_exit+0xb8/0xc0
    [ 7858.219463]  [<ffffffff81663452>] smp_apic_timer_interrupt+0x42/0x50
    [ 7858.219678]  [<ffffffff816625bc>] apic_timer_interrupt+0x8c/0xa0
    [ 7858.219897]  <EOI>  [<ffffffff81055f16>] ? native_safe_halt+0x6/0x10
    [ 7858.220165]  [<ffffffff810d64dd>] ? trace_hardirqs_on+0xd/0x10
    [ 7858.220373]  [<ffffffff810298e3>] default_idle+0x23/0x190
    [ 7858.220574]  [<ffffffff8102a20f>] arch_cpu_idle+0xf/0x20
    [ 7858.220790]  [<ffffffff810c9f8c>] default_idle_call+0x4c/0x60
    [ 7858.221016]  [<ffffffff810ca33b>] cpu_startup_entry+0x39b/0x4d0
    [ 7858.221257]  [<ffffffff8164f995>] rest_init+0x135/0x140
    [ 7858.221469]  [<ffffffff81f83014>] start_kernel+0x50e/0x51b
    [ 7858.221670]  [<ffffffff81f82120>] ? early_idt_handler_array+0x120/0x120
    [ 7858.221894]  [<ffffffff81f8243f>] x86_64_start_reservations+0x2a/0x2c
    [ 7858.222113]  [<ffffffff81f8257c>] x86_64_start_kernel+0x13b/0x14a
    
    Fixes: 2942e900 ("[RTNETLINK]: Use rtnl_unicast() for rtnetlink unicasts")
    Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    2cf75070
Name
Last commit
Last update
..
ila Loading commit data...
netfilter Loading commit data...
Kconfig Loading commit data...
Makefile Loading commit data...
addrconf.c Loading commit data...
addrconf_core.c Loading commit data...
addrlabel.c Loading commit data...
af_inet6.c Loading commit data...
ah6.c Loading commit data...
anycast.c Loading commit data...
calipso.c Loading commit data...
datagram.c Loading commit data...
esp6.c Loading commit data...
exthdrs.c Loading commit data...
exthdrs_core.c Loading commit data...
exthdrs_offload.c Loading commit data...
fib6_rules.c Loading commit data...
fou6.c Loading commit data...
icmp.c Loading commit data...
inet6_connection_sock.c Loading commit data...
inet6_hashtables.c Loading commit data...
ip6_checksum.c Loading commit data...
ip6_fib.c Loading commit data...
ip6_flowlabel.c Loading commit data...
ip6_gre.c Loading commit data...
ip6_icmp.c Loading commit data...
ip6_input.c Loading commit data...
ip6_offload.c Loading commit data...
ip6_offload.h Loading commit data...
ip6_output.c Loading commit data...
ip6_tunnel.c Loading commit data...
ip6_udp_tunnel.c Loading commit data...
ip6_vti.c Loading commit data...
ip6mr.c Loading commit data...
ipcomp6.c Loading commit data...
ipv6_sockglue.c Loading commit data...
mcast.c Loading commit data...
mcast_snoop.c Loading commit data...
mip6.c Loading commit data...
ndisc.c Loading commit data...
netfilter.c Loading commit data...
output_core.c Loading commit data...
ping.c Loading commit data...
proc.c Loading commit data...
protocol.c Loading commit data...
raw.c Loading commit data...
reassembly.c Loading commit data...
route.c Loading commit data...
sit.c Loading commit data...
syncookies.c Loading commit data...
sysctl_net_ipv6.c Loading commit data...
tcp_ipv6.c Loading commit data...
tcpv6_offload.c Loading commit data...
tunnel6.c Loading commit data...
udp.c Loading commit data...
udp_impl.h Loading commit data...
udp_offload.c Loading commit data...
udplite.c Loading commit data...
xfrm6_input.c Loading commit data...
xfrm6_mode_beet.c Loading commit data...
xfrm6_mode_ro.c Loading commit data...
xfrm6_mode_transport.c Loading commit data...
xfrm6_mode_tunnel.c Loading commit data...
xfrm6_output.c Loading commit data...
xfrm6_policy.c Loading commit data...
xfrm6_protocol.c Loading commit data...
xfrm6_state.c Loading commit data...
xfrm6_tunnel.c Loading commit data...