• Xin Long's avatar
    sctp: avoid running the sctp state machine recursively · a5d00345
    Xin Long authored
    [ Upstream commit fbd019737d71e405f86549fd738f81e2ff3dd073 ]
    
    Ying triggered a call trace when doing an asconf testing:
    
      BUG: scheduling while atomic: swapper/12/0/0x10000100
      Call Trace:
       <IRQ>  [<ffffffffa4375904>] dump_stack+0x19/0x1b
       [<ffffffffa436fcaf>] __schedule_bug+0x64/0x72
       [<ffffffffa437b93a>] __schedule+0x9ba/0xa00
       [<ffffffffa3cd5326>] __cond_resched+0x26/0x30
       [<ffffffffa437bc4a>] _cond_resched+0x3a/0x50
       [<ffffffffa3e22be8>] kmem_cache_alloc_node+0x38/0x200
       [<ffffffffa423512d>] __alloc_skb+0x5d/0x2d0
       [<ffffffffc0995320>] sctp_packet_transmit+0x610/0xa20 [sctp]
       [<ffffffffc098510e>] sctp_outq_flush+0x2ce/0xc00 [sctp]
       [<ffffffffc098646c>] sctp_outq_uncork+0x1c/0x20 [sctp]
       [<ffffffffc0977338>] sctp_cmd_interpreter.isra.22+0xc8/0x1460 [sctp]
       [<ffffffffc0976ad1>] sctp_do_sm+0xe1/0x350 [sctp]
       [<ffffffffc099443d>] sctp_primitive_ASCONF+0x3d/0x50 [sctp]
       [<ffffffffc0977384>] sctp_cmd_interpreter.isra.22+0x114/0x1460 [sctp]
       [<ffffffffc0976ad1>] sctp_do_sm+0xe1/0x350 [sctp]
       [<ffffffffc097b3a4>] sctp_assoc_bh_rcv+0xf4/0x1b0 [sctp]
       [<ffffffffc09840f1>] sctp_inq_push+0x51/0x70 [sctp]
       [<ffffffffc099732b>] sctp_rcv+0xa8b/0xbd0 [sctp]
    
    As it shows, the first sctp_do_sm() running under atomic context (NET_RX
    softirq) invoked sctp_primitive_ASCONF() that uses GFP_KERNEL flag later,
    and this flag is supposed to be used in non-atomic context only. Besides,
    sctp_do_sm() was called recursively, which is not expected.
    
    Vlad tried to fix this recursive call in Commit c0786693 ("sctp: Fix
    oops when sending queued ASCONF chunks") by introducing a new command
    SCTP_CMD_SEND_NEXT_ASCONF. But it didn't work as this command is still
    used in the first sctp_do_sm() call, and sctp_primitive_ASCONF() will
    be called in this command again.
    
    To avoid calling sctp_do_sm() recursively, we send the next queued ASCONF
    not by sctp_primitive_ASCONF(), but by sctp_sf_do_prm_asconf() in the 1st
    sctp_do_sm() directly.
    Reported-by: 's avatarYing Xu <yinxu@redhat.com>
    Signed-off-by: 's avatarXin Long <lucien.xin@gmail.com>
    Acked-by: 's avatarNeil Horman <nhorman@tuxdriver.com>
    Acked-by: 's avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
    Signed-off-by: 's avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    a5d00345
Name
Last commit
Last update
..
Kconfig Loading commit data...
Makefile Loading commit data...
associola.c Loading commit data...
auth.c Loading commit data...
bind_addr.c Loading commit data...
chunk.c Loading commit data...
debug.c Loading commit data...
endpointola.c Loading commit data...
input.c Loading commit data...
inqueue.c Loading commit data...
ipv6.c Loading commit data...
objcnt.c Loading commit data...
offload.c Loading commit data...
output.c Loading commit data...
outqueue.c Loading commit data...
primitive.c Loading commit data...
probe.c Loading commit data...
proc.c Loading commit data...
protocol.c Loading commit data...
sctp_diag.c Loading commit data...
sm_make_chunk.c Loading commit data...
sm_sideeffect.c Loading commit data...
sm_statefuns.c Loading commit data...
sm_statetable.c Loading commit data...
socket.c Loading commit data...
stream.c Loading commit data...
sysctl.c Loading commit data...
transport.c Loading commit data...
tsnmap.c Loading commit data...
ulpevent.c Loading commit data...
ulpqueue.c Loading commit data...