Skip to content

Commit 6ff64d2

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe: "Nothing profound here, just a last set of long standing bug fixes: - Incorrect error unwind in qib and pvrdma - User triggerable NULL pointer crash in mlx5 with ODP prefetch - syzkaller RCU race in uverbs - Rare double free crash in ipoib" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: IB/ipoib: Fix double free of skb in case of multicast traffic in CM mode RDMA/core: Fix double destruction of uobject RDMA/pvrdma: Fix missing pci disable in pvrdma_pci_probe() RDMA/mlx5: Fix NULL pointer dereference in destroy_prefetch_work IB/qib: Call kobject_put() when kobject_init_and_add() fails
2 parents 411ea67 + 1acba6a commit 6ff64d2

File tree

9 files changed

+47
-25
lines changed

9 files changed

+47
-25
lines changed

drivers/infiniband/core/rdma_core.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
153153
uobj->context = NULL;
154154

155155
/*
156-
* For DESTROY the usecnt is held write locked, the caller is expected
157-
* to put it unlock and put the object when done with it. Only DESTROY
158-
* can remove the IDR handle.
156+
* For DESTROY the usecnt is not changed, the caller is expected to
157+
* manage it via uobj_put_destroy(). Only DESTROY can remove the IDR
158+
* handle.
159159
*/
160160
if (reason != RDMA_REMOVE_DESTROY)
161161
atomic_set(&uobj->usecnt, 0);
@@ -187,7 +187,7 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
187187
/*
188188
* This calls uverbs_destroy_uobject() using the RDMA_REMOVE_DESTROY
189189
* sequence. It should only be used from command callbacks. On success the
190-
* caller must pair this with rdma_lookup_put_uobject(LOOKUP_WRITE). This
190+
* caller must pair this with uobj_put_destroy(). This
191191
* version requires the caller to have already obtained an
192192
* LOOKUP_DESTROY uobject kref.
193193
*/
@@ -198,6 +198,13 @@ int uobj_destroy(struct ib_uobject *uobj, struct uverbs_attr_bundle *attrs)
198198

199199
down_read(&ufile->hw_destroy_rwsem);
200200

201+
/*
202+
* Once the uobject is destroyed by RDMA_REMOVE_DESTROY then it is left
203+
* write locked as the callers put it back with UVERBS_LOOKUP_DESTROY.
204+
* This is because any other concurrent thread can still see the object
205+
* in the xarray due to RCU. Leaving it locked ensures nothing else will
206+
* touch it.
207+
*/
201208
ret = uverbs_try_lock_object(uobj, UVERBS_LOOKUP_WRITE);
202209
if (ret)
203210
goto out_unlock;
@@ -216,7 +223,7 @@ int uobj_destroy(struct ib_uobject *uobj, struct uverbs_attr_bundle *attrs)
216223
/*
217224
* uobj_get_destroy destroys the HW object and returns a handle to the uobj
218225
* with a NULL object pointer. The caller must pair this with
219-
* uverbs_put_destroy.
226+
* uobj_put_destroy().
220227
*/
221228
struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj,
222229
u32 id, struct uverbs_attr_bundle *attrs)
@@ -250,8 +257,7 @@ int __uobj_perform_destroy(const struct uverbs_api_object *obj, u32 id,
250257
uobj = __uobj_get_destroy(obj, id, attrs);
251258
if (IS_ERR(uobj))
252259
return PTR_ERR(uobj);
253-
254-
rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE);
260+
uobj_put_destroy(uobj);
255261
return 0;
256262
}
257263

drivers/infiniband/hw/mlx5/mr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
14391439

