• Tung Nguyen's avatar
    tipc: fix race condition causing hung sendto · bfd07f3d
    Tung Nguyen authored
    When sending multicast messages via blocking socket,
    if sending link is congested (tsk->cong_link_cnt is set to 1),
    the sending thread will be put into sleeping state. However,
    tipc_sk_filter_rcv() is called under socket spin lock but
    tipc_wait_for_cond() is not. So, there is no guarantee that
    the setting of tsk->cong_link_cnt to 0 in tipc_sk_proto_rcv() in
    CPU-1 will be perceived by CPU-0. If that is the case, the sending
    thread in CPU-0 after being waken up, will continue to see
    tsk->cong_link_cnt as 1 and put the sending thread into sleeping
    state again. The sending thread will sleep forever.
    
    CPU-0                                | CPU-1
    tipc_wait_for_cond()                 |
    {                                    |
     // condition_ = !tsk->cong_link_cnt |
     while ((rc_ = !(condition_))) {     |
      ...                                |
      release_sock(sk_);                 |
      wait_woken();                      |
                                         | if (!sock_owned_by_user(sk))
                                         |  tipc_sk_filter_rcv()
                                         |  {
                                         |   ...
                                         |   tipc_sk_proto_rcv()
                                         |   {
                                         |    ...
                                         |    tsk->cong_link_cnt--;
                                         |    ...
                                         |    sk->sk_write_space(sk);
                                         |    ...
                                         |   }
                                         |   ...
                                         |  }
      sched_annotate_sleep();            |
      lock_sock(sk_);                    |
      remove_wait_queue();               |
     }                                   |
    }                                    |
    
    This commit fixes it by adding memory barrier to tipc_sk_proto_rcv()
    and tipc_wait_for_cond().
    Acked-by: default avatarJon Maloy <jon.maloy@ericsson.com>
    Signed-off-by: default avatarTung Nguyen <tung.q.nguyen@dektech.com.au>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    bfd07f3d
Name
Last commit
Last update
..
Kconfig Loading commit data...
Makefile Loading commit data...
addr.c Loading commit data...
addr.h Loading commit data...
bcast.c Loading commit data...
bcast.h Loading commit data...
bearer.c Loading commit data...
bearer.h Loading commit data...
core.c Loading commit data...
core.h Loading commit data...
diag.c Loading commit data...
discover.c Loading commit data...
discover.h Loading commit data...
eth_media.c Loading commit data...
group.c Loading commit data...
group.h Loading commit data...
ib_media.c Loading commit data...
link.c Loading commit data...
link.h Loading commit data...
monitor.c Loading commit data...
monitor.h Loading commit data...
msg.c Loading commit data...
msg.h Loading commit data...
name_distr.c Loading commit data...
name_distr.h Loading commit data...
name_table.c Loading commit data...
name_table.h Loading commit data...
net.c Loading commit data...
net.h Loading commit data...
netlink.c Loading commit data...
netlink.h Loading commit data...
netlink_compat.c Loading commit data...
node.c Loading commit data...
node.h Loading commit data...
socket.c Loading commit data...
socket.h Loading commit data...
subscr.c Loading commit data...
subscr.h Loading commit data...
sysctl.c Loading commit data...
topsrv.c Loading commit data...
topsrv.h Loading commit data...
trace.c Loading commit data...
trace.h Loading commit data...
udp_media.c Loading commit data...
udp_media.h Loading commit data...