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 ]------------
Unified · Split
| @@ -454,7 +454,6 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv, · 453 unmodified lines | |||
| 454 | id_priv->id.route.addr.dev_addr.transport = | 454 | id_priv->id.route.addr.dev_addr.transport = |
| 455 | rdma_node_get_transport(cma_dev->device->node_type); | 455 | rdma_node_get_transport(cma_dev->device->node_type); |
| 456 | list_add_tail(&id_priv->list, &cma_dev->id_list); | 456 | list_add_tail(&id_priv->list, &cma_dev->id_list); |
| 457 | rdma_restrack_add(&id_priv->res); | ||
| 458 | 457 | ||
| 459 | trace_cm_id_attach(id_priv, cma_dev->device); | 458 | trace_cm_id_attach(id_priv, cma_dev->device); |
| 460 | } | 459 | } |
| @@ -691,6 +690,7 @@ static int cma_ib_acquire_dev(struct rdma_id_private *id_priv, · 230 unmodified lines | |||
| 691 | mutex_lock(&lock); | 690 | mutex_lock(&lock); |
| 692 | cma_attach_to_dev(id_priv, listen_id_priv->cma_dev); | 691 | cma_attach_to_dev(id_priv, listen_id_priv->cma_dev); |
| 693 | mutex_unlock(&lock); | 692 | mutex_unlock(&lock); |
| 693 | rdma_restrack_add(&id_priv->res); | ||
| 694 | return 0; | 694 | return 0; |
| 695 | } | 695 | } |
| 696 | 696 | ||
| @@ -745,8 +745,10 @@ static int cma_iw_acquire_dev(struct rdma_id_private *id_priv, · 48 unmodified lines | |||
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | out: | 747 | out: |
| 748 | if (!ret) | 748 | if (!ret) { |
| 749 | cma_attach_to_dev(id_priv, cma_dev); | 749 | cma_attach_to_dev(id_priv, cma_dev); |
| 750 | rdma_restrack_add(&id_priv->res); | ||
| 751 | } | ||
| 750 | 752 | ||
| 751 | mutex_unlock(&lock); | 753 | mutex_unlock(&lock); |
| 752 | return ret; | 754 | return ret; |
| @@ -807,6 +809,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) · 54 unmodified lines | |||
| 807 | 809 | ||
| 808 | found: | 810 | found: |
| 809 | cma_attach_to_dev(id_priv, cma_dev); | 811 | cma_attach_to_dev(id_priv, cma_dev); |
| 812 | rdma_restrack_add(&id_priv->res); | ||
| 810 | mutex_unlock(&lock); | 813 | mutex_unlock(&lock); |
| 811 | addr = (struct sockaddr_ib *)cma_src_addr(id_priv); | 814 | addr = (struct sockaddr_ib *)cma_src_addr(id_priv); |
| 812 | memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); | 815 | memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); |
| @@ -2526,6 +2529,7 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv, · 1713 unmodified lines | |||
| 2526 | rdma_addr_size(cma_src_addr(id_priv))); | 2529 | rdma_addr_size(cma_src_addr(id_priv))); |
| 2527 | 2530 | ||
| 2528 | _cma_attach_to_dev(dev_id_priv, cma_dev); | 2531 | _cma_attach_to_dev(dev_id_priv, cma_dev); |
| 2532 | rdma_restrack_add(&dev_id_priv->res); | ||
| 2529 | cma_id_get(id_priv); | 2533 | cma_id_get(id_priv); |
| 2530 | dev_id_priv->internal_id = 1; | 2534 | dev_id_priv->internal_id = 1; |
| 2531 | dev_id_priv->afonly = id_priv->afonly; | 2535 | dev_id_priv->afonly = id_priv->afonly; |
| @@ -3203,6 +3207,7 @@ port_found: · 671 unmodified lines | |||
| 3203 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); | 3207 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); |
| 3204 | id_priv->id.port_num = p; | 3208 | id_priv->id.port_num = p; |
| 3205 | cma_attach_to_dev(id_priv, cma_dev); | 3209 | cma_attach_to_dev(id_priv, cma_dev); |
| 3210 | rdma_restrack_add(&id_priv->res); | ||
| 3206 | cma_set_loopback(cma_src_addr(id_priv)); | 3211 | cma_set_loopback(cma_src_addr(id_priv)); |
| 3207 | out: | 3212 | out: |
| 3208 | mutex_unlock(&lock); | 3213 | mutex_unlock(&lock); |
| @@ -3235,6 +3240,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, · 26 unmodified lines | |||
| 3235 | if (status) | 3240 | if (status) |
| 3236 | pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to acquire device. status %d\n", | 3241 | pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to acquire device. status %d\n", |
| 3237 | status); | 3242 | status); |
| 3243 | rdma_restrack_add(&id_priv->res); | ||
| 3238 | } else if (status) { | 3244 | } else if (status) { |
| 3239 | pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to resolve IP. status %d\n", status); | 3245 | pr_debug_ratelimited("RDMA CM: ADDR_ERROR: failed to resolve IP. status %d\n", status); |
| 3240 | } | 3246 | } |
| @@ -3846,6 +3852,8 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) · 605 unmodified lines | |||
| 3846 | if (ret) | 3852 | if (ret) |
| 3847 | goto err2; | 3853 | goto err2; |
| 3848 | 3854 | ||
| 3855 | if (!cma_any_addr(addr)) | ||
| 3856 | rdma_restrack_add(&id_priv->res); | ||
| 3849 | return 0; | 3857 | return 0; |
| 3850 | err2: | 3858 | err2: |
| 3851 | if (id_priv->cma_dev) | 3859 | if (id_priv->cma_dev) |