[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