Patchwork [2/6] mm: make the mlock() stack guard page checks stricter

login
register
mail settings
Submitter Paolo Pisati
Date Nov. 24, 2011, 10:07 a.m.
Message ID <1322129246-5397-3-git-send-email-paolo.pisati@canonical.com>
Download mbox | patch
Permalink /patch/127465/
State New
Headers show

Comments

Paolo Pisati - Nov. 24, 2011, 10:07 a.m.
From: Linus Torvalds <torvalds@linux-foundation.org>

commit 7798330ac8114c731cfab83e634c6ecedaa233d7 upstream.

If we've split the stack vma, only the lowest one has the guard page.
Now that we have a doubly linked list of vma's, checking this is trivial.

Tested-by: Ian Campbell <ijc@hellion.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
(cherry picked from commit e89cfc48a21fa83088e083fe6341ff803ab32f8e)

BugLink: http://launchpad.net/bugs/893190

Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 mm/mlock.c |   21 ++++++++++++++++-----
 1 files changed, 16 insertions(+), 5 deletions(-)

Patch

diff --git a/mm/mlock.c b/mm/mlock.c
index 49e5e4c..cbae7c5 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -135,6 +135,19 @@  void munlock_vma_page(struct page *page)
 	}
 }
 
+/* Is the vma a continuation of the stack vma above it? */
+static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
+{
+	return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
+}
+
+static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	return (vma->vm_flags & VM_GROWSDOWN) &&
+		(vma->vm_start == addr) &&
+		!vma_stack_continue(vma->vm_prev, addr);
+}
+
 /**
  * __mlock_vma_pages_range() -  mlock a range of pages in the vma.
  * @vma:   target vma
@@ -168,11 +181,9 @@  static long __mlock_vma_pages_range(struct vm_area_struct *vma,
 		gup_flags |= FOLL_WRITE;
 
 	/* We don't try to access the guard page of a stack vma */
-	if (vma->vm_flags & VM_GROWSDOWN) {
-		if (start == vma->vm_start) {
-			start += PAGE_SIZE;
-			nr_pages--;
-		}
+	if (stack_guard_page(vma, start)) {
+		addr += PAGE_SIZE;
+		nr_pages--;
 	}
 
 	while (nr_pages > 0) {