14401440
if (is_odp_mr(mr)) {
14411441
to_ib_umem_odp(mr->umem)->private = mr;
1442+
init_waitqueue_head(&mr->q_deferred_work);
14421443
atomic_set(&mr->num_deferred_work, 0);
14431444
err = xa_err(xa_store(&dev->odp_mkeys,
14441445
mlx5_base_mkey(mr->mmkey.key), &mr->mmkey,

drivers/infiniband/hw/qib/qib_sysfs.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num,
760760
qib_dev_err(dd,
761761
"Skipping linkcontrol sysfs info, (err %d) port %u\n",
762762
ret, port_num);
763-
goto bail;
763+
goto bail_link;
764764
}
765765
kobject_uevent(&ppd->pport_kobj, KOBJ_ADD);
766766

@@ -770,7 +770,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num,
770770
qib_dev_err(dd,
771771
"Skipping sl2vl sysfs info, (err %d) port %u\n",
772772
ret, port_num);
773-
goto bail_link;
773+
goto bail_sl;
774774
}
775775
kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD);
776776

@@ -780,7 +780,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num,
780780
qib_dev_err(dd,
781781
"Skipping diag_counters sysfs info, (err %d) port %u\n",
782782
ret, port_num);
783-
goto bail_sl;
783+
goto bail_diagc;
784784
}
785785
kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD);
786786

@@ -793,7 +793,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num,
793793
qib_dev_err(dd,
794794
"Skipping Congestion Control sysfs info, (err %d) port %u\n",
795795
ret, port_num);
796-
goto bail_diagc;
796+
goto bail_cc;
797797
}
798798

799799
kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
@@ -854,6 +854,7 @@ void qib_verbs_unregister_sysfs(struct qib_devdata *dd)
854854
&cc_table_bin_attr);
855855
kobject_put(&ppd->pport_cc_kobj);
856856
}
857+
kobject_put(&ppd->diagc_kobj);
857858
kobject_put(&ppd->sl2vl_kobj);
858859
kobject_put(&ppd->pport_kobj);
859860
}

drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
829829
!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
830830
dev_err(&pdev->dev, "PCI BAR region not MMIO\n");
831831
ret = -ENOMEM;
832-
goto err_free_device;
832+
goto err_disable_pdev;
833833
}
834834

835835
ret = pci_request_regions(pdev, DRV_NAME);

drivers/infiniband/ulp/ipoib/ipoib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,12 @@ struct ipoib_dev_priv {
377377
struct ipoib_rx_buf *rx_ring;
378378

379379
struct ipoib_tx_buf *tx_ring;
380+
/* cyclic ring variables for managing tx_ring, for UD only */
380381
unsigned int tx_head;
381382
unsigned int tx_tail;
383+
/* cyclic ring variables for counting overall outstanding send WRs */
384+
unsigned int global_tx_head;
385+
unsigned int global_tx_tail;
382386
struct ib_sge tx_sge[MAX_SKB_FRAGS + 1];
383387
struct ib_ud_wr tx_wr;
384388
struct ib_wc send_wc[MAX_SEND_CQE];

drivers/infiniband/ulp/ipoib/ipoib_cm.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,8 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
756756
return;
757757
}
758758

759-
if ((priv->tx_head - priv->tx_tail) == ipoib_sendq_size - 1) {
759+
if ((priv->global_tx_head - priv->global_tx_tail) ==
760+
ipoib_sendq_size - 1) {
760761
ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
761762
tx->qp->qp_num);
762763
netif_stop_queue(dev);
@@ -786,7 +787,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
786787
} else {
787788
netif_trans_update(dev);
788789
++tx->tx_head;
789-
++priv->tx_head;
790+
++priv->global_tx_head;
790791
}
791792
}
792793

@@ -820,10 +821,11 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
820821
netif_tx_lock(dev);
821822

822823
++tx->tx_tail;
823-
++priv->tx_tail;
824+
++priv->global_tx_tail;
824825

825826
if (unlikely(netif_queue_stopped(dev) &&
826-
(priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1 &&
827+
((priv->global_tx_head - priv->global_tx_tail) <=
828+
ipoib_sendq_size >> 1) &&
827829
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)))
828830
netif_wake_queue(dev);
829831

