lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu,  1 Apr 2010 12:40:17 +0300
From:	Avi Kivity <avi@...hat.com>
To:	Rik van Riel <riel@...hat.com>, linux-kernel@...r.kernel.org
Cc:	peterz@...radead.org, aarcange@...hat.com,
	akpm@...ux-foundation.org,
	Kent Overstreet <kent.overstreet@...il.com>
Subject: [COUNTERPATCH] mm: avoid overflowing preempt_count() in  mmu_take_all_locks()

mmu_take_all_locks() takes a spinlock for each vma, which means we increase
the preempt count by the number of vmas in an address space.  Since the user
controls the number of vmas, they can cause preempt_count to overflow.

Fix by making mmu_take_all_locks() only disable preemption once by making
the spinlocks preempt-neutral.

Signed-off-by: Avi Kivity <avi@...hat.com>
---
 mm/mmap.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/mm/mmap.c b/mm/mmap.c
index 75557c6..7305510 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2442,6 +2442,12 @@ static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma)
 		 */
 		spin_lock_nest_lock(&anon_vma->lock, &mm->mmap_sem);
 		/*
+		 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+		 * vma preemp_count neutral and instead disable preempt
+		 * once per mmu_take_all_lock().
+		 */
+		preempt_enable();
+		/*
 		 * We can safely modify head.next after taking the
 		 * anon_vma->lock. If some other vma in this mm shares
 		 * the same anon_vma we won't take it again.
@@ -2471,6 +2477,12 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping)
 		if (test_and_set_bit(AS_MM_ALL_LOCKS, &mapping->flags))
 			BUG();
 		spin_lock_nest_lock(&mapping->i_mmap_lock, &mm->mmap_sem);
+		/*
+		 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+		 * vma preemp_count neutral and instead disable preempt
+		 * once per mmu_take_all_lock().
+		 */
+		preempt_enable();
 	}
 }
 
@@ -2516,6 +2528,13 @@ int mm_take_all_locks(struct mm_struct *mm)
 
 	mutex_lock(&mm_all_locks_mutex);
 
+	/*
+	 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+	 * vma preemp_count neutral and instead disable preempt
+	 * once per mmu_take_all_lock().
+	 */
+	preempt_disable();
+
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
 		if (signal_pending(current))
 			goto out_unlock;
@@ -2558,6 +2577,12 @@ static void vm_unlock_anon_vma(struct anon_vma *anon_vma)
 		if (!__test_and_clear_bit(0, (unsigned long *)
 					  &anon_vma->head.next))
 			BUG();
+		/*
+		 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+		 * vma preemp_count neutral and instead disable preempt
+		 * once per mmu_take_all_lock().
+		 */
+		preempt_disable();
 		spin_unlock(&anon_vma->lock);
 	}
 }
@@ -2569,6 +2594,12 @@ static void vm_unlock_mapping(struct address_space *mapping)
 		 * AS_MM_ALL_LOCKS can't change to 0 from under us
 		 * because we hold the mm_all_locks_mutex.
 		 */
+		/*
+		 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+		 * vma preemp_count neutral and instead disable preempt
+		 * once per mmu_take_all_lock().
+		 */
+		preempt_disable();
 		spin_unlock(&mapping->i_mmap_lock);
 		if (!test_and_clear_bit(AS_MM_ALL_LOCKS,
 					&mapping->flags))
@@ -2596,6 +2627,12 @@ void mm_drop_all_locks(struct mm_struct *mm)
 			vm_unlock_mapping(vma->vm_file->f_mapping);
 	}
 
+	/*
+	 * To avoid O(nr_vmas) preempt_disable()s, we keep each
+	 * vma preemp_count neutral and instead disable preempt
+	 * once per mmu_take_all_lock().
+	 */
+	preempt_enable();
 	mutex_unlock(&mm_all_locks_mutex);
 }
 
-- 
1.7.0.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