]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rxrpc: Fix trace-after-put looking at the put connection record
authorDavid Howells <dhowells@redhat.com>
Mon, 7 Oct 2019 09:58:29 +0000 (10:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Jan 2020 13:51:16 +0000 (14:51 +0100)
[ Upstream commit 4c1295dccc0afe0905b6ca4c62ade7f2406f2cfb ]

rxrpc_put_*conn() calls trace_rxrpc_conn() after they have done the
decrement of the refcount - which looks at the debug_id in the connection
record.  But unless the refcount was reduced to zero, we no longer have the
right to look in the record and, indeed, it may be deleted by some other
thread.

Fix this by getting the debug_id out before decrementing the refcount and
then passing that into the tracepoint.

Fixes: 363deeab6d0f ("rxrpc: Add connection tracepoint and client conn state tracepoint")
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/trace/events/rxrpc.h
net/rxrpc/call_accept.c
net/rxrpc/conn_client.c
net/rxrpc/conn_object.c
net/rxrpc/conn_service.c

index a08916eb76152ce4ab6069761621ca59f5784dba..0924119bcfa40f34efa148fa872698f5fd65e66a 100644 (file)
@@ -554,10 +554,10 @@ TRACE_EVENT(rxrpc_peer,
            );
 
 TRACE_EVENT(rxrpc_conn,
-           TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op,
+           TP_PROTO(unsigned int conn_debug_id, enum rxrpc_conn_trace op,
                     int usage, const void *where),
 
-           TP_ARGS(conn, op, usage, where),
+           TP_ARGS(conn_debug_id, op, usage, where),
 
            TP_STRUCT__entry(
                    __field(unsigned int,       conn            )
@@ -567,7 +567,7 @@ TRACE_EVENT(rxrpc_conn,
                             ),
 
            TP_fast_assign(
-                   __entry->conn = conn->debug_id;
+                   __entry->conn = conn_debug_id;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->where = where;
index 8079aacaecace1498c71d0d0ac13937992cc4612..c5566bc4aaca35cfb66c2493503d57b72aed933d 100644 (file)
@@ -88,7 +88,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
                smp_store_release(&b->conn_backlog_head,
                                  (head + 1) & (size - 1));
 
-               trace_rxrpc_conn(conn, rxrpc_conn_new_service,
+               trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service,
                                 atomic_read(&conn->usage), here);
        }
 
index 3dbb126e60608e0288f9a847d06d03bc9e1b3bf5..38d5485320242f2f1e3721d50f6a8744e5684b70 100644 (file)
@@ -217,7 +217,8 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
        rxrpc_get_local(conn->params.local);
        key_get(conn->params.key);
 
-       trace_rxrpc_conn(conn, rxrpc_conn_new_client, atomic_read(&conn->usage),
+       trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_client,
+                        atomic_read(&conn->usage),
                         __builtin_return_address(0));
        trace_rxrpc_client(conn, -1, rxrpc_client_alloc);
        _leave(" = %p", conn);
@@ -989,11 +990,12 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
 void rxrpc_put_client_conn(struct rxrpc_connection *conn)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = conn->debug_id;
        int n;
 
        do {
                n = atomic_dec_return(&conn->usage);
-               trace_rxrpc_conn(conn, rxrpc_conn_put_client, n, here);
+               trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here);
                if (n > 0)
                        return;
                ASSERTCMP(n, >=, 0);
index 004a6eb529bc13a071dce03e77262ad4d930454a..f338efd2880aa1f0147e6cf7270104f8ee94b4ff 100644 (file)
@@ -272,7 +272,7 @@ bool rxrpc_queue_conn(struct rxrpc_connection *conn)
        if (n == 0)
                return false;
        if (rxrpc_queue_work(&conn->processor))
-               trace_rxrpc_conn(conn, rxrpc_conn_queued, n + 1, here);
+               trace_rxrpc_conn(conn->debug_id, rxrpc_conn_queued, n + 1, here);
        else
                rxrpc_put_connection(conn);
        return true;
@@ -287,7 +287,7 @@ void rxrpc_see_connection(struct rxrpc_connection *conn)
        if (conn) {
                int n = atomic_read(&conn->usage);
 
-               trace_rxrpc_conn(conn, rxrpc_conn_seen, n, here);
+               trace_rxrpc_conn(conn->debug_id, rxrpc_conn_seen, n, here);
        }
 }
 
@@ -299,7 +299,7 @@ void rxrpc_get_connection(struct rxrpc_connection *conn)
        const void *here = __builtin_return_address(0);
        int n = atomic_inc_return(&conn->usage);
 
-       trace_rxrpc_conn(conn, rxrpc_conn_got, n, here);
+       trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here);
 }
 
 /*
@@ -313,7 +313,7 @@ rxrpc_get_connection_maybe(struct rxrpc_connection *conn)
        if (conn) {
                int n = atomic_fetch_add_unless(&conn->usage, 1, 0);
                if (n > 0)
-                       trace_rxrpc_conn(conn, rxrpc_conn_got, n + 1, here);
+                       trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n + 1, here);
                else
                        conn = NULL;
        }
@@ -336,10 +336,11 @@ static void rxrpc_set_service_reap_timer(struct rxrpc_net *rxnet,
 void rxrpc_put_service_conn(struct rxrpc_connection *conn)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = conn->debug_id;
        int n;
 
        n = atomic_dec_return(&conn->usage);
-       trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here);
+       trace_rxrpc_conn(debug_id, rxrpc_conn_put_service, n, here);
        ASSERTCMP(n, >=, 0);
        if (n == 1)
                rxrpc_set_service_reap_timer(conn->params.local->rxnet,
@@ -423,7 +424,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
                 */
                if (atomic_cmpxchg(&conn->usage, 1, 0) != 1)
                        continue;
-               trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, NULL);
+               trace_rxrpc_conn(conn->debug_id, rxrpc_conn_reap_service, 0, NULL);
 
                if (rxrpc_conn_is_client(conn))
                        BUG();
index 80773a50c755168773c758cb5c2b5b86c117cf02..6da7c4bf15e88cdb10abce24302d06bbce944149 100644 (file)
@@ -138,7 +138,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
                list_add_tail(&conn->proc_link, &rxnet->conn_proc_list);
                write_unlock(&rxnet->conn_lock);
 
-               trace_rxrpc_conn(conn, rxrpc_conn_new_service,
+               trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service,
                                 atomic_read(&conn->usage),
                                 __builtin_return_address(0));
        }