From: Dan Carpenter <error27@gmail.com>
To: Jason Gunthorpe
<jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Cc: Roland Dreier <rolandd-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>,
Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Hal Rosenstock
<hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kernel-janitors-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [patch v3] infiniband: uverbs: handle large number of entries
Date: Tue, 12 Oct 2010 11:31:17 +0000 [thread overview]
Message-ID: <20101012113117.GB6742@bicker> (raw)
In-Reply-To: <20101009231607.GA24649-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
In the original code there was a potential integer overflow if you
passed in a large cmd.ne. The calls to kmalloc() would allocate smaller
buffers than intended, leading to memory corruption.
There was also an information leak.
Documentation/infiniband/user_verbs.txt suggests this function is meant
for unprivileged access.
Jason Gunthorpe suggested that I should modify it to pass the data to
the user bit by bit and avoid the kmalloc() entirely.
CC: stable@kernel.org
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
Please, please, check this. I've think I've done it right, but I don't
have the hardware and can not test it.
It's strange to me that we return "in_len" on success.
struct ib_uverbs_poll_cq_resp is used by userspace libraries right?
Otherwise I could delete it.
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6fcfbeb..b0788b6 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -891,68 +891,89 @@ out:
return ret ? ret : in_len;
}
+static int copy_header_to_user(void __user *dest, u32 count)
+{
+ u32 header[2]; /* the second u32 is reserved */
+
+ memset(header, 0, sizeof(header));
+ if (copy_to_user(dest, header, sizeof(header)))
+ return -EFAULT;
+ return 0;
+}
+
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+ struct ib_uverbs_wc tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ tmp.wr_id = wc->wr_id;
+ tmp.status = wc->status;
+ tmp.opcode = wc->opcode;
+ tmp.vendor_err = wc->vendor_err;
+ tmp.byte_len = wc->byte_len;
+ tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data;
+ tmp.qp_num = wc->qp->qp_num;
+ tmp.src_qp = wc->src_qp;
+ tmp.wc_flags = wc->wc_flags;
+ tmp.pkey_index = wc->pkey_index;
+ tmp.slid = wc->slid;
+ tmp.sl = wc->sl;
+ tmp.dlid_path_bits = wc->dlid_path_bits;
+ tmp.port_num = wc->port_num;
+
+ if (copy_to_user(dest, &tmp, sizeof(tmp)))
+ return -EFAULT;
+ return 0;
+}
+
ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
struct ib_uverbs_poll_cq cmd;
- struct ib_uverbs_poll_cq_resp *resp;
+ u8 __user *header_ptr;
+ u8 __user *data_ptr;
struct ib_cq *cq;
- struct ib_wc *wc;
- int ret = 0;
+ struct ib_wc wc;
+ u32 count = 0;
+ int ret;
int i;
- int rsize;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- 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);
- if (!resp) {
- ret = -ENOMEM;
- goto out_wc;
- }
-
cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
- if (!cq) {
- ret = -EINVAL;
- goto out;
- }
+ if (!cq)
+ return -EINVAL;
- resp->count = ib_poll_cq(cq, cmd.ne, wc);
+ /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+ header_ptr = (void __user *)(unsigned long)cmd.response;
+ data_ptr = header_ptr + sizeof(u32) * 2;
- put_cq_read(cq);
+ for (i = 0; i < cmd.ne; i++) {
+ ret = ib_poll_cq(cq, 1, &wc);
+ if (ret < 0)
+ goto out_put;
+ if (!ret)
+ break;
- for (i = 0; i < resp->count; i++) {
- resp->wc[i].wr_id = wc[i].wr_id;
- resp->wc[i].status = wc[i].status;
- resp->wc[i].opcode = wc[i].opcode;
- resp->wc[i].vendor_err = wc[i].vendor_err;
- resp->wc[i].byte_len = wc[i].byte_len;
- resp->wc[i].ex.imm_data = (__u32 __force) wc[i].ex.imm_data;
- resp->wc[i].qp_num = wc[i].qp->qp_num;
- resp->wc[i].src_qp = wc[i].src_qp;
- resp->wc[i].wc_flags = wc[i].wc_flags;
- resp->wc[i].pkey_index = wc[i].pkey_index;
- resp->wc[i].slid = wc[i].slid;
- 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;
+ ret = copy_wc_to_user(data_ptr, &wc);
+ if (ret)
+ goto out_put;
+ data_ptr += sizeof(struct ib_uverbs_wc);
+ count++;
}
- if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
- ret = -EFAULT;
+ ret = copy_header_to_user(header_ptr, count);
+ if (ret)
+ goto out_put;
-out:
- kfree(resp);
+ ret = in_len;
-out_wc:
- kfree(wc);
- return ret ? ret : in_len;
+out_put:
+ put_cq_read(cq);
+ return ret;
}
ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
WARNING: multiple messages have this Message-ID (diff)
From: Dan Carpenter <error27-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Jason Gunthorpe
<jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Cc: Roland Dreier <rolandd-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>,
Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Hal Rosenstock
<hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kernel-janitors-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [patch v3] infiniband: uverbs: handle large number of entries
Date: Tue, 12 Oct 2010 13:31:17 +0200 [thread overview]
Message-ID: <20101012113117.GB6742@bicker> (raw)
In-Reply-To: <20101009231607.GA24649-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
In the original code there was a potential integer overflow if you
passed in a large cmd.ne. The calls to kmalloc() would allocate smaller
buffers than intended, leading to memory corruption.
There was also an information leak.
Documentation/infiniband/user_verbs.txt suggests this function is meant
for unprivileged access.
Jason Gunthorpe suggested that I should modify it to pass the data to
the user bit by bit and avoid the kmalloc() entirely.
CC: stable-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Signed-off-by: Dan Carpenter <error27-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
Please, please, check this. I've think I've done it right, but I don't
have the hardware and can not test it.
It's strange to me that we return "in_len" on success.
struct ib_uverbs_poll_cq_resp is used by userspace libraries right?
Otherwise I could delete it.
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6fcfbeb..b0788b6 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -891,68 +891,89 @@ out:
return ret ? ret : in_len;
}
+static int copy_header_to_user(void __user *dest, u32 count)
+{
+ u32 header[2]; /* the second u32 is reserved */
+
+ memset(header, 0, sizeof(header));
+ if (copy_to_user(dest, header, sizeof(header)))
+ return -EFAULT;
+ return 0;
+}
+
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+ struct ib_uverbs_wc tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ tmp.wr_id = wc->wr_id;
+ tmp.status = wc->status;
+ tmp.opcode = wc->opcode;
+ tmp.vendor_err = wc->vendor_err;
+ tmp.byte_len = wc->byte_len;
+ tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data;
+ tmp.qp_num = wc->qp->qp_num;
+ tmp.src_qp = wc->src_qp;
+ tmp.wc_flags = wc->wc_flags;
+ tmp.pkey_index = wc->pkey_index;
+ tmp.slid = wc->slid;
+ tmp.sl = wc->sl;
+ tmp.dlid_path_bits = wc->dlid_path_bits;
+ tmp.port_num = wc->port_num;
+
+ if (copy_to_user(dest, &tmp, sizeof(tmp)))
+ return -EFAULT;
+ return 0;
+}
+
ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
{
struct ib_uverbs_poll_cq cmd;
- struct ib_uverbs_poll_cq_resp *resp;
+ u8 __user *header_ptr;
+ u8 __user *data_ptr;
struct ib_cq *cq;
- struct ib_wc *wc;
- int ret = 0;
+ struct ib_wc wc;
+ u32 count = 0;
+ int ret;
int i;
- int rsize;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- 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);
- if (!resp) {
- ret = -ENOMEM;
- goto out_wc;
- }
-
cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
- if (!cq) {
- ret = -EINVAL;
- goto out;
- }
+ if (!cq)
+ return -EINVAL;
- resp->count = ib_poll_cq(cq, cmd.ne, wc);
+ /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+ header_ptr = (void __user *)(unsigned long)cmd.response;
+ data_ptr = header_ptr + sizeof(u32) * 2;
- put_cq_read(cq);
+ for (i = 0; i < cmd.ne; i++) {
+ ret = ib_poll_cq(cq, 1, &wc);
+ if (ret < 0)
+ goto out_put;
+ if (!ret)
+ break;
- for (i = 0; i < resp->count; i++) {
- resp->wc[i].wr_id = wc[i].wr_id;
- resp->wc[i].status = wc[i].status;
- resp->wc[i].opcode = wc[i].opcode;
- resp->wc[i].vendor_err = wc[i].vendor_err;
- resp->wc[i].byte_len = wc[i].byte_len;
- resp->wc[i].ex.imm_data = (__u32 __force) wc[i].ex.imm_data;
- resp->wc[i].qp_num = wc[i].qp->qp_num;
- resp->wc[i].src_qp = wc[i].src_qp;
- resp->wc[i].wc_flags = wc[i].wc_flags;
- resp->wc[i].pkey_index = wc[i].pkey_index;
- resp->wc[i].slid = wc[i].slid;
- 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;
+ ret = copy_wc_to_user(data_ptr, &wc);
+ if (ret)
+ goto out_put;
+ data_ptr += sizeof(struct ib_uverbs_wc);
+ count++;
}
- if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
- ret = -EFAULT;
+ ret = copy_header_to_user(header_ptr, count);
+ if (ret)
+ goto out_put;
-out:
- kfree(resp);
+ ret = in_len;
-out_wc:
- kfree(wc);
- return ret ? ret : in_len;
+out_put:
+ put_cq_read(cq);
+ return ret;
}
ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2010-10-12 11:31 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-07 7:16 [patch] infiniband: uverbs: limit the number of entries Dan Carpenter
2010-10-07 7:16 ` Dan Carpenter
2010-10-07 16:16 ` Jason Gunthorpe
2010-10-07 16:16 ` Jason Gunthorpe
[not found] ` <20101007161649.GD21206-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-10-07 16:59 ` Dan Carpenter
2010-10-07 16:59 ` Dan Carpenter
2010-10-08 7:59 ` Nicolas Palix
2010-10-08 7:59 ` Nicolas Palix
[not found] ` <AANLkTin5zou2JHsdDyhGESuxyPonOs3kLo9Th0vg-kd8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-10-08 14:25 ` [patch v2] " Dan Carpenter
2010-10-08 14:25 ` Dan Carpenter
2010-10-09 23:16 ` [patch] " Jason Gunthorpe
2010-10-09 23:16 ` Jason Gunthorpe
[not found] ` <20101009231607.GA24649-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-10-12 11:31 ` Dan Carpenter [this message]
2010-10-12 11:31 ` [patch v3] infiniband: uverbs: handle large " Dan Carpenter
2010-10-12 21:01 ` Jason Gunthorpe
2010-10-12 21:01 ` Jason Gunthorpe
[not found] ` <20101012210118.GR24268-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-10-13 9:05 ` Dan Carpenter
2010-10-13 9:05 ` Dan Carpenter
2010-10-13 9:13 ` [patch v4] " Dan Carpenter
2010-10-13 9:13 ` Dan Carpenter
2010-11-23 7:10 ` Dan Carpenter
2010-11-23 7:10 ` Dan Carpenter
2010-11-24 22:07 ` Roland Dreier
2010-11-24 22:07 ` Roland Dreier
[not found] ` <adahbf6gytv.fsf-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
2010-11-24 22:18 ` Jason Gunthorpe
2010-11-24 22:18 ` Jason Gunthorpe
[not found] ` <20101124221845.GH2369-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-11-25 4:05 ` Roland Dreier
2010-11-25 4:05 ` Roland Dreier
[not found] ` <adad3pugi90.fsf-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
2010-11-25 4:13 ` Jason Gunthorpe
2010-11-25 4:13 ` Jason Gunthorpe
[not found] ` <20101125041337.GA11049-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-11-25 15:00 ` ibv_post_send/recv kernel path optimizations (was: uverbs: handle large number of entries) Or Gerlitz
[not found] ` <4CEE7A22.2040706-smomgflXvOZWk0Htik3J/w@public.gmane.org>
2010-11-26 11:56 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C644860408064B44854-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-12-01 8:11 ` ibv_post_send/recv kernel path optimizations Or Gerlitz
[not found] ` <4CF60343.7050602-smomgflXvOZWk0Htik3J/w@public.gmane.org>
2010-12-08 12:14 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C64486040806673CF38-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-12-08 18:30 ` Jason Gunthorpe
2010-12-08 19:04 ` Roland Dreier
2010-12-14 14:12 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C644860408066ABCF66-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-12-14 18:17 ` Jason Gunthorpe
[not found] ` <20101214181735.GA2506-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2010-12-27 12:38 ` Or Gerlitz
[not found] ` <4D1888CB.2010101-hKgKHo2Ms0FWk0Htik3J/w@public.gmane.org>
2010-12-27 15:18 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C644860408066C547E0-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-12-27 15:22 ` Or Gerlitz
[not found] ` <4D18AF2D.1010109-smomgflXvOZWk0Htik3J/w@public.gmane.org>
2010-12-27 15:40 ` Walukiewicz, Miroslaw
2011-01-05 18:16 ` Roland Dreier
[not found] ` <ada4o9nfc6e.fsf-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
2011-01-10 14:15 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C644860408066DDDF31-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2011-01-10 20:38 ` Roland Dreier
[not found] ` <adawrmc7av2.fsf-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
2011-01-21 11:41 ` Walukiewicz, Miroslaw
[not found] ` <BE2BFE91933D1B4089447C644860408066F95285-IGOiFh9zz4wLt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2011-01-21 15:49 ` Hefty, Sean
[not found] ` <CF9C39F99A89134C9CF9C4CCB68B8DDF25C1D51C31-osO9UTpF0USkrb+BlOpmy7fspsVTdybXVpNB7YpNyf8@public.gmane.org>
2011-01-24 17:03 ` Walukiewicz, Miroslaw
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101012113117.GB6742@bicker \
--to=error27@gmail.com \
--cc=hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org \
--cc=kernel-janitors-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=rolandd-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org \
--cc=sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.