@@ -1232,8 +1234,9 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
12321234
dev_kfree_skb_any(tx_req->skb);
12331235
netif_tx_lock_bh(p->dev);
12341236
++p->tx_tail;
1235-
++priv->tx_tail;
1236-
if (unlikely(priv->tx_head - priv->tx_tail == ipoib_sendq_size >> 1) &&
1237+
++priv->global_tx_tail;
1238+
if (unlikely((priv->global_tx_head - priv->global_tx_tail) <=
1239+
ipoib_sendq_size >> 1) &&
12371240
netif_queue_stopped(p->dev) &&
12381241
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
12391242
netif_wake_queue(p->dev);

drivers/infiniband/ulp/ipoib/ipoib_ib.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
407407
dev_kfree_skb_any(tx_req->skb);
408408

409409
++priv->tx_tail;
410+
++priv->global_tx_tail;
410411

411412
if (unlikely(netif_queue_stopped(dev) &&
412-
((priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1) &&
413+
((priv->global_tx_head - priv->global_tx_tail) <=
414+
ipoib_sendq_size >> 1) &&
413415
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)))
414416
netif_wake_queue(dev);
415417

@@ -634,7 +636,8 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
634636
else
635637
priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
636638
/* increase the tx_head after send success, but use it for queue state */
637-
if (priv->tx_head - priv->tx_tail == ipoib_sendq_size - 1) {
639+
if ((priv->global_tx_head - priv->global_tx_tail) ==
640+
ipoib_sendq_size - 1) {
638641
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
639642
netif_stop_queue(dev);
640643
}
@@ -662,6 +665,7 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
662665

663666
rc = priv->tx_head;
664667
++priv->tx_head;
668+
++priv->global_tx_head;
665669
}
666670
return rc;
667671
}
@@ -807,6 +811,7 @@ int ipoib_ib_dev_stop_default(struct net_device *dev)
807811
ipoib_dma_unmap_tx(priv, tx_req);
808812
dev_kfree_skb_any(tx_req->skb);
809813
++priv->tx_tail;
814+
++priv->global_tx_tail;
810815
}
811816

812817
for (i = 0; i < ipoib_recvq_size; ++i) {

drivers/infiniband/ulp/ipoib/ipoib_main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,9 +1184,11 @@ static void ipoib_timeout(struct net_device *dev, unsigned int txqueue)
11841184

11851185
ipoib_warn(priv, "transmit timeout: latency %d msecs\n",
11861186
jiffies_to_msecs(jiffies - dev_trans_start(dev)));
1187-
ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n",
1188-
netif_queue_stopped(dev),
1189-
priv->tx_head, priv->tx_tail);
1187+
ipoib_warn(priv,
1188+
"queue stopped %d, tx_head %u, tx_tail %u, global_tx_head %u, global_tx_tail %u\n",
1189+
netif_queue_stopped(dev), priv->tx_head, priv->tx_tail,
1190+
priv->global_tx_head, priv->global_tx_tail);
1191+
11901192
/* XXX reset QP, etc. */
11911193
}
11921194

@@ -1701,7 +1703,7 @@ static int ipoib_dev_init_default(struct net_device *dev)
17011703
goto out_rx_ring_cleanup;
17021704
}
17031705

1704-
/* priv->tx_head, tx_tail & tx_outstanding are already 0 */
1706+
/* priv->tx_head, tx_tail and global_tx_tail/head are already 0 */
17051707

17061708
if (ipoib_transport_dev_init(dev, priv->ca)) {
17071709
pr_warn("%s: ipoib_transport_dev_init failed\n",

include/rdma/uverbs_std_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj,
8888

8989
static inline void uobj_put_destroy(struct ib_uobject *uobj)
9090
{
91-
rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE);
91+
rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_DESTROY);
9292
}
9393

9494
static inline void uobj_put_read(struct ib_uobject *uobj)

0 commit comments

Comments
 (0)