mm: fix up some user-visible effects of the stack guard page

This commit makes the stack guard page somewhat less visible to user
space. It does this by:

- not showing the guard page in /proc/<pid>/maps

It looks like lvm-tools will actually read /proc/self/maps to figure
out where all its mappings are, and effectively do a specialized
"mlockall()" in user space. By not showing the guard page as part of
the mapping (by just adding PAGE_SIZE to the start for grows-up
pages), lvm-tools ends up not being aware of it.

- by also teaching the _real_ mlock() functionality not to try to lock
the guard page.

That would just expand the mapping down to create a new guard page,
so there really is no point in trying to lock it in place.

It would perhaps be nice to show the guard page specially in
/proc/<pid>/maps (or at least mark grow-down segments some way), but
let's not open ourselves up to more breakage by user space from programs
that depends on the exact deails of the 'maps' file.

Special thanks to Henrique de Moraes Holschuh for diving into lvm-tools
source code to see what was going on with the whole new warning.

Reported-and-tested-by: François Valenduc <francois.valenduc@tvcablenet.be
Reported-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+15 -1
+7 -1
fs/proc/task_mmu.c
··· 210 int flags = vma->vm_flags; 211 unsigned long ino = 0; 212 unsigned long long pgoff = 0; 213 dev_t dev = 0; 214 int len; 215 ··· 221 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; 222 } 223 224 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", 225 - vma->vm_start, 226 vma->vm_end, 227 flags & VM_READ ? 'r' : '-', 228 flags & VM_WRITE ? 'w' : '-',
··· 210 int flags = vma->vm_flags; 211 unsigned long ino = 0; 212 unsigned long long pgoff = 0; 213 + unsigned long start; 214 dev_t dev = 0; 215 int len; 216 ··· 220 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; 221 } 222 223 + /* We don't show the stack guard page in /proc/maps */ 224 + start = vma->vm_start; 225 + if (vma->vm_flags & VM_GROWSDOWN) 226 + start += PAGE_SIZE; 227 + 228 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", 229 + start, 230 vma->vm_end, 231 flags & VM_READ ? 'r' : '-', 232 flags & VM_WRITE ? 'w' : '-',
+8
mm/mlock.c
··· 167 if (vma->vm_flags & VM_WRITE) 168 gup_flags |= FOLL_WRITE; 169 170 while (nr_pages > 0) { 171 int i; 172
··· 167 if (vma->vm_flags & VM_WRITE) 168 gup_flags |= FOLL_WRITE; 169 170 + /* We don't try to access the guard page of a stack vma */ 171 + if (vma->vm_flags & VM_GROWSDOWN) { 172 + if (start == vma->vm_start) { 173 + start += PAGE_SIZE; 174 + nr_pages--; 175 + } 176 + } 177 + 178 while (nr_pages > 0) { 179 int i; 180