lkml.org 
[lkml]   [2020]   [Feb]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 140/173] rxrpc: Fix service call disconnection
    Date
    From: David Howells <dhowells@redhat.com>

    [ Upstream commit b39a934ec72fa2b5a74123891f25273a38378b90 ]

    The recent patch that substituted a flag on an rxrpc_call for the
    connection pointer being NULL as an indication that a call was disconnected
    puts the set_bit in the wrong place for service calls. This is only a
    problem if a call is implicitly terminated by a new call coming in on the
    same connection channel instead of a terminating ACK packet.

    In such a case, rxrpc_input_implicit_end_call() calls
    __rxrpc_disconnect_call(), which is now (incorrectly) setting the
    disconnection bit, meaning that when rxrpc_release_call() is later called,
    it doesn't call rxrpc_disconnect_call() and so the call isn't removed from
    the peer's error distribution list and the list gets corrupted.

    KASAN finds the issue as an access after release on a call, but the
    position at which it occurs is confusing as it appears to be related to a
    different call (the call site is where the latter call is being removed
    from the error distribution list and either the next or pprev pointer
    points to a previously released call).

    Fix this by moving the setting of the flag from __rxrpc_disconnect_call()
    to rxrpc_disconnect_call() in the same place that the connection pointer
    was being cleared.

    Fixes: 5273a191dca6 ("rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect")
    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/rxrpc/conn_object.c | 3 +--
    1 file changed, 1 insertion(+), 2 deletions(-)

    diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
    index 13b29e491de91..af02328205979 100644
    --- a/net/rxrpc/conn_object.c
    +++ b/net/rxrpc/conn_object.c
    @@ -163,8 +163,6 @@ void __rxrpc_disconnect_call(struct rxrpc_connection *conn,

    _enter("%d,%x", conn->debug_id, call->cid);

    - set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
    -
    if (rcu_access_pointer(chan->call) == call) {
    /* Save the result of the call so that we can repeat it if necessary
    * through the channel, whilst disposing of the actual call record.
    @@ -209,6 +207,7 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
    __rxrpc_disconnect_call(conn, call);
    spin_unlock(&conn->channel_lock);

    + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
    conn->idle_timestamp = jiffies;
    }

    --
    2.20.1


    \
     
     \ /
      Last update: 2020-02-13 16:28    [W:8.495 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site