diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2013-03-08 09:53:39 -0500 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2013-03-08 09:55:06 -0500 |
commit | e338afcb163ba3a3187f07f1fa750ee82d95912a (patch) | |
tree | dbd027ce2483025b64ba155646f402178f477448 | |
parent | e588bc2c02f28f8d56b5b62a296fa4f2806adb65 (diff) | |
download | longterm-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.patch | 107 | ||||
-rw-r--r-- | queue/mm-fix-vma_resv_map-NULL-pointer.patch | 67 | ||||
-rw-r--r-- | queue/series | 2 |
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 |