[kernel] r18923 - in dists/sid/linux-2.6/debian: . patches/bugfix/all patches/series
Ben Hutchings
benh at alioth.debian.org
Fri Apr 13 03:01:35 UTC 2012
Author: benh
Date: Fri Apr 13 03:01:31 2012
New Revision: 18923
Log:
hugetlb: fix race condition in hugetlb_fault()
Added:
dists/sid/linux-2.6/debian/patches/bugfix/all/hugetlb-fix-race-condition-in-hugetlb_fault.patch
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/patches/series/base
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog Mon Apr 9 04:05:34 2012 (r18922)
+++ dists/sid/linux-2.6/debian/changelog Fri Apr 13 03:01:31 2012 (r18923)
@@ -10,6 +10,7 @@
* drm/radeon/kms: fix fans after resume (Closes: #596741)
* [x86] hv: Update all Hyper-V drivers to 3.4-rc1 (Closes: #661318)
* nfs: Fix length of buffer copied in __nfs4_get_acl_uncached
+ * hugetlb: fix race condition in hugetlb_fault()
[ Jonathan Nieder ]
* [x86] ioat: fix size of 'completion' for Xen (Closes: #660554)
Added: dists/sid/linux-2.6/debian/patches/bugfix/all/hugetlb-fix-race-condition-in-hugetlb_fault.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/hugetlb-fix-race-condition-in-hugetlb_fault.patch Fri Apr 13 03:01:31 2012 (r18923)
@@ -0,0 +1,88 @@
+From: Chris Metcalf <cmetcalf at tilera.com>
+Date: Thu, 12 Apr 2012 12:49:15 -0700
+Subject: [PATCH] hugetlb: fix race condition in hugetlb_fault()
+
+commit 66aebce747eaf9bc456bf1f1b217d8db843031d0 upstream.
+
+The race is as follows:
+
+Suppose a multi-threaded task forks a new process (on cpu A), thus
+bumping up the ref count on all the pages. While the fork is occurring
+(and thus we have marked all the PTEs as read-only), another thread in
+the original process (on cpu B) tries to write to a huge page, taking an
+access violation from the write-protect and calling hugetlb_cow(). Now,
+suppose the fork() fails. It will undo the COW and decrement the ref
+count on the pages, so the ref count on the huge page drops back to 1.
+Meanwhile hugetlb_cow() also decrements the ref count by one on the
+original page, since the original address space doesn't need it any
+more, having copied a new page to replace the original page. This
+leaves the ref count at zero, and when we call unlock_page(), we panic.
+
+ fork on CPU A fault on CPU B
+ ============= ==============
+ ...
+ down_write(&parent->mmap_sem);
+ down_write_nested(&child->mmap_sem);
+ ...
+ while duplicating vmas
+ if error
+ break;
+ ...
+ up_write(&child->mmap_sem);
+ up_write(&parent->mmap_sem); ...
+ down_read(&parent->mmap_sem);
+ ...
+ lock_page(page);
+ handle COW
+ page_mapcount(old_page) == 2
+ alloc and prepare new_page
+ ...
+ handle error
+ page_remove_rmap(page);
+ put_page(page);
+ ...
+ fold new_page into pte
+ page_remove_rmap(page);
+ put_page(page);
+ ...
+ oops ==> unlock_page(page);
+ up_read(&parent->mmap_sem);
+
+The solution is to take an extra reference to the page while we are
+holding the lock on it.
+
+Signed-off-by: Chris Metcalf <cmetcalf at tilera.com>
+Cc: Hillf Danton <dhillf at gmail.com>
+Cc: Michal Hocko <mhocko at suse.cz>
+Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
+Cc: Hugh Dickins <hughd at google.com>
+Cc: <stable at vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+ mm/hugetlb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index b8ce6f4..cd65cb1 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2791,6 +2791,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+ * so no worry about deadlock.
+ */
+ page = pte_page(entry);
++ get_page(page);
+ if (page != pagecache_page)
+ lock_page(page);
+
+@@ -2822,6 +2823,7 @@ out_page_table_lock:
+ }
+ if (page != pagecache_page)
+ unlock_page(page);
++ put_page(page);
+
+ out_mutex:
+ mutex_unlock(&hugetlb_instantiation_mutex);
+--
+1.7.9.5
+
Modified: dists/sid/linux-2.6/debian/patches/series/base
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/base Mon Apr 9 04:05:34 2012 (r18922)
+++ dists/sid/linux-2.6/debian/patches/series/base Fri Apr 13 03:01:31 2012 (r18923)
@@ -179,3 +179,4 @@
+ debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch
+ bugfix/all/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncach.patch
++ bugfix/all/hugetlb-fix-race-condition-in-hugetlb_fault.patch
More information about the Kernel-svn-changes
mailing list