From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
Dan Carpenter <error27@gmail.com>,
Roland Dreier <rolandd@cisco.com>
Subject: [16/49] IB/uverbs: Handle large number of entries in poll CQ
Date: Wed, 05 Jan 2011 15:00:34 -0800 [thread overview]
Message-ID: <20110105230325.073385055@clark.site> (raw)
In-Reply-To: <20110105230438.GA26241@kroah.com>
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dan Carpenter <error27@gmail.com>
commit 7182afea8d1afd432a17c18162cc3fd441d0da93 upstream.
In ib_uverbs_poll_cq() code there is a potential integer overflow if
userspace passes in a large cmd.ne. The calls to kmalloc() would
allocate smaller buffers than intended, leading to memory corruption.
There iss also an information leak if resp wasn't all used.
Unprivileged userspace may call this function, although only if an
RDMA device that uses this function is present.
Fix this by copying CQ entries one at a time, which avoids the
allocation entirely, and also by moving this copying into a function
that makes sure to initialize all memory copied to userspace.
Special thanks to Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
for his help and advice.
Signed-off-by: Dan Carpenter <error27@gmail.com>
[ Monkey around with things a bit to avoid bad code generation by gcc
when designated initializers are used. - Roland ]
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/infiniband/core/uverbs_cmd.c | 101 +++++++++++++++++++----------------
1 file changed, 57 insertions(+), 44 deletions(-)
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -875,68 +875,81 @@ out:
return ret ? ret : in_len;
}
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+ struct ib_uverbs_wc 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;
+ tmp.reserved = 0;
+
+ 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;
+ 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;
- int i;
- int rsize;
+ struct ib_wc wc;
+ int ret;
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);
-
- put_cq_read(cq);
+ /* 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 resp;
+
+ memset(&resp, 0, sizeof resp);
+ while (resp.count < cmd.ne) {
+ ret = ib_poll_cq(cq, 1, &wc);
+ if (ret < 0)
+ goto out_put;
+ if (!ret)
+ break;
+
+ ret = copy_wc_to_user(data_ptr, &wc);
+ if (ret)
+ goto out_put;
- 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;
+ data_ptr += sizeof(struct ib_uverbs_wc);
+ ++resp.count;
}
- if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+ if (copy_to_user(header_ptr, &resp, sizeof resp)) {
ret = -EFAULT;
+ 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,
next prev parent reply other threads:[~2011-01-05 23:06 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-05 23:04 [00/49] 2.6.32.28-longterm review Greg KH
2011-01-05 23:00 ` Greg KH
2011-01-05 23:00 ` [01/49] TTY: Fix error return from tty_ldisc_open() Greg KH
2011-01-05 23:00 ` [02/49] x86, hotplug: Use mwait to offline a processor, fix the legacy case Greg KH
2011-01-05 23:00 ` [03/49] fuse: verify ioctl retries Greg KH
2011-01-05 23:00 ` [04/49] fuse: fix ioctl when server is 32bit Greg KH
2011-01-05 23:00 ` [05/49] ALSA: hda: Use model=lg quirk for LG P1 Express to enable playback and capture Greg KH
2011-01-05 23:00 ` [06/49] drm/kms: remove spaces from connector names (v2) Greg KH
2011-01-05 23:49 ` [Stable-review] " Ben Hutchings
2011-01-05 23:56 ` Greg KH
2011-01-06 0:04 ` Ben Hutchings
2011-01-06 0:32 ` Alex Deucher
2011-01-05 23:00 ` [07/49] nohz: Fix printk_needs_cpu() return value on offline cpus Greg KH
2011-01-05 23:00 ` [08/49] nohz: Fix get_next_timer_interrupt() vs cpu hotplug Greg KH
2011-01-05 23:00 ` [09/49] NFS: Fix panic after nfs_umount() Greg KH
2011-01-05 23:00 ` [10/49] nfsd: Fix possible BUG_ON firing in set_change_info Greg KH
2011-01-05 23:00 ` [11/49] NFS: Fix fcntl F_GETLK not reporting some conflicts Greg KH
2011-01-05 23:00 ` [12/49] sunrpc: prevent use-after-free on clearing XPT_BUSY Greg KH
2011-01-05 23:00 ` [13/49] hwmon: (adm1026) Allow 1 as a valid divider value Greg KH
2011-01-05 23:00 ` [14/49] hwmon: (adm1026) Fix setting fan_div Greg KH
2011-01-05 23:00 ` [15/49] amd64_edac: Fix interleaving check Greg KH
2011-01-05 23:00 ` Greg KH [this message]
2011-01-05 23:00 ` [17/49] PM / Hibernate: Fix PM_POST_* notification with user-space suspend Greg KH
2011-01-05 23:00 ` [18/49] ACPICA: Fix Scope() op in module level code Greg KH
2011-01-05 23:00 ` [19/49] ACPI: EC: Add another dmi match entry for MSI hardware Greg KH
2011-01-05 23:00 ` [20/49] orinoco: fix TKIP countermeasure behaviour Greg KH
2011-01-05 23:00 ` [21/49] orinoco: clear countermeasure setting on commit Greg KH
2011-01-05 23:00 ` [22/49] x86, amd: Fix panic on AMD CPU family 0x15 Greg KH
2011-01-05 23:00 ` [23/49] md: fix bug with re-adding of partially recovered device Greg KH
2011-01-05 23:00 ` [24/49] tracing: Fix panic when lseek() called on "trace" opened for writing Greg KH
2011-01-05 23:00 ` [25/49] x86, gcc-4.6: Use gcc -m options when building vdso Greg KH
2011-01-05 23:00 ` [26/49] x86: Enable the intr-remap fault handling after local APIC setup Greg KH
2011-01-05 23:00 ` [27/49] x86, vt-d: Handle previous faults after enabling fault handling Greg KH
2011-01-05 23:00 ` [28/49] x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode Greg KH
2011-01-05 23:00 ` [29/49] x86, vt-d: Quirk for masking vtd spec errors to platform error handling logic Greg KH
2011-01-05 23:00 ` [30/49] hvc_console: Fix race between hvc_close and hvc_remove Greg KH
2011-01-05 23:00 ` [31/49] hvc_console: Fix race between hvc_close and hvc_remove, again Greg KH
2011-01-05 23:00 ` [32/49] HID: hidraw: fix window in hidraw_release Greg KH
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=20110105230325.073385055@clark.site \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=error27@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rolandd@cisco.com \
--cc=stable-review@kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox