RDMA/qedr: Prevent memory overrun in verbs' user responses
[sfrench/cifs-2.6.git] / drivers / infiniband / hw / qedr / verbs.c
index 548e4d1e998f15bfa5356a96c0419c2b2d8deb03..2ae71b8f1ba8a49f1c2aae0e6c59908ed4063093 100644 (file)
 
 #define DB_ADDR_SHIFT(addr)            ((addr) << DB_PWM_ADDR_OFFSET_SHIFT)
 
+static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src,
+                                       size_t len)
+{
+       size_t min_len = min_t(size_t, len, udata->outlen);
+
+       return ib_copy_to_udata(udata, src, min_len);
+}
+
 int qedr_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 {
        if (index > QEDR_ROCE_PKEY_TABLE_LEN)
@@ -378,7 +386,7 @@ struct ib_ucontext *qedr_alloc_ucontext(struct ib_device *ibdev,
        uresp.sges_per_srq_wr = dev->attr.max_srq_sge;
        uresp.max_cqes = QEDR_MAX_CQES;
 
-       rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+       rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
        if (rc)
                goto err;
 
@@ -499,7 +507,7 @@ struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,
 
                uresp.pd_id = pd_id;
 
-               rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+               rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
                if (rc) {
                        DP_ERR(dev, "copy error pd_id=0x%x.\n", pd_id);
                        dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd_id);
@@ -729,7 +737,7 @@ static int qedr_copy_cq_uresp(struct qedr_dev *dev,
        uresp.db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT);
        uresp.icid = cq->icid;
 
-       rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+       rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
        if (rc)
                DP_ERR(dev, "copy error cqid=0x%x.\n", cq->icid);
 
@@ -1238,7 +1246,7 @@ static int qedr_copy_qp_uresp(struct qedr_dev *dev,
        uresp.atomic_supported = dev->atomic_cap != IB_ATOMIC_NONE;
        uresp.qp_id = qp->qp_id;
 
-       rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+       rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
        if (rc)
                DP_ERR(dev,
                       "create qp: failed a copy to user space with qp icid=0x%x.\n",