]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
RDMA/core: Add CM to restrack after successful attachment to a device
authorShay Drory <shayd@nvidia.com>
Sun, 18 Apr 2021 13:55:54 +0000 (16:55 +0300)
committerKelsey Skunberg <kelsey.skunberg@canonical.com>
Mon, 24 May 2021 23:46:42 +0000 (17:46 -0600)
BugLink: https://bugs.launchpad.net/bugs/1929455
[ Upstream commit cb5cd0ea4eb3ce338a593a5331ddb4986ae20faa ]

The device attach triggers addition of CM_ID to the restrack DB.
However, when error occurs, we releasing this device, but defer CM_ID
release. This causes to the situation where restrack sees CM_ID that
is not valid anymore.

As a solution, add the CM_ID to the resource tracking DB only after the
attachment is finished.

Found by syzcaller:
infiniband syz0: added syz_tun
rdma_rxe: ignoring netdev event = 10 for syz_tun
infiniband syz0: set down
infiniband syz0: ib_query_port failed (-19)
restrack: ------------[ cut here    ]------------
infiniband syz0: BUG: RESTRACK detected leak of resources
restrack: User CM_ID object allocated by syz-executor716 is not freed
restrack: ------------[ cut here    ]------------

Fixes: b09c4d701220 ("RDMA/restrack: Improve readability in task name management")
Link: https://lore.kernel.org/r/ab93e56ba831eac65c322b3256796fa1589ec0bb.1618753862.git.leonro@nvidia.com
Signed-off-by: Shay Drory <shayd@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kelsey Skunberg <kelsey.skunberg@canonical.com>
drivers/infiniband/core/cma.c

index e3638f80e1d5257fd1b81254673dae3a91a505fe..6af066a2c8c068e4a66f6eda8cd5691f5e143008 100644 (file)
@@ -463,7 +463,6 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
        id_priv->id.route.addr.dev_addr.transport =
                rdma_node_get_transport(cma_dev->device->node_type);
        list_add_tail(&id_priv->list, &cma_dev->id_list);
-       rdma_restrack_add(&id_priv->res);
 
        trace_cm_id_attach(id_priv, cma_dev->device);
 }
@@ -700,6 +699,7 @@ static int cma_ib_acquire_dev(struct rdma_id_private *id_priv,
        mutex_lock(&lock);
        cma_attach_to_dev(id_priv, listen_id_priv->cma_dev);
        mutex_unlock(&lock);
+       rdma_restrack_add(&id_priv->res);
        return 0;
 }
 
@@ -754,8 +754,10 @@ static int cma_iw_acquire_dev(struct rdma_id_private *id_priv,
        }
 
 out:
-       if (!ret)
+       if (!ret) {
                cma_attach_to_dev(id_priv, cma_dev);
+               rdma_restrack_add(&id_priv->res);
+       }
 
        mutex_unlock(&lock);
        return ret;
@@ -816,6 +818,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
 
 found:
        cma_attach_to_dev(id_priv, cma_dev);
+       rdma_restrack_add(&id_priv->res);
        mutex_unlock(&lock);
        addr = (struct sockaddr_ib *)cma_src_addr(id_priv);
        memcpy(&addr->sib_addr, &sgid, sizeof(sgid));
@@ -2529,6 +2532,7 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv,
               rdma_addr_size(cma_src_addr(id_priv)));
 
        _cma_attach_to_dev(dev_id_priv, cma_dev);
+       rdma_restrack_add(&dev_id_priv->res);
        cma_id_get(id_priv);
        dev_id_priv->internal_id = 1;
        dev_id_priv->afonly = id_priv->afonly;
@@ -3169,6 +3173,7 @@ port_found:
        ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
        id_priv->id.port_num = p;
        cma_attach_to_dev(id_priv, cma_dev);
+       rdma_restrack_add(&id_priv->res);
        cma_set_loopback(cma_src_addr(id_priv));
 out:
        mutex_unlock(&lock);
@@ -3201,6 +3206,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
                if (status)
                        pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to acquire device. status %d\n",
                                             status);
+               rdma_restrack_add(&id_priv->res);
        } else if (status) {
                pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to resolve IP. status %d\n", status);
        }
@@ -3812,6 +3818,8 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
        if (ret)
                goto err2;
 
+       if (!cma_any_addr(addr))
+               rdma_restrack_add(&id_priv->res);
        return 0;
 err2:
        if (id_priv->cma_dev)