summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@windriver.com>2013-03-08 09:53:39 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2013-03-08 09:55:06 -0500
commite338afcb163ba3a3187f07f1fa750ee82d95912a (patch)
treedbd027ce2483025b64ba155646f402178f477448
parente588bc2c02f28f8d56b5b62a296fa4f2806adb65 (diff)
downloadlongterm-queue-2.6.34-e338afcb163ba3a3187f07f1fa750ee82d95912a.tar.gz
add hugetlb CVE fix and the follow on fix
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r--queue/hugetlb-fix-resv_map-leak-in-error-path.patch107
-rw-r--r--queue/mm-fix-vma_resv_map-NULL-pointer.patch67
-rw-r--r--queue/series2
3 files changed, 176 insertions, 0 deletions
diff --git a/queue/hugetlb-fix-resv_map-leak-in-error-path.patch b/queue/hugetlb-fix-resv_map-leak-in-error-path.patch
new file mode 100644
index 0000000..acbbab4
--- /dev/null
+++ b/queue/hugetlb-fix-resv_map-leak-in-error-path.patch
@@ -0,0 +1,107 @@
+From 65a36de41b9c65f3008e0ecc1a0798a67eaf117a Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave@linux.vnet.ibm.com>
+Date: Tue, 29 May 2012 15:06:46 -0700
+Subject: [PATCH] hugetlb: fix resv_map leak in error path
+
+commit c50ac050811d6485616a193eb0f37bfbd191cc89 upstream.
+
+When called for anonymous (non-shared) mappings, hugetlb_reserve_pages()
+does a resv_map_alloc(). It depends on code in hugetlbfs's
+vm_ops->close() to release that allocation.
+
+However, in the mmap() failure path, we do a plain unmap_region() without
+the remove_vma() which actually calls vm_ops->close().
+
+This is a decent fix. This leak could get reintroduced if new code (say,
+after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return
+an error. But, I think it would have to unroll the reservation anyway.
+
+Christoph's test case:
+
+ http://marc.info/?l=linux-mm&m=133728900729735
+
+This patch applies to 3.4 and later. A version for earlier kernels is at
+https://lkml.org/lkml/2012/5/22/418.
+
+Signed-off-by: Dave Hansen <dave@linux.vnet.ibm.com>
+Acked-by: Mel Gorman <mel@csn.ul.ie>
+Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Reported-by: Christoph Lameter <cl@linux.com>
+Tested-by: Christoph Lameter <cl@linux.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index ca9ce49..f7b8054 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2030,6 +2030,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma)
+ kref_get(&reservations->refs);
+ }
+
++static void resv_map_put(struct vm_area_struct *vma)
++{
++ struct resv_map *reservations = vma_resv_map(vma);
++
++ if (!reservations)
++ return;
++ kref_put(&reservations->refs, resv_map_release);
++}
++
+ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
+ {
+ struct hstate *h = hstate_vma(vma);
+@@ -2045,7 +2054,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
+ reserve = (end - start) -
+ region_count(&reservations->regions, start, end);
+
+- kref_put(&reservations->refs, resv_map_release);
++ resv_map_put(vma);
+
+ if (reserve) {
+ hugetlb_acct_memory(h, -reserve);
+@@ -2744,12 +2753,16 @@ int hugetlb_reserve_pages(struct inode *inode,
+ set_vma_resv_flags(vma, HPAGE_RESV_OWNER);
+ }
+
+- if (chg < 0)
+- return chg;
++ if (chg < 0) {
++ ret = chg;
++ goto out_err;
++ }
+
+ /* There must be enough filesystem quota for the mapping */
+- if (hugetlb_get_quota(inode->i_mapping, chg))
+- return -ENOSPC;
++ if (hugetlb_get_quota(inode->i_mapping, chg)) {
++ ret = -ENOSPC;
++ goto out_err;
++ }
+
+ /*
+ * Check enough hugepages are available for the reservation.
+@@ -2758,7 +2771,7 @@ int hugetlb_reserve_pages(struct inode *inode,
+ ret = hugetlb_acct_memory(h, chg);
+ if (ret < 0) {
+ hugetlb_put_quota(inode->i_mapping, chg);
+- return ret;
++ goto out_err;
+ }
+
+ /*
+@@ -2775,6 +2788,9 @@ int hugetlb_reserve_pages(struct inode *inode,
+ if (!vma || vma->vm_flags & VM_MAYSHARE)
+ region_add(&inode->i_mapping->private_list, from, to);
+ return 0;
++out_err:
++ resv_map_put(vma);
++ return ret;
+ }
+
+ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
+--
+1.8.1.2
+
diff --git a/queue/mm-fix-vma_resv_map-NULL-pointer.patch b/queue/mm-fix-vma_resv_map-NULL-pointer.patch
new file mode 100644
index 0000000..cdadf66
--- /dev/null
+++ b/queue/mm-fix-vma_resv_map-NULL-pointer.patch
@@ -0,0 +1,67 @@
+From b25291aea8e7abe48d387e1d76d89e44d1c78175 Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave@linux.vnet.ibm.com>
+Date: Wed, 30 May 2012 07:51:07 -0700
+Subject: [PATCH] mm: fix vma_resv_map() NULL pointer
+
+commit 4523e1458566a0e8ecfaff90f380dd23acc44d27 upstream.
+
+hugetlb_reserve_pages() can be used for either normal file-backed
+hugetlbfs mappings, or MAP_HUGETLB. In the MAP_HUGETLB, semi-anonymous
+mode, there is not a VMA around. The new call to resv_map_put() assumed
+that there was, and resulted in a NULL pointer dereference:
+
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000030
+ IP: vma_resv_map+0x9/0x30
+ PGD 141453067 PUD 1421e1067 PMD 0
+ Oops: 0000 [#1] PREEMPT SMP
+ ...
+ Pid: 14006, comm: trinity-child6 Not tainted 3.4.0+ #36
+ RIP: vma_resv_map+0x9/0x30
+ ...
+ Process trinity-child6 (pid: 14006, threadinfo ffff8801414e0000, task ffff8801414f26b0)
+ Call Trace:
+ resv_map_put+0xe/0x40
+ hugetlb_reserve_pages+0xa6/0x1d0
+ hugetlb_file_setup+0x102/0x2c0
+ newseg+0x115/0x360
+ ipcget+0x1ce/0x310
+ sys_shmget+0x5a/0x60
+ system_call_fastpath+0x16/0x1b
+
+This was reported by Dave Jones, but was reproducible with the
+libhugetlbfs test cases, so shame on me for not running them in the
+first place.
+
+With this, the oops is gone, and the output of libhugetlbfs's
+run_tests.py is identical to plain 3.4 again.
+
+[ Marked for stable, since this was introduced by commit c50ac050811d
+ ("hugetlb: fix resv_map leak in error path") which was also marked for
+ stable ]
+
+Reported-by: Dave Jones <davej@redhat.com>
+Cc: Mel Gorman <mel@csn.ul.ie>
+Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index f7b8054..c80dd85 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2789,7 +2789,8 @@ int hugetlb_reserve_pages(struct inode *inode,
+ region_add(&inode->i_mapping->private_list, from, to);
+ return 0;
+ out_err:
+- resv_map_put(vma);
++ if (vma)
++ resv_map_put(vma);
+ return ret;
+ }
+
+--
+1.8.1.2
+
diff --git a/queue/series b/queue/series
index 84eae84..a79d709 100644
--- a/queue/series
+++ b/queue/series
@@ -1,3 +1,5 @@
x86-random-make-ARCH_RANDOM-prompt-if-EMBEDDED-not-E.patch
staging-comedi-ni_labpc-correct-differential-channel.patch
staging-comedi-ni_labpc-set-up-command4-register-aft.patch
+hugetlb-fix-resv_map-leak-in-error-path.patch
+mm-fix-vma_resv_map-NULL-pointer.patch