Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/core: Add CM to restrack after successful attachment to a device

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>

authored by

Shay Drory and committed by
Jason Gunthorpe
cb5cd0ea 4d51c3d9

+10 -2
+10 -2
drivers/infiniband/core/cma.c
··· 454 454 id_priv->id.route.addr.dev_addr.transport = 455 455 rdma_node_get_transport(cma_dev->device->node_type); 456 456 list_add_tail(&id_priv->list, &cma_dev->id_list); 457 - rdma_restrack_add(&id_priv->res); 458 457 459 458 trace_cm_id_attach(id_priv, cma_dev->device); 460 459 } ··· 690 691 mutex_lock(&lock); 691 692 cma_attach_to_dev(id_priv, listen_id_priv->cma_dev); 692 693 mutex_unlock(&lock); 694 + rdma_restrack_add(&id_priv->res); 693 695 return 0; 694 696 } 695 697 ··· 745 745 } 746 746 747 747 out: 748 - if (!ret) 748 + if (!ret) { 749 749 cma_attach_to_dev(id_priv, cma_dev); 750 + rdma_restrack_add(&id_priv->res); 751 + } 750 752 751 753 mutex_unlock(&lock); 752 754 return ret; ··· 809 807 810 808 found: 811 809 cma_attach_to_dev(id_priv, cma_dev); 810 + rdma_restrack_add(&id_priv->res); 812 811 mutex_unlock(&lock); 813 812 addr = (struct sockaddr_ib *)cma_src_addr(id_priv); 814 813 memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); ··· 2529 2526 rdma_addr_size(cma_src_addr(id_priv))); 2530 2527 2531 2528 _cma_attach_to_dev(dev_id_priv, cma_dev); 2529 + rdma_restrack_add(&dev_id_priv->res); 2532 2530 cma_id_get(id_priv); 2533 2531 dev_id_priv->internal_id = 1; 2534 2532 dev_id_priv->afonly = id_priv->afonly; ··· 3207 3203 ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); 3208 3204 id_priv->id.port_num = p; 3209 3205 cma_attach_to_dev(id_priv, cma_dev); 3206 + rdma_restrack_add(&id_priv->res); 3210 3207 cma_set_loopback(cma_src_addr(id_priv)); 3211 3208 out: 3212 3209 mutex_unlock(&lock); ··· 3240 3235 if (status) 3241 3236 pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to acquire device. status %d\n", 3242 3237 status); 3238 + rdma_restrack_add(&id_priv->res); 3243 3239 } else if (status) { 3244 3240 pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to resolve IP. status %d\n", status); 3245 3241 } ··· 3852 3846 if (ret) 3853 3847 goto err2; 3854 3848 3849 + if (!cma_any_addr(addr)) 3850 + rdma_restrack_add(&id_priv->res); 3855 3851 return 0; 3856 3852 err2: 3857 3853 if (id_priv->cma_dev)