[kernel/f13/master] Security updates CVE-2010-4346: install_special_mapping skips security_file_mmap check CVE-2010-
Chuck Ebbert
cebbert at fedoraproject.org
Sat Jan 22 17:26:33 UTC 2011
commit ce15d645be55a6229f4c596aca7ba66ca960bb21
Author: Chuck Ebbert <cebbert at redhat.com>
Date: Sat Jan 22 12:25:37 2011 -0500
Security updates
CVE-2010-4346: install_special_mapping skips security_file_mmap check
CVE-2010-4649: IB/uverbs: Handle large number of entries in poll CQ
CVE-2011-0006: ima: fix add LSM rule bug
CVE-2010-4648: orinoco: fix TKIP countermeasure behaviour
CVE-2010-4650: fuse: verify ioctl retries
fuse-verify-ioctl-retries.patch | 56 +++++++
...e-large-number-of-poll-entries-in-poll-cq.patch | 160 ++++++++++++++++++++
ima-fix-add-lsm-rule-bug.patch | 62 ++++++++
...al-mapping-skips-security-file-mmap-check.patch | 107 +++++++++++++
kernel.spec | 30 ++++
orinoco-fix-tkip-countermeasure-behaviour.patch | 59 +++++++
6 files changed, 474 insertions(+), 0 deletions(-)
---
diff --git a/fuse-verify-ioctl-retries.patch b/fuse-verify-ioctl-retries.patch
new file mode 100644
index 0000000..d95d8ce
--- /dev/null
+++ b/fuse-verify-ioctl-retries.patch
@@ -0,0 +1,56 @@
+From: Miklos Szeredi <mszeredi at suse.cz>
+Date: Tue, 30 Nov 2010 15:39:27 +0000 (+0100)
+Subject: fuse: verify ioctl retries
+X-Git-Tag: v2.6.37-rc6~31^2
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7572777eef78ebdee1ecb7c258c0ef94d35bad16
+
+fuse: verify ioctl retries
+
+Verify that the total length of the iovec returned in FUSE_IOCTL_RETRY
+doesn't overflow iov_length().
+
+Signed-off-by: Miklos Szeredi <mszeredi at suse.cz>
+CC: Tejun Heo <tj at kernel.org>
+CC: <stable at kernel.org> [2.6.31+]
+---
+
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 0e2e25b..8b984a2 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1666,6 +1666,20 @@ static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+ return 0;
+ }
+
++/* Make sure iov_length() won't overflow */
++static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
++{
++ size_t n;
++ u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
++
++ for (n = 0; n < count; n++) {
++ if (iov->iov_len > (size_t) max)
++ return -ENOMEM;
++ max -= iov->iov_len;
++ }
++ return 0;
++}
++
+ /*
+ * For ioctls, there is no generic way to determine how much memory
+ * needs to be read and/or written. Furthermore, ioctls are allowed
+@@ -1858,6 +1872,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+ in_iov = page_address(iov_page);
+ out_iov = in_iov + in_iovs;
+
++ err = fuse_verify_ioctl_iov(in_iov, in_iovs);
++ if (err)
++ goto out;
++
++ err = fuse_verify_ioctl_iov(out_iov, out_iovs);
++ if (err)
++ goto out;
++
+ goto retry;
+ }
+
diff --git a/ib-uverbs-handle-large-number-of-poll-entries-in-poll-cq.patch b/ib-uverbs-handle-large-number-of-poll-entries-in-poll-cq.patch
new file mode 100644
index 0000000..cfa5bf9
--- /dev/null
+++ b/ib-uverbs-handle-large-number-of-poll-entries-in-poll-cq.patch
@@ -0,0 +1,160 @@
+From: Dan Carpenter <error27 at gmail.com>
+Date: Wed, 13 Oct 2010 09:13:12 +0000 (+0000)
+Subject: IB/uverbs: Handle large number of entries in poll CQ
+X-Git-Tag: v2.6.37-rc6~22^2
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7182afea8d1afd432a17c18162cc3fd441d0da93
+
+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>
+---
+
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index b342248..c426992 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -893,68 +893,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);
++ /* 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].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,
diff --git a/ima-fix-add-lsm-rule-bug.patch b/ima-fix-add-lsm-rule-bug.patch
new file mode 100644
index 0000000..ac56bcd
--- /dev/null
+++ b/ima-fix-add-lsm-rule-bug.patch
@@ -0,0 +1,62 @@
+From: Mimi Zohar <zohar at linux.vnet.ibm.com>
+Date: Mon, 3 Jan 2011 22:59:10 +0000 (-0800)
+Subject: ima: fix add LSM rule bug
+X-Git-Tag: v2.6.37~5
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=867c20265459d30a01b021a9c1e81fb4c5832aa9
+
+ima: fix add LSM rule bug
+
+If security_filter_rule_init() doesn't return a rule, then not everything
+is as fine as the return code implies.
+
+This bug only occurs when the LSM (eg. SELinux) is disabled at runtime.
+
+Adding an empty LSM rule causes ima_match_rules() to always succeed,
+ignoring any remaining rules.
+
+ default IMA TCB policy:
+ # PROC_SUPER_MAGIC
+ dont_measure fsmagic=0x9fa0
+ # SYSFS_MAGIC
+ dont_measure fsmagic=0x62656572
+ # DEBUGFS_MAGIC
+ dont_measure fsmagic=0x64626720
+ # TMPFS_MAGIC
+ dont_measure fsmagic=0x01021994
+ # SECURITYFS_MAGIC
+ dont_measure fsmagic=0x73636673
+
+ < LSM specific rule >
+ dont_measure obj_type=var_log_t
+
+ measure func=BPRM_CHECK
+ measure func=FILE_MMAP mask=MAY_EXEC
+ measure func=FILE_CHECK mask=MAY_READ uid=0
+
+Thus without the patch, with the boot parameters 'tcb selinux=0', adding
+the above 'dont_measure obj_type=var_log_t' rule to the default IMA TCB
+measurement policy, would result in nothing being measured. The patch
+prevents the default TCB policy from being replaced.
+
+Signed-off-by: Mimi Zohar <zohar at us.ibm.com>
+Cc: James Morris <jmorris at namei.org>
+Acked-by: Serge Hallyn <serge.hallyn at canonical.com>
+Cc: David Safford <safford at watson.ibm.com>
+Cc: <stable at kernel.org>
+Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+
+diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
+index aef8c0a..d661afb 100644
+--- a/security/integrity/ima/ima_policy.c
++++ b/security/integrity/ima/ima_policy.c
+@@ -253,6 +253,8 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
+ result = security_filter_rule_init(entry->lsm[lsm_rule].type,
+ Audit_equal, args,
+ &entry->lsm[lsm_rule].rule);
++ if (!entry->lsm[lsm_rule].rule)
++ return -EINVAL;
+ return result;
+ }
+
diff --git a/install-special-mapping-skips-security-file-mmap-check.patch b/install-special-mapping-skips-security-file-mmap-check.patch
new file mode 100644
index 0000000..b53b399
--- /dev/null
+++ b/install-special-mapping-skips-security-file-mmap-check.patch
@@ -0,0 +1,107 @@
+From: Tavis Ormandy <taviso at cmpxchg8b.com>
+Date: Thu, 9 Dec 2010 14:29:42 +0000 (+0100)
+Subject: install_special_mapping skips security_file_mmap check.
+X-Git-Tag: v2.6.37-rc6~5
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=462e635e5b73ba9a4c03913b77138cd57ce4b050
+
+install_special_mapping skips security_file_mmap check.
+
+[ Trivial backport to 2.6.34 ]
+
+The install_special_mapping routine (used, for example, to setup the
+vdso) skips the security check before insert_vm_struct, allowing a local
+attacker to bypass the mmap_min_addr security restriction by limiting
+the available pages for special mappings.
+
+bprm_mm_init() also skips the check, and although I don't think this can
+be used to bypass any restrictions, I don't see any reason not to have
+the security check.
+
+ $ uname -m
+ x86_64
+ $ cat /proc/sys/vm/mmap_min_addr
+ 65536
+ $ cat install_special_mapping.s
+ section .bss
+ resb BSS_SIZE
+ section .text
+ global _start
+ _start:
+ mov eax, __NR_pause
+ int 0x80
+ $ nasm -D__NR_pause=29 -DBSS_SIZE=0xfffed000 -f elf -o install_special_mapping.o install_special_mapping.s
+ $ ld -m elf_i386 -Ttext=0x10000 -Tbss=0x11000 -o install_special_mapping install_special_mapping.o
+ $ ./install_special_mapping &
+ [1] 14303
+ $ cat /proc/14303/maps
+ 0000f000-00010000 r-xp 00000000 00:00 0 [vdso]
+ 00010000-00011000 r-xp 00001000 00:19 2453665 /home/taviso/install_special_mapping
+ 00011000-ffffe000 rwxp 00000000 00:00 0 [stack]
+
+It's worth noting that Red Hat are shipping with mmap_min_addr set to
+4096.
+
+Signed-off-by: Tavis Ormandy <taviso at google.com>
+Acked-by: Kees Cook <kees at ubuntu.com>
+Acked-by: Robert Swiecki <swiecki at google.com>
+[ Changed to not drop the error code - akpm ]
+Reviewed-by: James Morris <jmorris at namei.org>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+
+diff --git a/fs/exec.c b/fs/exec.c
+index d68c378..c62efcb 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -275,6 +275,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
+ vma->vm_flags = VM_STACK_FLAGS;
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
++
++ err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
++ if (err)
++ goto err;
++
+ err = insert_vm_struct(mm, vma);
+ if (err)
+ goto err;
+diff --git a/mm/mmap.c b/mm/mmap.c
+index b179abb..50a4aa0 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2462,6 +2462,7 @@ int install_special_mapping(struct mm_struct *mm,
+ unsigned long addr, unsigned long len,
+ unsigned long vm_flags, struct page **pages)
+ {
++ int ret;
+ struct vm_area_struct *vma;
+
+ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
+@@ -2479,16 +2480,23 @@ int install_special_mapping(struct mm_struct *mm,
+ vma->vm_ops = &special_mapping_vmops;
+ vma->vm_private_data = pages;
+
+- if (unlikely(insert_vm_struct(mm, vma))) {
+- kmem_cache_free(vm_area_cachep, vma);
+- return -ENOMEM;
+- }
++ ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
++ if (ret)
++ goto out;
++
++ ret = insert_vm_struct(mm, vma);
++ if (ret)
++ goto out;
+
+ mm->total_vm += len >> PAGE_SHIFT;
+
+ perf_event_mmap(vma);
+
+ return 0;
++
++out:
++ kmem_cache_free(vm_area_cachep, vma);
++ return ret;
+ }
+
+ static DEFINE_MUTEX(mm_all_locks_mutex);
diff --git a/kernel.spec b/kernel.spec
index cfc99f7..d6e21b4 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -918,6 +918,17 @@ Patch13925: block-check-for-proper-length-of-iov-entries-earlier-in-blk_rq_map_u
# rhbz#643758
Patch13926: hostap_cs-fix-sleeping-function-called-from-invalid-context.patch
+# CVE-2010-4346
+Patch13930: install-special-mapping-skips-security-file-mmap-check.patch
+# CVE-2010-4649
+Patch13931: ib-uverbs-handle-large-number-of-poll-entries-in-poll-cq.patch
+# CVE-2011-0006
+Patch13932: ima-fix-add-lsm-rule-bug.patch
+# CVE-2010-4648
+Patch13933: orinoco-fix-tkip-countermeasure-behaviour.patch
+# CVE-2010-4650
+Patch13934: fuse-verify-ioctl-retries.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1759,6 +1770,17 @@ ApplyPatch block-check-for-proper-length-of-iov-entries-earlier-in-blk_rq_map_us
# rhbz#643758
ApplyPatch hostap_cs-fix-sleeping-function-called-from-invalid-context.patch
+# CVE-2010-4346
+ApplyPatch install-special-mapping-skips-security-file-mmap-check.patch
+# CVE-2010-4649
+ApplyPatch ib-uverbs-handle-large-number-of-poll-entries-in-poll-cq.patch
+# CVE-2011-0006
+ApplyPatch ima-fix-add-lsm-rule-bug.patch
+# CVE-2010-4648
+ApplyPatch orinoco-fix-tkip-countermeasure-behaviour.patch
+# CVE-2010-4650
+ApplyPatch fuse-verify-ioctl-retries.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2380,6 +2402,14 @@ fi
%changelog
+* Sat Jan 22 2011 Chuck Ebbert <cebbert at redhat.com>
+- Security updates
+ CVE-2010-4346: install_special_mapping skips security_file_mmap check
+ CVE-2010-4649: IB/uverbs: Handle large number of entries in poll CQ
+ CVE-2011-0006: ima: fix add LSM rule bug
+ CVE-2010-4648: orinoco: fix TKIP countermeasure behaviour
+ CVE-2010-4650: fuse: verify ioctl retries
+
* Tue Jan 18 2011 Kyle McMartin <kmcmartin at redhat.com>
- sgruszka: hostap_cs: fix sleeping function called in invalid
context (#643758)
diff --git a/orinoco-fix-tkip-countermeasure-behaviour.patch b/orinoco-fix-tkip-countermeasure-behaviour.patch
new file mode 100644
index 0000000..f62a601
--- /dev/null
+++ b/orinoco-fix-tkip-countermeasure-behaviour.patch
@@ -0,0 +1,59 @@
+From: David Kilroy <kilroyd at googlemail.com>
+Date: Sun, 5 Dec 2010 15:43:55 +0000 (+0000)
+Subject: orinoco: fix TKIP countermeasure behaviour
+X-Git-Tag: v2.6.37-rc6~14^2~14^2
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=0a54917c3fc295cb61f3fb52373c173fd3b69f48
+
+orinoco: fix TKIP countermeasure behaviour
+
+Enable the port when disabling countermeasures, and disable it on
+enabling countermeasures.
+
+This bug causes the response of the system to certain attacks to be
+ineffective.
+
+It also prevents wpa_supplicant from getting scan results, as
+wpa_supplicant disables countermeasures on startup - preventing the
+hardware from scanning.
+
+wpa_supplicant works with ap_mode=2 despite this bug because the commit
+handler re-enables the port.
+
+The log tends to look like:
+
+State: DISCONNECTED -> SCANNING
+Starting AP scan for wildcard SSID
+Scan requested (ret=0) - scan timeout 5 seconds
+EAPOL: disable timer tick
+EAPOL: Supplicant port status: Unauthorized
+Scan timeout - try to get results
+Failed to get scan results
+Failed to get scan results - try scanning again
+Setting scan request: 1 sec 0 usec
+Starting AP scan for wildcard SSID
+Scan requested (ret=-1) - scan timeout 5 seconds
+Failed to initiate AP scan.
+
+Reported by: Giacomo Comes <comes at naic.edu>
+Signed-off by: David Kilroy <kilroyd at googlemail.com>
+Cc: stable at kernel.org
+Signed-off-by: John W. Linville <linville at tuxdriver.com>
+---
+
+diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
+index 93505f9..e5afabe 100644
+--- a/drivers/net/wireless/orinoco/wext.c
++++ b/drivers/net/wireless/orinoco/wext.c
+@@ -911,10 +911,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
+ */
+ if (param->value) {
+ priv->tkip_cm_active = 1;
+- ret = hermes_enable_port(hw, 0);
++ ret = hermes_disable_port(hw, 0);
+ } else {
+ priv->tkip_cm_active = 0;
+- ret = hermes_disable_port(hw, 0);
++ ret = hermes_enable_port(hw, 0);
+ }
+ break;
+
More information about the scm-commits
mailing list