@@ -903,17 +903,17 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
struct ib_wc *wc;
int ret = 0;
int i;
- int rsize;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ cmd.ne = min_t(u32, cmd.ne, IB_UVERBS_POLL_CQ_MAX_ENTRIES);
+
wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
if (!wc)
return -ENOMEM;
- rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
- resp = kmalloc(rsize, GFP_KERNEL);
+ resp = kmalloc(sizeof *resp + cmd.ne * sizeof *resp->wc, GFP_KERNEL);
if (!resp) {
ret = -ENOMEM;
goto out_wc;
@@ -925,10 +925,17 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
goto out;
}
- resp->count = ib_poll_cq(cq, cmd.ne, wc);
+ ret = ib_poll_cq(cq, cmd.ne, wc);
+ if (ret < 0) {
+ ret = -EIO;
+ goto out;
+ }
put_cq_read(cq);
+ resp->count = ret;
+ resp->reserved = 0;
+
for (i = 0; i < resp->count; i++) {
resp->wc[i].wr_id = wc[i].wr_id;
resp->wc[i].status = wc[i].status;
@@ -944,9 +951,11 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
resp->wc[i].sl = wc[i].sl;
resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
resp->wc[i].port_num = wc[i].port_num;
+ resp->wc[i].reserved = 0;
}
- if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+ if (copy_to_user((void __user *) (unsigned long) cmd.response, resp,
+ sizeof *resp + resp->count * sizeof *resp->wc))
ret = -EFAULT;
out:
@@ -278,6 +278,10 @@ struct ib_uverbs_resize_cq_resp {
__u64 driver_data[0];
};
+enum {
+ IB_UVERBS_POLL_CQ_MAX_ENTRIES = 1000
+};
+
struct ib_uverbs_poll_cq {
__u64 response;
__u32 cq_handle;