> -----Original Message-----
> From: Ying Xue [mailto:[email protected]]
> Sent: Monday, December 04, 2017 09:11
> To: [email protected]; Jon Maloy <[email protected]>
> Cc: [email protected]
> Subject: [net-next PATCH 1/2] tipc: prevent swork item from queuing
> workqueue after connection is closed
> 
> For one same connection, tipc_close_conn() and tipc_conn_sendmsg() might
> be conducted on different cores in parallel. Once connection is flagged as
> close, we should not queue swork item to workqueue.
> 
> But as sk->sk_callback_lock is not taken in tipc_conn_sendmsg(), a swork
> item might be queued into s->send_wq workqueue even if the connection
> has been shut down in tipc_close_conn() on another core.
> 
> To prevent the race condition from happening, we first hold
> sk->sk_callback and then ensure connection flags and sk->sk_user_data
> are both valid before swork item is queued into s->send_wq workqueue.
> 
> Signed-off-by: Ying Xue <[email protected]>
> ---
>  net/tipc/server.c | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/net/tipc/server.c b/net/tipc/server.c index acaef80..571e137
> 100644
> --- a/net/tipc/server.c
> +++ b/net/tipc/server.c
> @@ -449,16 +449,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int
> conid,  {
>       struct outqueue_entry *e;
>       struct tipc_conn *con;
> +     struct sock *sk;
> 
>       con = tipc_conn_lookup(s, conid);
>       if (!con)
>               return -EINVAL;
> 
> -     if (!test_bit(CF_CONNECTED, &con->flags)) {
> -             conn_put(con);
> -             return 0;
> -     }
> -
>       e = tipc_alloc_entry(data, len);
>       if (!e) {
>               conn_put(con);
> @@ -472,8 +468,17 @@ int tipc_conn_sendmsg(struct tipc_server *s, int
> conid,


You cannot be sure that con is valid here. You need to add the 
!kref_get_unless_zero(&con->kref)) in the lookup function, as I had to do.
This was caused by observed crashes.


>       list_add_tail(&e->list, &con->outqueue);
>       spin_unlock_bh(&con->outqueue_lock);
> 
> -     if (!queue_work(s->send_wq, &con->swork))
> +     sk = con->sock->sk;
> +

You don't know if the socket still exists here. We may be in the middle of a 
tipc_conn_close().
Furthermore, in the case of a kernel subscriber, there *is* no socket. 
But I am not sure this patch is needed at all ??

///jon


> +     read_lock_bh(&sk->sk_callback_lock);
> +     if (sk->sk_user_data && test_bit(CF_CONNECTED, &con->flags)) {
> +             if (!queue_work(s->send_wq, &con->swork))
> +                     conn_put(con);
> +     } else {
>               conn_put(con);
> +     }
> +     read_unlock_bh(&sk->sk_callback_lock);
> +
>       return 0;
>  }
> 
> --
> 2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
tipc-discussion mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to