From: Greg Kroah-Hartman Date: Thu, 14 Jun 2012 22:44:04 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.0.35~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1c48d79cf795890d7179ce004bb0c2163ad3e51f;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: hugetlb-fix-resv_map-leak-in-error-path.patch --- diff --git a/queue-3.0/hugetlb-fix-resv_map-leak-in-error-path.patch b/queue-3.0/hugetlb-fix-resv_map-leak-in-error-path.patch new file mode 100644 index 00000000000..65bd2513bab --- /dev/null +++ b/queue-3.0/hugetlb-fix-resv_map-leak-in-error-path.patch @@ -0,0 +1,111 @@ +From c50ac050811d6485616a193eb0f37bfbd191cc89 Mon Sep 17 00:00:00 2001 +From: Dave Hansen +Date: Tue, 29 May 2012 15:06:46 -0700 +Subject: hugetlb: fix resv_map leak in error path + +From: Dave Hansen + +commit c50ac050811d6485616a193eb0f37bfbd191cc89 and +4523e1458566a0e8ecfaff90f380dd23acc44d27 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 +Acked-by: Mel Gorman +Acked-by: KOSAKI Motohiro +Reported-by: Christoph Lameter +Tested-by: Christoph Lameter +Cc: Andrea Arcangeli +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + + +--- + mm/hugetlb.c | 29 +++++++++++++++++++++++------ + 1 file changed, 23 insertions(+), 6 deletions(-) + +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2060,6 +2060,15 @@ static void hugetlb_vm_op_open(struct vm + 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); +@@ -2075,7 +2084,7 @@ static void hugetlb_vm_op_close(struct v + 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); +@@ -2877,12 +2886,16 @@ int hugetlb_reserve_pages(struct 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. +@@ -2891,7 +2904,7 @@ int hugetlb_reserve_pages(struct inode * + ret = hugetlb_acct_memory(h, chg); + if (ret < 0) { + hugetlb_put_quota(inode->i_mapping, chg); +- return ret; ++ goto out_err; + } + + /* +@@ -2908,6 +2921,10 @@ int hugetlb_reserve_pages(struct inode * + if (!vma || vma->vm_flags & VM_MAYSHARE) + region_add(&inode->i_mapping->private_list, from, to); + return 0; ++out_err: ++ if (vma) ++ resv_map_put(vma); ++ return ret; + } + + void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) diff --git a/queue-3.0/series b/queue-3.0/series index 4c92d33248c..a3b512ef377 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -17,3 +17,4 @@ fuse-fix-stat-call-on-32-bit-platforms.patch e1000-save-skb-counts-in-tx-to-avoid-cache-misses.patch mm-vmalloc.c-change-void-into-explict-vm_struct.patch mm-fix-faulty-initialization-in-vmalloc_init.patch +hugetlb-fix-resv_map-leak-in-error-path.patch