diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-20 19:39:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-21 11:49:50 -0400 |
commit | 7798330ac8114c731cfab83e634c6ecedaa233d7 (patch) | |
tree | 76c15db91609ad3355add2a6f23823ea27cf920d /mm/mlock.c | |
parent | 297c5eee372478fc32fec5fe8eed711eedb13f3d (diff) |
mm: make the mlock() stack guard page checks stricter
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>
Diffstat (limited to 'mm/mlock.c')
-rw-r--r-- | mm/mlock.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/mm/mlock.c b/mm/mlock.c index 49e5e4cb8232..cbae7c5b9568 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
@@ -135,6 +135,19 @@ void munlock_vma_page(struct page *page) | |||
135 | } | 135 | } |
136 | } | 136 | } |
137 | 137 | ||
138 | /* Is the vma a continuation of the stack vma above it? */ | ||
139 | static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) | ||
140 | { | ||
141 | return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); | ||
142 | } | ||
143 | |||
144 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | ||
145 | { | ||
146 | return (vma->vm_flags & VM_GROWSDOWN) && | ||
147 | (vma->vm_start == addr) && | ||
148 | !vma_stack_continue(vma->vm_prev, addr); | ||
149 | } | ||
150 | |||
138 | /** | 151 | /** |
139 | * __mlock_vma_pages_range() - mlock a range of pages in the vma. | 152 | * __mlock_vma_pages_range() - mlock a range of pages in the vma. |
140 | * @vma: target vma | 153 | * @vma: target vma |
@@ -168,11 +181,9 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, | |||
168 | gup_flags |= FOLL_WRITE; | 181 | gup_flags |= FOLL_WRITE; |
169 | 182 | ||
170 | /* We don't try to access the guard page of a stack vma */ | 183 | /* We don't try to access the guard page of a stack vma */ |
171 | if (vma->vm_flags & VM_GROWSDOWN) { | 184 | if (stack_guard_page(vma, start)) { |
172 | if (start == vma->vm_start) { | 185 | addr += PAGE_SIZE; |
173 | start += PAGE_SIZE; | 186 | nr_pages--; |
174 | nr_pages--; | ||
175 | } | ||
176 | } | 187 | } |
177 | 188 | ||
178 | while (nr_pages > 0) { | 189 | while (nr_pages > 0) { |