[kernel] r16834 - in dists/lenny-security/linux-2.6/debian: . patches/bugfix/all patches/series
Dann Frazier
dannf at alioth.debian.org
Mon Jan 17 20:22:39 UTC 2011
Author: dannf
Date: Mon Jan 17 20:22:36 2011
New Revision: 16834
Log:
IB/uverbs: Handle large number of entries in poll CQ (CVE-2010-4649)
Added:
dists/lenny-security/linux-2.6/debian/patches/bugfix/all/ib-uverbs-handle-large-number-of-entries-in-poll-CQ.patch
Modified:
dists/lenny-security/linux-2.6/debian/changelog
dists/lenny-security/linux-2.6/debian/patches/series/26lenny2
Modified: dists/lenny-security/linux-2.6/debian/changelog
==============================================================================
--- dists/lenny-security/linux-2.6/debian/changelog Mon Jan 17 20:14:20 2011 (r16833)
+++ dists/lenny-security/linux-2.6/debian/changelog Mon Jan 17 20:22:36 2011 (r16834)
@@ -22,6 +22,7 @@
* sctp: a race between ICMP protocol unreachable and connect() (CVE-2010-4526)
* sound: Prevent buffer overflow in OSS load_mixer_volumes (CVE-2010-4527)
* CAN: Use inode instead of kernel address for /proc file (CVE-2010-4565)
+ * IB/uverbs: Handle large number of entries in poll CQ (CVE-2010-4649)
[ Moritz Muehlenhoff ]
* blkback/blktap/netback: Fix CVE-2010-3699
Added: dists/lenny-security/linux-2.6/debian/patches/bugfix/all/ib-uverbs-handle-large-number-of-entries-in-poll-CQ.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/lenny-security/linux-2.6/debian/patches/bugfix/all/ib-uverbs-handle-large-number-of-entries-in-poll-CQ.patch Mon Jan 17 20:22:36 2011 (r16834)
@@ -0,0 +1,158 @@
+commit 6c4ff74fe922494252bb112aa86359b9559cef10
+Author: Dan Carpenter <error27 at gmail.com>
+Date: Wed Oct 13 09:13:12 2010 +0000
+
+ IB/uverbs: Handle large number of entries in poll CQ
+
+ 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 at obsidianresearch.com>
+ for his help and advice.
+
+ Cc: <stable at kernel.org>
+ Signed-off-by: Dan Carpenter <error27 at 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 at cisco.com>
+ [dannf: backported to Debian's 2.6.26]
+
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index 2c3bff5..6c788a1 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -877,68 +877,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.imm_data = (__u32 __force) wc->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);
++ /* 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;
+
+- put_cq_read(cq);
++ 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].imm_data = (__u32 __force) wc[i].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,
Modified: dists/lenny-security/linux-2.6/debian/patches/series/26lenny2
==============================================================================
--- dists/lenny-security/linux-2.6/debian/patches/series/26lenny2 Mon Jan 17 20:14:20 2011 (r16833)
+++ dists/lenny-security/linux-2.6/debian/patches/series/26lenny2 Mon Jan 17 20:22:36 2011 (r16834)
@@ -19,3 +19,4 @@
+ bugfix/all/sctp-fix-race-between-ICMP-protocol-unreachable-and-connect.patch
+ bugfix/all/sound-prevent-buffer-overflow-in-OSS-load_mixer_volumes.patch
+ bugfix/all/can-use-inode-instead-of-kernel-address-for-proc-file.patch
++ bugfix/all/ib-uverbs-handle-large-number-of-entries-in-poll-CQ.patch
More information about the Kernel-svn-changes
mailing list