New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Security: Multiple flaws relating to stack/heap clash attacks

Project Member Reported by jorgelo@chromium.org, May 18 2017

Issue description

From Kees:

EMBARGOED until Jun 19. Do not discuss outside of Google or work in public repositories.

"
> Attached is a draft advisory from Qualys who have done an extensive
> analysis of how to exploit stack growth vs heap grow attacks against
> suid programs. Nearly all the PoCs are local to root privilege
> escalation, though in theory, it may be possible to perform this
> remotely given a particularly weird program.
>
> The number of flaws used is large, covering the kernel, sudo, su,
> exim, and ld.so.
"

Draft advisory attached to this bug as well.

Next steps: figure out how to enable -fstack-check for affected packages, then extend to the whole system.

Related -fstack-check bug:   issue 485492  .
 
Showing comments 28 - 127 of 127 Older
#18: what needs fixing? It should be possible to communicate directly, but I'll double check.
#28: arch/ia64/mm/fault.c:           if (expand_upwards(vma, address))

Also, it would be useful to know if patches for older kernels are available or in the works.

I haven't seen any mention of backports yet (I assume this contributed to the embargo extension).
Answering #25: CROS_WORKON_ALWAYS_LIVE="1" in the .9999 ebuild does the trick.

For glibc patch in #13, it works fine on different trybots.
Updates from the embargoed list thread. It includes a new fix that was coincidentally fixed in upstream glibc already, but is considered part of the glibc fix.
kernel.patch
15.3 KB Download
ld-library-path-suid.patch
3.9 KB Download
ld-hwcap-mask-suid.patch
1.2 KB Download
#33: kernel.patch appears incomplete (header/description missing). Any chance you can attach a complete version ?

I will rerun the glibc test with updated patches.
#34: that's all that was sent. No header, and I have to add multiple follow-up fixes to it manually. :(
#36: No worries; I re-created the header myself. Did you add the follow-up fixes already, or do you have more ?

As of this morning, all the follow-up fixes I've seen on the thread were incorporated into that patch I attached. (Though it sounds like there are more to come?)
#38: Yes, there is at least one more I am aware of.

Cc: ghackmann@google.com
Cc: andreyu@google.com
The glibc patches in #33 works. (although I need to modify it to make it apply to our glibc 2.23).
After applying the patch in #33, I'm getting some very odd behavior if I map and unmap pages in a specific sequence.  Basically /proc/pid/maps starts claiming that the [stack] VMA's start address is *higher* than its end address.  From the attached test program:

found [stack] in /proc/self/maps: 7ffe35d9d000-7ffe35ebe000 rw-p 00000000 00:00 0                          [stack]
mapped page at 0x7ffe35d9b000
found [stack] in /proc/self/maps: 7ffe35e9c000-7ffe35ebe000 rw-p 00000000 00:00 0                          [stack]
unmapped page at 0x7ffe35d9b000
mapped page at 0x7ffe35e9a000
found [stack] in /proc/self/maps: 7ffe35f9b000-7ffe35ebe000 rw-p 00000000 00:00 0                          [stack]
addr_start = 7ffe35f9b000 > addr_end = 7ffe35ebe000?!?!

Can someone else try this and see if I'm doing something wrong?  I've reproduced this on ToT torvalds built for x86_64 (running on qemu), and android-4.9 built for ARM64 (running on hikey).  Both are running AOSP userspace, but I don't think that should matter.
stack_guard_wtf.c
1.6 KB View Download
Project Member

Comment 44 by sheriffbot@chromium.org, Jun 6 2017

Labels: -M-58 M-59
Okay, I'm not crazy.  The way I was mapping pages split the stack VMA in the middle of the multi-page stack guard.

The lower VMA resulting from the split wasn't printed, due to a check in stack_guard_area().

The upper VMA *was* printed, but the reported lower address was moved up by a hard-coded 1MB ("start += stack_guard_gap" in show_map_vma()) despite the stack guard being split between two VMAs.  In this case I'd split things so the whole VMA was less than 1MB, causing the kernel to report a VMA that ends before it starts.
#43: I can not reproduce the problem with your test application, but maybe I have a different environment. The stack address doesn't seem to change much in my test. Do I maybe need a specific cc or kernel configuration option ?



Comment 47 by andreyu@google.com, Jun 14 2017

Cc: adityakali@google.com
I've updated https://b.corp.google.com/issues/38413813 with the latest proposed kernel patches.
Labels: M-60 Merge-Approved-60
Consider this merge approved for 60 as soon as the embargo is lifted and the changes make it into ToT.
Labels: Merge-Approved-59
Project Member

Comment 51 by sheriffbot@chromium.org, Jun 16 2017

Status: Fixed (was: Assigned)
Please mark security bugs as fixed as soon as the fix lands, and before requesting merges. This update is based on the merge- labels applied to this issue. Please reopen if this update was incorrect.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Project Member

Comment 52 by sheriffbot@chromium.org, Jun 17 2017

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Project Member

Comment 53 by sheriffbot@chromium.org, Jun 19 2017

Cc: bhthompson@google.com gkihumba@google.com
This issue has been approved for a merge. Please merge the fix to any appropriate branches as soon as possible!

If all merges have been completed, please remove any remaining Merge-Approved labels from this issue.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Cc: keescook@chromium.org
Owner: groeck@chromium.org
Status: Started (was: Fixed)
I've attached new kernel patches from over the weekend to https://b.corp.google.com/issues/38413813 along with backports.
Can we upload and push the glibc patch now?
#55: Presumably only after the embargo has been lifted unless you can find the code in public.

Again #55: The linux kernel changes have been published.

glibc patch in #33 are all upstream patches. Given these two patches, do we still need the patch in #13?
Patch in #13 is subsumed into ld-library-path-suid.patch AFAICT.

Embargo has been lifted indeed and advisory is public now here: http://www.openwall.com/lists/oss-security/2017/06/19/1

We're all go for landing patches.


Note that the official upstream fix ended up being entirely different, but does not have as much testing:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1be7107fbe18eed3e319a6c3e83c78254b693acb
#60: I am picking up fixes from -stable release candidates where available.

Project Member

Comment 63 by bugdroid1@chromium.org, Jun 20 2017

Labels: merge-merged-release-R60-9592.B
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4622e34c5bdf25a0ec6810d7266edbf9836ade48

commit 4622e34c5bdf25a0ec6810d7266edbf9836ade48
Author: Yunlian Jiang <yunlian@google.com>
Date: Tue Jun 20 22:21:09 2017

glibc: backport two upstream patches.

This backports two glibc patches include in the #33 of the bug
entry.

BUG=chromium:724093
TEST=cbuildbot chromiumos-sdk falco-release elm-release
     veyron_jaq-release

Previous-Reviewed-on: https://chromium-review.googlesource.com/540067
(cherry picked from commit 441117a8567d751be303918f5a9c93f856902e8d)
Change-Id: I5f706c0ff826a51cc40890b9dc9da4d9b974b31e
Reviewed-on: https://chromium-review.googlesource.com/540831
Reviewed-by: Bernie Thompson <bhthompson@chromium.org>
Reviewed-by: Luis Lozano <llozano@chromium.org>
Commit-Queue: Yunlian Jiang <yunlian@chromium.org>
Tested-by: Yunlian Jiang <yunlian@chromium.org>
Trybot-Ready: Yunlian Jiang <yunlian@chromium.org>

[add] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/files/local/glibc-2.23-ld-hwcap-mask-suid.patch
[add] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/files/local/glibc-2.23-ld-library-path-suid.patch
[rename] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/glibc-2.23-r7.ebuild

Project Member

Comment 64 by bugdroid1@chromium.org, Jun 20 2017

Labels: merge-merged-release-R60-9592.B
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4622e34c5bdf25a0ec6810d7266edbf9836ade48

commit 4622e34c5bdf25a0ec6810d7266edbf9836ade48
Author: Yunlian Jiang <yunlian@google.com>
Date: Tue Jun 20 22:21:09 2017

glibc: backport two upstream patches.

This backports two glibc patches include in the #33 of the bug
entry.

BUG=chromium:724093
TEST=cbuildbot chromiumos-sdk falco-release elm-release
     veyron_jaq-release

Previous-Reviewed-on: https://chromium-review.googlesource.com/540067
(cherry picked from commit 441117a8567d751be303918f5a9c93f856902e8d)
Change-Id: I5f706c0ff826a51cc40890b9dc9da4d9b974b31e
Reviewed-on: https://chromium-review.googlesource.com/540831
Reviewed-by: Bernie Thompson <bhthompson@chromium.org>
Reviewed-by: Luis Lozano <llozano@chromium.org>
Commit-Queue: Yunlian Jiang <yunlian@chromium.org>
Tested-by: Yunlian Jiang <yunlian@chromium.org>
Trybot-Ready: Yunlian Jiang <yunlian@chromium.org>

[add] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/files/local/glibc-2.23-ld-hwcap-mask-suid.patch
[add] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/files/local/glibc-2.23-ld-library-path-suid.patch
[rename] https://crrev.com/4622e34c5bdf25a0ec6810d7266edbf9836ade48/sys-libs/glibc/glibc-2.23-r7.ebuild

Project Member

Comment 65 by bugdroid1@chromium.org, Jun 21 2017

Labels: merge-merged-release-R59-9460.B
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4d93fbcd8a0d7a36f0359e3b48fdb0c2af5ab34b

commit 4d93fbcd8a0d7a36f0359e3b48fdb0c2af5ab34b
Author: Yunlian Jiang <yunlian@google.com>
Date: Wed Jun 21 00:07:34 2017

glibc: backport two upstream patches.

This backports two glibc patches include in the #33 of the bug
entry.

BUG=chromium:724093
TEST=cbuildbot chromiumos-sdk falco-release elm-release
     veyron_jaq-release

Previous-Reviewed-on: https://chromium-review.googlesource.com/540067
(cherry picked from commit 441117a8567d751be303918f5a9c93f856902e8d)

Change-Id: I77dfce1fe6b580ccd02e9f70508b7724fd960460
Reviewed-on: https://chromium-review.googlesource.com/541935
Reviewed-by: Luis Lozano <llozano@chromium.org>
Commit-Queue: Luis Lozano <llozano@chromium.org>
Tested-by: Luis Lozano <llozano@chromium.org>
Trybot-Ready: Luis Lozano <llozano@chromium.org>

[add] https://crrev.com/4d93fbcd8a0d7a36f0359e3b48fdb0c2af5ab34b/sys-libs/glibc/files/local/glibc-2.23-ld-hwcap-mask-suid.patch
[add] https://crrev.com/4d93fbcd8a0d7a36f0359e3b48fdb0c2af5ab34b/sys-libs/glibc/files/local/glibc-2.23-ld-library-path-suid.patch
[rename] https://crrev.com/4d93fbcd8a0d7a36f0359e3b48fdb0c2af5ab34b/sys-libs/glibc/glibc-2.23-r5.ebuild

Project Member

Comment 66 by bugdroid1@chromium.org, Jun 21 2017

Labels: merge-merged-chromeos-3.10
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/35c3601157aa61fe8bc855c3ccbac1f9cb88d98d

commit 35c3601157aa61fe8bc855c3ccbac1f9cb88d98d
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Wed Jun 21 02:30:13 2017

UPSTREAM: mm: Don't count the stack guard page towards RLIMIT_STACK

commit 690eac53daff34169a4d74fc7bfbd388c4896abb upstream.

Commit fee7e49d4514 ("mm: propagate error from stack expansion even for
guard page") made sure that we return the error properly for stack
growth conditions.  It also theorized that counting the guard page
towards the stack limit might break something, but also said "Let's see
if anybody notices".

Somebody did notice.  Apparently android-x86 sets the stack limit very
close to the limit indeed, and including the guard page in the rlimit
check causes the android 'zygote' process problems.

So this adds the (fairly trivial) code to make the stack rlimit check be
against the actual real stack size, rather than the size of the vma that
includes the guard page.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I28e215b13cfdf35a2ae7cda9c4131abec40b770e
Reported-and-tested-by: Chih-Wei Huang <cwhuang@android-x86.org>
Cc: Jay Foad <jay.foad@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 7d702b4b2b0f1)
Reviewed-on: https://chromium-review.googlesource.com/540055
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/35c3601157aa61fe8bc855c3ccbac1f9cb88d98d/mm/mmap.c

Project Member

Comment 67 by bugdroid1@chromium.org, Jun 21 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/6e14b4cf04c068db1dcc77a86206fd8a98961f74

commit 6e14b4cf04c068db1dcc77a86206fd8a98961f74
Author: Hugh Dickins <hughd@google.com>
Date: Wed Jun 21 02:30:15 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie59d153b2515e70a8c3feb07fb6760aeb8e273bf
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
Conflicts:
   mm/memory.c
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1c64738f7b84e975a560c34c9040764b1419eed8,
 git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/540058
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/include/linux/mm.h
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/mips/mm/mmap.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/mm/mmap.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/fs/hugetlbfs/inode.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/powerpc/mm/slice.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/sh/mm/mmap.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/arm/mm/mmap.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/fs/proc/task_mmu.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/Documentation/kernel-parameters.txt
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/arc/mm/mmap.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/mm/memory.c
[modify] https://crrev.com/6e14b4cf04c068db1dcc77a86206fd8a98961f74/arch/frv/mm/elf-fdpic.c

Project Member

Comment 68 by bugdroid1@chromium.org, Jun 21 2017

Labels: merge-merged-chromeos-3.10
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/32526279211718379f3bee8ab94cfe2f4f303984

commit 32526279211718379f3bee8ab94cfe2f4f303984
Author: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Date: Wed Jun 21 02:30:14 2017

UPSTREAM: mm: ensure get_unmapped_area() returns higher address than mmap_min_addr

commit 2afc745f3e3079ab16c826be4860da2529054dd2 upstream.

This patch fixes the problem that get_unmapped_area() can return illegal
address and result in failing mmap(2) etc.

In case that the address higher than PAGE_SIZE is set to
/proc/sys/vm/mmap_min_addr, the address lower than mmap_min_addr can be
returned by get_unmapped_area(), even if you do not pass any virtual
address hint (i.e.  the second argument).

This is because the current get_unmapped_area() code does not take into
account mmap_min_addr.

This leads to two actual problems as follows:

1. mmap(2) can fail with EPERM on the process without CAP_SYS_RAWIO,
   although any illegal parameter is not passed.

2. The bottom-up search path after the top-down search might not work in
   arch_get_unmapped_area_topdown().

Note: The first and third chunk of my patch, which changes "len" check,
are for more precise check using mmap_min_addr, and not for solving the
above problem.

[How to reproduce]

	--- test.c -------------------------------------------------
	#include <stdio.h>
	#include <unistd.h>
	#include <sys/mman.h>
	#include <sys/errno.h>

	int main(int argc, char *argv[])
	{
		void *ret = NULL, *last_map;
		size_t pagesize = sysconf(_SC_PAGESIZE);

		do {
			last_map = ret;
			ret = mmap(0, pagesize, PROT_NONE,
				MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
	//		printf("ret=%p\n", ret);
		} while (ret != MAP_FAILED);

		if (errno != ENOMEM) {
			printf("ERR: unexpected errno: %d (last map=%p)\n",
			errno, last_map);
		}

		return 0;
	}
	---------------------------------------------------------------

	$ gcc -m32 -o test test.c
	$ sudo sysctl -w vm.mmap_min_addr=65536
	vm.mmap_min_addr = 65536
	$ ./test  (run as non-priviledge user)
	ERR: unexpected errno: 1 (last map=0x10000)

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Id3aa0dc0d6a9371b3082461b92edf3ea6a7dd1f6
Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 3cbafaa72d3afc4a4177f0d76178cd26a525589b)
Reviewed-on: https://chromium-review.googlesource.com/541596
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/32526279211718379f3bee8ab94cfe2f4f303984/mm/mmap.c

Project Member

Comment 69 by bugdroid1@chromium.org, Jun 21 2017

Labels: merge-merged-chromeos-4.4
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/ed885074942501a379487c5d91db412412f5ded0

commit ed885074942501a379487c5d91db412412f5ded0
Author: Hugh Dickins <hughd@google.com>
Date: Wed Jun 21 02:30:21 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie29dd7e16a4e6b038d272ead44bc89906357a74e
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Conflicts:
   Documentation/kernel-parameters.txt
   arch/arc/mm/mmap.c
   arch/arm/mm/mmap.c
   arch/frv/mm/elf-fdpic.c
   arch/mips/mm/mmap.c
   arch/parisc/kernel/sys_parisc.c
   arch/powerpc/mm/slice.c
   arch/s390/mm/mmap.c
   arch/sh/mm/mmap.c
   arch/sparc/kernel/sys_sparc_64.c
   arch/sparc/mm/hugetlbpage.c
   arch/tile/mm/hugetlbpage.c
   arch/x86/kernel/sys_x86_64.c
   arch/x86/mm/hugetlbpage.c
   arch/xtensa/kernel/syscall.c
   fs/hugetlbfs/inode.c
   fs/proc/task_mmu.c
   include/linux/mm.h
   mm/gup.c
   mm/memory.c
   mm/mmap.c
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 87422f5b9b4f)
Reviewed-on: https://chromium-review.googlesource.com/539995
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/include/linux/mm.h
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/mips/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/mm/gup.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/fs/hugetlbfs/inode.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/s390/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/powerpc/mm/slice.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/sh/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/arm/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/fs/proc/task_mmu.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/Documentation/kernel-parameters.txt
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/arc/mm/mmap.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/mm/memory.c
[modify] https://crrev.com/ed885074942501a379487c5d91db412412f5ded0/arch/frv/mm/elf-fdpic.c

Project Member

Comment 70 by bugdroid1@chromium.org, Jun 21 2017

Labels: merge-merged-chromeos-3.14
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4699b5a32cc81a833f3c6483c6663db054765c52

commit 4699b5a32cc81a833f3c6483c6663db054765c52
Author: Hugh Dickins <hughd@google.com>
Date: Wed Jun 21 04:56:56 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie59d153b2515e70a8c3feb07fb6760aeb8e273bf
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1c64738f7b84e975a560c34c9040764b1419eed8)
Reviewed-on: https://chromium-review.googlesource.com/540119
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/include/linux/mm.h
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/mips/mm/mmap.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/mm/mmap.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/fs/hugetlbfs/inode.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/powerpc/mm/slice.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/sh/mm/mmap.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/arm/mm/mmap.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/fs/proc/task_mmu.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/Documentation/kernel-parameters.txt
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/arc/mm/mmap.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/mm/memory.c
[modify] https://crrev.com/4699b5a32cc81a833f3c6483c6663db054765c52/arch/frv/mm/elf-fdpic.c

glibc change has been merged into M59 and M60.
I can't see the 3.18 kernel CL, did that land Guenter?
#72: I am having trouble with chromeos-3.18; Android doesn't start. It looks like
the fix may interfer with our local changes in the same files. Also, 3.18.y (stable) includes various mm related fixes which are not in our tree. Still testing.

Note that the version for chromeos-3.10 may require an update; it is still
under discussion upstream.

Project Member

Comment 74 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4a14977c3eaa4679a5a3f97a89127f960d4468d9

commit 4a14977c3eaa4679a5a3f97a89127f960d4468d9
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jun 22 01:48:10 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7feb5d461a6af3755955401314bd9c37e0988d55
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
Reviewed-on: https://chromium-review.googlesource.com/543668
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/4a14977c3eaa4679a5a3f97a89127f960d4468d9/mm/mmap.c

Project Member

Comment 75 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/119dbb0d958e3802f11fc1dc009940ada631573a

commit 119dbb0d958e3802f11fc1dc009940ada631573a
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jun 22 01:48:07 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7feb5d461a6af3755955401314bd9c37e0988d55
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
Reviewed-on: https://chromium-review.googlesource.com/543669
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/119dbb0d958e3802f11fc1dc009940ada631573a/mm/mmap.c

Project Member

Comment 76 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/a3feb3ffde82233356275801763518231b156e82

commit a3feb3ffde82233356275801763518231b156e82
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jun 22 01:48:03 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7feb5d461a6af3755955401314bd9c37e0988d55
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
Reviewed-on: https://chromium-review.googlesource.com/543442
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/a3feb3ffde82233356275801763518231b156e82/mm/mmap.c

Project Member

Comment 77 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e4f915693c77e3e87ee6a5b76f0acb669a821178

commit e4f915693c77e3e87ee6a5b76f0acb669a821178
Author: Guenter Roeck <groeck@chromium.org>
Date: Thu Jun 22 03:44:38 2017

Revert "UPSTREAM: mm: fix new crash in unmapped_area_topdown()"

This reverts commit 4a14977c3eaa4679a5a3f97a89127f960d4468d9.

Reason for revert: Causes ARC+ failures.

Original change's description:
> UPSTREAM: mm: fix new crash in unmapped_area_topdown()
> 
> Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
> mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
> end of unmapped_area_topdown().  Linus points out how MAP_FIXED
> (which does not have to respect our stack guard gap intentions)
> could result in gap_end below gap_start there.  Fix that, and
> the similar case in its alternative, unmapped_area().
> 
> BUG=chromium:726072, chromium:724093
> TEST=Build and run
> 
> Change-Id: I7feb5d461a6af3755955401314bd9c37e0988d55
> Cc: stable@vger.kernel.org
> Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
> Reported-by: Dave Jones <davej@codemonkey.org.uk>
> Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> Acked-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> (cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
> Reviewed-on: https://chromium-review.googlesource.com/543668
> Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

Bug: chromium:726072, chromium:724093
Change-Id: I16a4a99dd27b8c3d4db3b737c6b218654d98a6b4
Reviewed-on: https://chromium-review.googlesource.com/544705
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Commit-Queue: Guenter Roeck <groeck@chromium.org>
Tested-by: Guenter Roeck <groeck@chromium.org>

[modify] https://crrev.com/e4f915693c77e3e87ee6a5b76f0acb669a821178/mm/mmap.c

Project Member

Comment 78 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/2d911696496162677a3c4c3fcd03013b644c2122

commit 2d911696496162677a3c4c3fcd03013b644c2122
Author: Guenter Roeck <groeck@chromium.org>
Date: Thu Jun 22 03:47:12 2017

Revert "UPSTREAM: mm: larger stack guard gap, between vmas"

This reverts commit 4699b5a32cc81a833f3c6483c6663db054765c52.

Reason for revert: Causes problems with ARC+ (crashes)

Original change's description:
> UPSTREAM: mm: larger stack guard gap, between vmas
> 
> commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.
> 
> Stack guard page is a useful feature to reduce a risk of stack smashing
> into a different mapping. We have been using a single page gap which
> is sufficient to prevent having stack adjacent to a different mapping.
> But this seems to be insufficient in the light of the stack usage in
> userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
> used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
> which is 256kB or stack strings with MAX_ARG_STRLEN.
> 
> This will become especially dangerous for suid binaries and the default
> no limit for the stack size limit because those applications can be
> tricked to consume a large portion of the stack and a single glibc call
> could jump over the guard page. These attacks are not theoretical,
> unfortunatelly.
> 
> Make those attacks less probable by increasing the stack guard gap
> to 1MB (on systems with 4k pages; but make it depend on the page size
> because systems with larger base pages might cap stack allocations in
> the PAGE_SIZE units) which should cover larger alloca() and VLA stack
> allocations. It is obviously not a full fix because the problem is
> somehow inherent, but it should reduce attack space a lot.
> 
> One could argue that the gap size should be configurable from userspace,
> but that can be done later when somebody finds that the new 1MB is wrong
> for some special case applications.  For now, add a kernel command line
> option (stack_guard_gap) to specify the stack gap size (in page units).
> 
> Implementation wise, first delete all the old code for stack guard page:
> because although we could get away with accounting one extra page in a
> stack vma, accounting a larger gap can break userspace - case in point,
> a program run with "ulimit -S -v 20000" failed when the 1MB gap was
> counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
> and strict non-overcommit mode.
> 
> Instead of keeping gap inside the stack vma, maintain the stack guard
> gap as a gap between vmas: using vm_start_gap() in place of vm_start
> (or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
> places which need to respect the gap - mainly arch_get_unmapped_area(),
> and and the vma tree's subtree_gap support for that.
> 
> BUG=chromium:726072, chromium:724093
> TEST=Build and run
> 
> Change-Id: Ie59d153b2515e70a8c3feb07fb6760aeb8e273bf
> Original-patch-by: Oleg Nesterov <oleg@redhat.com>
> Original-patch-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> [wt: backport to 4.11: adjust context]
> [wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
> [wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
> [wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
>      s390 uses generic arch_get_unmapped_area()]
> [wt: backport to 3.16: adjust context]
> [wt: backport to 3.10: adjust context ; code logic in PARISC's
>      arch_get_unmapped_area() wasn't found ; code inserted into
>      expand_upwards() and expand_downwards() runs under anon_vma lock;
>      changes for gup.c:faultin_page go to memory.c:__get_user_pages()]
> Signed-off-by: Willy Tarreau <w@1wt.eu>
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> (cherry picked from commit 1c64738f7b84e975a560c34c9040764b1419eed8)
> Reviewed-on: https://chromium-review.googlesource.com/540119
> Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

Bug: chromium:726072, chromium:724093
Change-Id: I0743d75ed28b4b4bb89d88b83113b828b295e488
Reviewed-on: https://chromium-review.googlesource.com/544706
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Commit-Queue: Guenter Roeck <groeck@chromium.org>
Tested-by: Guenter Roeck <groeck@chromium.org>

[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/include/linux/mm.h
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/mips/mm/mmap.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/mm/mmap.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/fs/hugetlbfs/inode.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/powerpc/mm/slice.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/sh/mm/mmap.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/arm/mm/mmap.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/fs/proc/task_mmu.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/Documentation/kernel-parameters.txt
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/arc/mm/mmap.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/mm/memory.c
[modify] https://crrev.com/2d911696496162677a3c4c3fcd03013b644c2122/arch/frv/mm/elf-fdpic.c

Project Member

Comment 79 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/bcc77b6af4353ff2d4bde9b1393420e94309186b

commit bcc77b6af4353ff2d4bde9b1393420e94309186b
Author: Guenter Roeck <groeck@chromium.org>
Date: Thu Jun 22 03:48:35 2017

Revert "UPSTREAM: mm: fix new crash in unmapped_area_topdown()"

This reverts commit 119dbb0d958e3802f11fc1dc009940ada631573a.

Reason for revert: Causes problems (crashes) with ARC+

Original change's description:
> UPSTREAM: mm: fix new crash in unmapped_area_topdown()
> 
> Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
> mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
> end of unmapped_area_topdown().  Linus points out how MAP_FIXED
> (which does not have to respect our stack guard gap intentions)
> could result in gap_end below gap_start there.  Fix that, and
> the similar case in its alternative, unmapped_area().
> 
> BUG=chromium:726072, chromium:724093
> TEST=Build and run
> 
> Change-Id: I7feb5d461a6af3755955401314bd9c37e0988d55
> Cc: stable@vger.kernel.org
> Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
> Reported-by: Dave Jones <davej@codemonkey.org.uk>
> Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> Acked-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> (cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
> Reviewed-on: https://chromium-review.googlesource.com/543669
> Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

Bug: chromium:726072, chromium:724093
Change-Id: I5b04cb001950c53f276dfad8b3e1a64bf2aef6b7
Reviewed-on: https://chromium-review.googlesource.com/544707
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Commit-Queue: Guenter Roeck <groeck@chromium.org>
Tested-by: Guenter Roeck <groeck@chromium.org>

[modify] https://crrev.com/bcc77b6af4353ff2d4bde9b1393420e94309186b/mm/mmap.c

Project Member

Comment 80 by bugdroid1@chromium.org, Jun 22 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/088e4715a1dede9330532061ebd05fee7983e0ff

commit 088e4715a1dede9330532061ebd05fee7983e0ff
Author: Guenter Roeck <groeck@chromium.org>
Date: Thu Jun 22 03:51:47 2017

Revert "BACKPORT: mm: larger stack guard gap, between vmas"

This reverts commit 6e14b4cf04c068db1dcc77a86206fd8a98961f74.

Reason for revert: Causes ARC+ crashes

Original change's description:
> BACKPORT: mm: larger stack guard gap, between vmas
> 
> commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.
> 
> Stack guard page is a useful feature to reduce a risk of stack smashing
> into a different mapping. We have been using a single page gap which
> is sufficient to prevent having stack adjacent to a different mapping.
> But this seems to be insufficient in the light of the stack usage in
> userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
> used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
> which is 256kB or stack strings with MAX_ARG_STRLEN.
> 
> This will become especially dangerous for suid binaries and the default
> no limit for the stack size limit because those applications can be
> tricked to consume a large portion of the stack and a single glibc call
> could jump over the guard page. These attacks are not theoretical,
> unfortunatelly.
> 
> Make those attacks less probable by increasing the stack guard gap
> to 1MB (on systems with 4k pages; but make it depend on the page size
> because systems with larger base pages might cap stack allocations in
> the PAGE_SIZE units) which should cover larger alloca() and VLA stack
> allocations. It is obviously not a full fix because the problem is
> somehow inherent, but it should reduce attack space a lot.
> 
> One could argue that the gap size should be configurable from userspace,
> but that can be done later when somebody finds that the new 1MB is wrong
> for some special case applications.  For now, add a kernel command line
> option (stack_guard_gap) to specify the stack gap size (in page units).
> 
> Implementation wise, first delete all the old code for stack guard page:
> because although we could get away with accounting one extra page in a
> stack vma, accounting a larger gap can break userspace - case in point,
> a program run with "ulimit -S -v 20000" failed when the 1MB gap was
> counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
> and strict non-overcommit mode.
> 
> Instead of keeping gap inside the stack vma, maintain the stack guard
> gap as a gap between vmas: using vm_start_gap() in place of vm_start
> (or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
> places which need to respect the gap - mainly arch_get_unmapped_area(),
> and and the vma tree's subtree_gap support for that.
> 
> BUG=chromium:726072, chromium:724093
> TEST=Build and run
> 
> Change-Id: Ie59d153b2515e70a8c3feb07fb6760aeb8e273bf
> Original-patch-by: Oleg Nesterov <oleg@redhat.com>
> Original-patch-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> [wt: backport to 4.11: adjust context]
> [wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
> [wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
> [wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
>      s390 uses generic arch_get_unmapped_area()]
> [wt: backport to 3.16: adjust context]
> [wt: backport to 3.10: adjust context ; code logic in PARISC's
>      arch_get_unmapped_area() wasn't found ; code inserted into
>      expand_upwards() and expand_downwards() runs under anon_vma lock;
>      changes for gup.c:faultin_page go to memory.c:__get_user_pages()]
> Signed-off-by: Willy Tarreau <w@1wt.eu>
> Conflicts:
>    mm/memory.c
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> (cherry picked from commit 1c64738f7b84e975a560c34c9040764b1419eed8,
>  git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/linux-stable.git)
> Reviewed-on: https://chromium-review.googlesource.com/540058
> Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

Bug: chromium:726072, chromium:724093
Change-Id: Id18f78e45b0232ab3fb83309c31813cad7420cce
Reviewed-on: https://chromium-review.googlesource.com/544710
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Commit-Queue: Guenter Roeck <groeck@chromium.org>
Tested-by: Guenter Roeck <groeck@chromium.org>

[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/include/linux/mm.h
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/mips/mm/mmap.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/mm/mmap.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/fs/hugetlbfs/inode.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/powerpc/mm/slice.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/sh/mm/mmap.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/arm/mm/mmap.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/fs/proc/task_mmu.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/Documentation/kernel-parameters.txt
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/arc/mm/mmap.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/mm/memory.c
[modify] https://crrev.com/088e4715a1dede9330532061ebd05fee7983e0ff/arch/frv/mm/elf-fdpic.c

Project Member

Comment 81 by sheriffbot@chromium.org, Jun 23 2017

This issue has been approved for a merge. Please merge the fix to any appropriate branches as soon as possible!

If all merges have been completed, please remove any remaining Merge-Approved labels from this issue.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Kees and other security experts: does the glibc patches provide sufficient protection for this CVE? It seems that kernel fixes are going to take longer and we ('lakitu' board - Container-Optimized OS for GCP) need to decide whether to wait until all fixes or make a release now with glibc fixes that users can roll out immediately?

What would you recommend?

Thanks.
Re comment #82: The glibc fix isn't sufficient. Any setuid/setcap binary that can be launched by an attacker is potentially vulnerable. The glibc patch just fixes a generic exploit that works for most (any?) vulnerable privileged binary. The Qualys advisory contains other exploits against specific privileged binaries (such as sudo).
Cc: edjee@google.com
Yup, #83 is correct: glibc fix isn't sufficient.

Are there still problems with the upstream patches?

1be7107fbe18eed3e319a6c3e83c78254b693acb
f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89
bd726c90b6b8ce87602208701b208a208e6d5600
#85: See b/62952017.

ARM compiler team is asking me if we need any compiler changes for this. 
Is it ok if I say we dont need compiler changes for now? 
Re #87: I think that's fair.

On a related note: In the long run, it'd be useful to explore ways for the compiler to reliably prevent stack operations ending up manipulating heap memory (instead of relying on the kernel to set up a "large enough" gap). There's GCC's -fstack-check that mitigates a large subset of the problem, but it might be useful to figure out whether we can do something to eradicate this type of attack once and for all...
Project Member

Comment 89 by bugdroid1@chromium.org, Jun 30 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0

commit 3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0
Author: Johannes Weiner <hannes@cmpxchg.org>
Date: Fri Jun 30 06:41:08 2017

BACKPORT: proc: revert /proc/<pid>/maps [stack:TID] annotation

[ Upstream commit 65376df582174ffcec9e6471bf5b0dd79ba05e4a ]

Commit b76437579d13 ("procfs: mark thread stack correctly in
proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps.

Finding the task of a stack VMA requires walking the entire thread list,
turning this into quadratic behavior: a thousand threads means a
thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a
million combinations.

The cost is not in proportion to the usefulness as described in the
patch.

Drop the [stack:TID] annotation to make /proc/<pid>/maps (and
/proc/<pid>/numa_maps) usable again for higher thread counts.

The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as
identifying the stack VMA there is an O(1) operation.

Siddesh said:
 "The end users needed a way to identify thread stacks programmatically and
  there wasn't a way to do that.  I'm afraid I no longer remember (or have
  access to the resources that would aid my memory since I changed
  employers) the details of their requirement.  However, I did do this on my
  own time because I thought it was an interesting project for me and nobody
  really gave any feedback then as to its utility, so as far as I am
  concerned you could roll back the main thread maps information since the
  information is available in the thread-specific files"

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7bb9730dab3aff9d53e35bd27eef19eb5b4b9ad5
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
Cc: Shaohua Li <shli@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[groeck: Fix conflicts in fs/proc/task_mmu.c, caused by commit 586278d78bfa
 ("mm: add a field to store names for private anonymous memory")
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f3de8fbe2a2a3ec4c612e2e0ddeee68f9c5bd972,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545096
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0/include/linux/mm.h
[modify] https://crrev.com/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0/fs/proc/task_mmu.c
[modify] https://crrev.com/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0/Documentation/filesystems/proc.txt
[modify] https://crrev.com/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0/fs/proc/task_nommu.c
[modify] https://crrev.com/3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0/mm/util.c

Project Member

Comment 90 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4

commit 8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:22 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

CQ-DEPEND=CL:559932
Change-Id: Icb104d67a71d5bcfc0918d15b89fad13d286c147
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages();
     included Hugh Dickins' fixes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[groeck: Backport; minor context changes]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1ad9a25dd06f,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/559930
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/include/linux/mm.h
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/mips/mm/mmap.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/mm/mmap.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/fs/hugetlbfs/inode.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/powerpc/mm/slice.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/sh/mm/mmap.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/arm/mm/mmap.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/fs/proc/task_mmu.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/Documentation/kernel-parameters.txt
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/arc/mm/mmap.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/mm/memory.c
[modify] https://crrev.com/8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4/arch/frv/mm/elf-fdpic.c

Project Member

Comment 91 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/71c7596b284997d55e88cf18da07b5a9cfb58f35

commit 71c7596b284997d55e88cf18da07b5a9cfb58f35
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:23 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

Change-Id: If5c4687962ef5f626d86c603144931a7403e115d
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 28ebf89579a0,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/559931
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/71c7596b284997d55e88cf18da07b5a9cfb58f35/mm/mmap.c

Project Member

Comment 92 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/3c2f4706a9304f9723a85c935c540eaa088f5a43

commit 3c2f4706a9304f9723a85c935c540eaa088f5a43
Author: Greg Hackmann <ghackmann@google.com>
Date: Thu Jul 06 01:50:24 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/559932
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/3c2f4706a9304f9723a85c935c540eaa088f5a43/arch/x86/mm/fault.c

Project Member

Comment 93 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/44b0c157700e612aed07ca5a35260cf385990f75

commit 44b0c157700e612aed07ca5a35260cf385990f75
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:14 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

CQ-DEPEND=CL:556052
BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I483e3136829e7a95cd7b1fbad17a9c0f1dc24a3a
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[gkh: minor build fixes for 4.4]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 4b359430674c,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545097
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/include/linux/mm.h
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/mips/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/mm/gup.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/fs/hugetlbfs/inode.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/s390/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/powerpc/mm/slice.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/sh/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/arm/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/fs/proc/task_mmu.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/Documentation/kernel-parameters.txt
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/arc/mm/mmap.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/mm/memory.c
[modify] https://crrev.com/44b0c157700e612aed07ca5a35260cf385990f75/arch/frv/mm/elf-fdpic.c

Project Member

Comment 94 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/6beb2f0524fdf3535400ec21036ef71c0ef43f32

commit 6beb2f0524fdf3535400ec21036ef71c0ef43f32
Author: Helge Deller <deller@gmx.de>
Date: Thu Jul 06 01:50:16 2017

UPSTREAM: Allow stack to grow up to address space limit

commit bd726c90b6b8ce87602208701b208a208e6d5600 upstream.

Fix expand_upwards() on architectures with an upward-growing stack (parisc,
metag and partly IA-64) to allow the stack to reliably grow exactly up to
the address space limit given by TASK_SIZE.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I23629e4e5f8eb2c1fd848f26714f92a8579f224e
Signed-off-by: Helge Deller <deller@gmx.de>
Acked-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f41512c6acb7,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545098
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/6beb2f0524fdf3535400ec21036ef71c0ef43f32/mm/mmap.c

Project Member

Comment 95 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/2dd361385e91df1d33e208e35708a9150684ab1f

commit 2dd361385e91df1d33e208e35708a9150684ab1f
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:17 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ib30cb5cb70c80f7186caf63f7ac1def7ded76e8b
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1f2284fac218,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545099
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/2dd361385e91df1d33e208e35708a9150684ab1f/mm/mmap.c

Project Member

Comment 96 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/c54f22922b38591032ce97e278007046e31047a7

commit c54f22922b38591032ce97e278007046e31047a7
Author: Greg Hackmann <ghackmann@google.com>
Date: Thu Jul 06 01:50:18 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/556052
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/c54f22922b38591032ce97e278007046e31047a7/arch/x86/mm/fault.c

Project Member

Comment 97 by bugdroid1@chromium.org, Jul 6 2017

Labels: merge-merged-chromeos-3.18
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/85e7c1e19a08d79e3e680af8f7dcb6b615557942

commit 85e7c1e19a08d79e3e680af8f7dcb6b615557942
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:19 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

CQ-DEPEND=CL:549182
BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie908315957f5036bab4aca4896a9c6f8420861c0
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[gkh: minor build fixes for 3.18]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[groeck: Fixed conflicts (mm/memory.c mm/mmap.c) seen due to missing
	 changes compared to 3.18.y]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit b1fd03c625eb,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git)
Reviewed-on: https://chromium-review.googlesource.com/539978
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/include/linux/mm.h
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/mips/mm/mmap.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/mm/mmap.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/mm/gup.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/fs/hugetlbfs/inode.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/powerpc/mm/slice.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/sh/mm/mmap.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/arm/mm/mmap.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/fs/proc/task_mmu.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/Documentation/kernel-parameters.txt
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/arc/mm/mmap.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/mm/memory.c
[modify] https://crrev.com/85e7c1e19a08d79e3e680af8f7dcb6b615557942/arch/frv/mm/elf-fdpic.c

Project Member

Comment 98 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/a936c044f9084f6a5dc0642076b325c396412a6b

commit a936c044f9084f6a5dc0642076b325c396412a6b
Author: Greg Hackmann <ghackmann@google.com>
Date: Thu Jul 06 01:50:21 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/549182
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/a936c044f9084f6a5dc0642076b325c396412a6b/arch/x86/mm/fault.c

Project Member

Comment 99 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e16e994e6b0e96187530228ad22a87758dd628eb

commit e16e994e6b0e96187530228ad22a87758dd628eb
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 04:54:44 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

CQ-DEPEND=CL:557932
Change-Id: I09201def44e81686facd7d8333146336b49f84e1
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages();
     included Hugh Dickins' fixes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1ad9a25dd06f,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/557930
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/include/linux/mm.h
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/mips/mm/mmap.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/mm/mmap.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/fs/hugetlbfs/inode.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/powerpc/mm/slice.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/sh/mm/mmap.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/arm/mm/mmap.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/fs/proc/task_mmu.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/Documentation/kernel-parameters.txt
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/arc/mm/mmap.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/mm/memory.c
[modify] https://crrev.com/e16e994e6b0e96187530228ad22a87758dd628eb/arch/frv/mm/elf-fdpic.c

Project Member

Comment 100 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e0aa322a8fac4856cb22083c550ccbafc8b2bb56

commit e0aa322a8fac4856cb22083c550ccbafc8b2bb56
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 04:54:45 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

Change-Id: I573cce18919ce07a68cd1390d2159fb5447cfcb9
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 28ebf89579a0,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/557931
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/e0aa322a8fac4856cb22083c550ccbafc8b2bb56/mm/mmap.c

Project Member

Comment 101 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/11f0ee346e03a269cb386cbfb3ebc4df658a3446

commit 11f0ee346e03a269cb386cbfb3ebc4df658a3446
Author: Greg Hackmann <ghackmann@google.com>
Date: Thu Jul 06 04:54:46 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/557932
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/11f0ee346e03a269cb386cbfb3ebc4df658a3446/arch/x86/mm/fault.c

Issue 739680 has been merged into this issue.
Project Member

Comment 103 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/d0377baafd501a9622f06fb09b603b39178ff620

commit d0377baafd501a9622f06fb09b603b39178ff620
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 01:50:20 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie034fdee219fdf012da5ff062711ed7610320f8c
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
Reviewed-on: https://chromium-review.googlesource.com/543975
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>

[modify] https://crrev.com/d0377baafd501a9622f06fb09b603b39178ff620/mm/mmap.c

Project Member

Comment 104 by bugdroid1@chromium.org, Jul 6 2017

Labels: merge-merged-release-R60-9592.B-chromeos-3.10
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/5db63f849cd8ab86dd18c905c6fc5d8cb3d4602e

commit 5db63f849cd8ab86dd18c905c6fc5d8cb3d4602e
Author: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Date: Thu Jul 06 17:54:38 2017

UPSTREAM: mm: ensure get_unmapped_area() returns higher address than mmap_min_addr

commit 2afc745f3e3079ab16c826be4860da2529054dd2 upstream.

This patch fixes the problem that get_unmapped_area() can return illegal
address and result in failing mmap(2) etc.

In case that the address higher than PAGE_SIZE is set to
/proc/sys/vm/mmap_min_addr, the address lower than mmap_min_addr can be
returned by get_unmapped_area(), even if you do not pass any virtual
address hint (i.e.  the second argument).

This is because the current get_unmapped_area() code does not take into
account mmap_min_addr.

This leads to two actual problems as follows:

1. mmap(2) can fail with EPERM on the process without CAP_SYS_RAWIO,
   although any illegal parameter is not passed.

2. The bottom-up search path after the top-down search might not work in
   arch_get_unmapped_area_topdown().

Note: The first and third chunk of my patch, which changes "len" check,
are for more precise check using mmap_min_addr, and not for solving the
above problem.

[How to reproduce]

	--- test.c -------------------------------------------------
	#include <stdio.h>
	#include <unistd.h>
	#include <sys/mman.h>
	#include <sys/errno.h>

	int main(int argc, char *argv[])
	{
		void *ret = NULL, *last_map;
		size_t pagesize = sysconf(_SC_PAGESIZE);

		do {
			last_map = ret;
			ret = mmap(0, pagesize, PROT_NONE,
				MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
	//		printf("ret=%p\n", ret);
		} while (ret != MAP_FAILED);

		if (errno != ENOMEM) {
			printf("ERR: unexpected errno: %d (last map=%p)\n",
			errno, last_map);
		}

		return 0;
	}
	---------------------------------------------------------------

	$ gcc -m32 -o test test.c
	$ sudo sysctl -w vm.mmap_min_addr=65536
	vm.mmap_min_addr = 65536
	$ ./test  (run as non-priviledge user)
	ERR: unexpected errno: 1 (last map=0x10000)

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Id3aa0dc0d6a9371b3082461b92edf3ea6a7dd1f6
Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 3cbafaa72d3afc4a4177f0d76178cd26a525589b)
Reviewed-on: https://chromium-review.googlesource.com/541596
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 32526279211718379f3bee8ab94cfe2f4f303984)
Reviewed-on: https://chromium-review.googlesource.com/561969

[modify] https://crrev.com/5db63f849cd8ab86dd18c905c6fc5d8cb3d4602e/mm/mmap.c

Project Member

Comment 105 by bugdroid1@chromium.org, Jul 6 2017

Labels: merge-merged-release-R60-9592.B-chromeos-4.4
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/91f30d3bfb703f6df8aca6adf878b1484bb56f93

commit 91f30d3bfb703f6df8aca6adf878b1484bb56f93
Author: Johannes Weiner <hannes@cmpxchg.org>
Date: Thu Jul 06 18:10:06 2017

BACKPORT: proc: revert /proc/<pid>/maps [stack:TID] annotation

[ Upstream commit 65376df582174ffcec9e6471bf5b0dd79ba05e4a ]

Commit b76437579d13 ("procfs: mark thread stack correctly in
proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps.

Finding the task of a stack VMA requires walking the entire thread list,
turning this into quadratic behavior: a thousand threads means a
thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a
million combinations.

The cost is not in proportion to the usefulness as described in the
patch.

Drop the [stack:TID] annotation to make /proc/<pid>/maps (and
/proc/<pid>/numa_maps) usable again for higher thread counts.

The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as
identifying the stack VMA there is an O(1) operation.

Siddesh said:
 "The end users needed a way to identify thread stacks programmatically and
  there wasn't a way to do that.  I'm afraid I no longer remember (or have
  access to the resources that would aid my memory since I changed
  employers) the details of their requirement.  However, I did do this on my
  own time because I thought it was an interesting project for me and nobody
  really gave any feedback then as to its utility, so as far as I am
  concerned you could roll back the main thread maps information since the
  information is available in the thread-specific files"

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7bb9730dab3aff9d53e35bd27eef19eb5b4b9ad5
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
Cc: Shaohua Li <shli@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[groeck: Fix conflicts in fs/proc/task_mmu.c, caused by commit 586278d78bfa
 ("mm: add a field to store names for private anonymous memory")
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f3de8fbe2a2a3ec4c612e2e0ddeee68f9c5bd972,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545096
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0)
Reviewed-on: https://chromium-review.googlesource.com/561961

[modify] https://crrev.com/91f30d3bfb703f6df8aca6adf878b1484bb56f93/include/linux/mm.h
[modify] https://crrev.com/91f30d3bfb703f6df8aca6adf878b1484bb56f93/fs/proc/task_mmu.c
[modify] https://crrev.com/91f30d3bfb703f6df8aca6adf878b1484bb56f93/Documentation/filesystems/proc.txt
[modify] https://crrev.com/91f30d3bfb703f6df8aca6adf878b1484bb56f93/fs/proc/task_nommu.c
[modify] https://crrev.com/91f30d3bfb703f6df8aca6adf878b1484bb56f93/mm/util.c

Project Member

Comment 106 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/ffe16f9e00ba189f1fe7618b75917ba35f3826c9

commit ffe16f9e00ba189f1fe7618b75917ba35f3826c9
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Thu Jul 06 18:10:17 2017

UPSTREAM: mm: Don't count the stack guard page towards RLIMIT_STACK

commit 690eac53daff34169a4d74fc7bfbd388c4896abb upstream.

Commit fee7e49d4514 ("mm: propagate error from stack expansion even for
guard page") made sure that we return the error properly for stack
growth conditions.  It also theorized that counting the guard page
towards the stack limit might break something, but also said "Let's see
if anybody notices".

Somebody did notice.  Apparently android-x86 sets the stack limit very
close to the limit indeed, and including the guard page in the rlimit
check causes the android 'zygote' process problems.

So this adds the (fairly trivial) code to make the stack rlimit check be
against the actual real stack size, rather than the size of the vma that
includes the guard page.

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I28e215b13cfdf35a2ae7cda9c4131abec40b770e
Reported-and-tested-by: Chih-Wei Huang <cwhuang@android-x86.org>
Cc: Jay Foad <jay.foad@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 7d702b4b2b0f1)
Reviewed-on: https://chromium-review.googlesource.com/540055
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 35c3601157aa61fe8bc855c3ccbac1f9cb88d98d)
Reviewed-on: https://chromium-review.googlesource.com/561968

[modify] https://crrev.com/ffe16f9e00ba189f1fe7618b75917ba35f3826c9/mm/mmap.c

Project Member

Comment 107 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4342b4b958e3e67752ecc61f632a97588d0e76ab

commit 4342b4b958e3e67752ecc61f632a97588d0e76ab
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 18:51:37 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

CQ-DEPEND=CL:556052
BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I483e3136829e7a95cd7b1fbad17a9c0f1dc24a3a
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[gkh: minor build fixes for 4.4]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 4b359430674c,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545097
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 44b0c157700e612aed07ca5a35260cf385990f75)
Reviewed-on: https://chromium-review.googlesource.com/561972

[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/include/linux/mm.h
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/mips/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/mm/gup.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/fs/hugetlbfs/inode.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/s390/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/powerpc/mm/slice.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/sh/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/arm/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/fs/proc/task_mmu.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/Documentation/kernel-parameters.txt
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/arc/mm/mmap.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/mm/memory.c
[modify] https://crrev.com/4342b4b958e3e67752ecc61f632a97588d0e76ab/arch/frv/mm/elf-fdpic.c

Let's have it bake in 60 this week and merge to 59 early next week (Mon).
Project Member

Comment 109 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/bf2fc1f56de69894a97d092e7e9d2a4cb2d05c60

commit bf2fc1f56de69894a97d092e7e9d2a4cb2d05c60
Author: Hugh Dickins <hughd@google.com>
Date: Thu Jul 06 18:53:49 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ib30cb5cb70c80f7186caf63f7ac1def7ded76e8b
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1f2284fac218,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545099
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 2dd361385e91df1d33e208e35708a9150684ab1f)
Reviewed-on: https://chromium-review.googlesource.com/561974

[modify] https://crrev.com/bf2fc1f56de69894a97d092e7e9d2a4cb2d05c60/mm/mmap.c

Project Member

Comment 110 by bugdroid1@chromium.org, Jul 6 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/5add41fe095759ad72ab15d2627a10f5223bc0ab

commit 5add41fe095759ad72ab15d2627a10f5223bc0ab
Author: Greg Hackmann <ghackmann@google.com>
Date: Thu Jul 06 18:54:01 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/556052
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit c54f22922b38591032ce97e278007046e31047a7)
Reviewed-on: https://chromium-review.googlesource.com/561975

[modify] https://crrev.com/5add41fe095759ad72ab15d2627a10f5223bc0ab/arch/x86/mm/fault.c

Project Member

Comment 111 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/a7c97aa9c8df609bc90ee588df5654e2e9570c0d

commit a7c97aa9c8df609bc90ee588df5654e2e9570c0d
Author: Greg Hackmann <ghackmann@google.com>
Date: Fri Jul 07 14:39:32 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/559932
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 3c2f4706a9304f9723a85c935c540eaa088f5a43)
Reviewed-on: https://chromium-review.googlesource.com/562439

[modify] https://crrev.com/a7c97aa9c8df609bc90ee588df5654e2e9570c0d/arch/x86/mm/fault.c

Project Member

Comment 112 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/aff149fbcca7fb750e4302b2e34f9d8a8eea1173

commit aff149fbcca7fb750e4302b2e34f9d8a8eea1173
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:39:44 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

Change-Id: If5c4687962ef5f626d86c603144931a7403e115d
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 28ebf89579a0,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/559931
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 71c7596b284997d55e88cf18da07b5a9cfb58f35)
Reviewed-on: https://chromium-review.googlesource.com/562438

[modify] https://crrev.com/aff149fbcca7fb750e4302b2e34f9d8a8eea1173/mm/mmap.c

Project Member

Comment 113 by bugdroid1@chromium.org, Jul 7 2017

Labels: merge-merged-release-R60-9592.B-chromeos-3.14
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e373bfc921965214c410d4f74791b3a3729b0593

commit e373bfc921965214c410d4f74791b3a3729b0593
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:42:09 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

CQ-DEPEND=CL:557932
Change-Id: I09201def44e81686facd7d8333146336b49f84e1
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages();
     included Hugh Dickins' fixes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1ad9a25dd06f,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/557930
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit e16e994e6b0e96187530228ad22a87758dd628eb)
Reviewed-on: https://chromium-review.googlesource.com/561962

[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/include/linux/mm.h
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/mips/mm/mmap.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/mm/mmap.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/fs/hugetlbfs/inode.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/powerpc/mm/slice.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/sh/mm/mmap.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/arm/mm/mmap.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/fs/proc/task_mmu.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/Documentation/kernel-parameters.txt
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/arc/mm/mmap.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/mm/memory.c
[modify] https://crrev.com/e373bfc921965214c410d4f74791b3a3729b0593/arch/frv/mm/elf-fdpic.c

Project Member

Comment 114 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80

commit d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:42:21 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

CQ-DEPEND=CL:559932
Change-Id: Icb104d67a71d5bcfc0918d15b89fad13d286c147
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
[wt: backport to 3.16: adjust context]
[wt: backport to 3.10: adjust context ; code logic in PARISC's
     arch_get_unmapped_area() wasn't found ; code inserted into
     expand_upwards() and expand_downwards() runs under anon_vma lock;
     changes for gup.c:faultin_page go to memory.c:__get_user_pages();
     included Hugh Dickins' fixes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[groeck: Backport; minor context changes]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1ad9a25dd06f,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/559930
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 8fe88d7f70aa4170f3c992ceec7738ab1eb2b3e4)
Reviewed-on: https://chromium-review.googlesource.com/562437

[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/include/linux/mm.h
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/mips/mm/mmap.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/mm/mmap.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/fs/hugetlbfs/inode.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/powerpc/mm/slice.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/sh/mm/mmap.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/arm/mm/mmap.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/fs/proc/task_mmu.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/Documentation/kernel-parameters.txt
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/arc/mm/mmap.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/mm/memory.c
[modify] https://crrev.com/d1d27c0b2ebd66fe6a8ec78563ca1d7ff4af5c80/arch/frv/mm/elf-fdpic.c

Project Member

Comment 115 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/6b797367317f026a846f35f6c1cd848dfa26f3e1

commit 6b797367317f026a846f35f6c1cd848dfa26f3e1
Author: Greg Hackmann <ghackmann@google.com>
Date: Fri Jul 07 14:42:26 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/557932
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 11f0ee346e03a269cb386cbfb3ebc4df658a3446)
Reviewed-on: https://chromium-review.googlesource.com/561967

[modify] https://crrev.com/6b797367317f026a846f35f6c1cd848dfa26f3e1/arch/x86/mm/fault.c

Project Member

Comment 116 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/89fcabe08f6ae6c8ec98455dff01d04f5c9088f6

commit 89fcabe08f6ae6c8ec98455dff01d04f5c9088f6
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:42:29 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093, chromium:737932
TEST=Build and run

Change-Id: I573cce18919ce07a68cd1390d2159fb5447cfcb9
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 28ebf89579a0,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/557931
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit e0aa322a8fac4856cb22083c550ccbafc8b2bb56)
Reviewed-on: https://chromium-review.googlesource.com/561966

[modify] https://crrev.com/89fcabe08f6ae6c8ec98455dff01d04f5c9088f6/mm/mmap.c

Project Member

Comment 117 by bugdroid1@chromium.org, Jul 7 2017

Labels: merge-merged-release-R60-9592.B-chromeos-3.18
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/62dca0a6127026debe502b9fff47ce6e00868899

commit 62dca0a6127026debe502b9fff47ce6e00868899
Author: Greg Hackmann <ghackmann@google.com>
Date: Fri Jul 07 14:45:00 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017, chromium:737932
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/549182
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit a936c044f9084f6a5dc0642076b325c396412a6b)
Reviewed-on: https://chromium-review.googlesource.com/561965

[modify] https://crrev.com/62dca0a6127026debe502b9fff47ce6e00868899/arch/x86/mm/fault.c

Project Member

Comment 118 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc

commit ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:45:05 2017

BACKPORT: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

CQ-DEPEND=CL:549182
BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie908315957f5036bab4aca4896a9c6f8420861c0
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ;
     s390 uses generic arch_get_unmapped_area()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[gkh: minor build fixes for 3.18]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[groeck: Fixed conflicts (mm/memory.c mm/mmap.c) seen due to missing
	 changes compared to 3.18.y]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit b1fd03c625eb,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git)
Reviewed-on: https://chromium-review.googlesource.com/539978
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 85e7c1e19a08d79e3e680af8f7dcb6b615557942)
Reviewed-on: https://chromium-review.googlesource.com/561963

[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/include/linux/mm.h
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/mips/mm/mmap.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/mm/mmap.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/mm/gup.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/fs/hugetlbfs/inode.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/powerpc/mm/slice.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/sh/mm/mmap.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/arm/mm/mmap.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/fs/proc/task_mmu.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/Documentation/kernel-parameters.txt
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/arc/mm/mmap.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/mm/memory.c
[modify] https://crrev.com/ae59f469b49e5bc3fc8fd3c5b6b28c7ae39563dc/arch/frv/mm/elf-fdpic.c

Project Member

Comment 119 by bugdroid1@chromium.org, Jul 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/335441e598bef02117aad218fb2b5b425bb56f08

commit 335441e598bef02117aad218fb2b5b425bb56f08
Author: Hugh Dickins <hughd@google.com>
Date: Fri Jul 07 14:45:09 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ie034fdee219fdf012da5ff062711ed7610320f8c
Cc: stable@vger.kernel.org
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89)
Reviewed-on: https://chromium-review.googlesource.com/543975
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit d0377baafd501a9622f06fb09b603b39178ff620)
Reviewed-on: https://chromium-review.googlesource.com/561964

[modify] https://crrev.com/335441e598bef02117aad218fb2b5b425bb56f08/mm/mmap.c

Project Member

Comment 120 by bugdroid1@chromium.org, Jul 10 2017

Labels: merge-merged-release-R59-9460.B-chromeos-4.4
The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2

commit ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2
Author: Johannes Weiner <hannes@cmpxchg.org>
Date: Mon Jul 10 16:21:52 2017

BACKPORT: proc: revert /proc/<pid>/maps [stack:TID] annotation

[ Upstream commit 65376df582174ffcec9e6471bf5b0dd79ba05e4a ]

Commit b76437579d13 ("procfs: mark thread stack correctly in
proc/<pid>/maps") added [stack:TID] annotation to /proc/<pid>/maps.

Finding the task of a stack VMA requires walking the entire thread list,
turning this into quadratic behavior: a thousand threads means a
thousand stacks, so the rendering of /proc/<pid>/maps needs to look at a
million combinations.

The cost is not in proportion to the usefulness as described in the
patch.

Drop the [stack:TID] annotation to make /proc/<pid>/maps (and
/proc/<pid>/numa_maps) usable again for higher thread counts.

The [stack] annotation inside /proc/<pid>/task/<tid>/maps is retained, as
identifying the stack VMA there is an O(1) operation.

Siddesh said:
 "The end users needed a way to identify thread stacks programmatically and
  there wasn't a way to do that.  I'm afraid I no longer remember (or have
  access to the resources that would aid my memory since I changed
  employers) the details of their requirement.  However, I did do this on my
  own time because I thought it was an interesting project for me and nobody
  really gave any feedback then as to its utility, so as far as I am
  concerned you could roll back the main thread maps information since the
  information is available in the thread-specific files"

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I7bb9730dab3aff9d53e35bd27eef19eb5b4b9ad5
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
Cc: Shaohua Li <shli@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[groeck: Fix conflicts in fs/proc/task_mmu.c, caused by commit 586278d78bfa
 ("mm: add a field to store names for private anonymous memory")
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit f3de8fbe2a2a3ec4c612e2e0ddeee68f9c5bd972,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545096
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 3a0c2ea8f6f8a9480bb5c77af74eff0b12c3f2f0)
Reviewed-on: https://chromium-review.googlesource.com/561961
(cherry picked from commit 91f30d3bfb703f6df8aca6adf878b1484bb56f93)
Reviewed-on: https://chromium-review.googlesource.com/562440

[modify] https://crrev.com/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2/include/linux/mm.h
[modify] https://crrev.com/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2/fs/proc/task_mmu.c
[modify] https://crrev.com/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2/Documentation/filesystems/proc.txt
[modify] https://crrev.com/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2/fs/proc/task_nommu.c
[modify] https://crrev.com/ff94bf51d7c6ffaf25ab2d875e3d50e71a91f3f2/mm/util.c

Project Member

Comment 121 by bugdroid1@chromium.org, Jul 10 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/5cc04a7030e27c7be2c496b7946dde2ddeeb6565

commit 5cc04a7030e27c7be2c496b7946dde2ddeeb6565
Author: Greg Hackmann <ghackmann@google.com>
Date: Mon Jul 10 16:53:56 2017

HACK: CHROMIUM: x86/mm: don't check %sp when faulting page immediately before stack

Prior to 1be7107fbe18 ("mm: larger stack guard gap, between vmas"), the
stack guard page was included in the stack's VMA.  This implementation
detail created a subtle corner case in __do_page_fault(), where the
branch

	if (likely(vma->vm_start <= address))
		goto good_area;

would skip over the %sp check when `address' was inside the stack guard
page.  This allowed userspace to expand the stack without altering %sp
by repeatedly touching the page just below the "advertised" start of the
stack VMA.

Although this corner case probably isn't intended, it appears to have
been in the kernel for years, and is used by real software in the wild.
For example the Android Runtime's Thread::InstallImplicitProtection()
routine has relied on this behavior to expand the main thread's stack,
and crashes on x86 kernels with 1be7107fbe18 applied.

NOTE: Marked as HACK since it effectively re-introduces a bug into the
kernel which is exploited by zygote in Android. Fixing that bug results
in a zygote crash in art::Thread::InstallImplicitProtection(). If and when
this problem will be fixed is currently unknown. If possible, this patch
should be dropped at a later time or, if applicable, be replaced with an
upstream patch.

BUG=chromium:726072, chromium:724093, b:62952017
TEST=Run ARC++

Change-Id: I8d2f6d3e598e99b2605a9caf8e5c6c166de88e0f
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/556052
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit c54f22922b38591032ce97e278007046e31047a7)
Reviewed-on: https://chromium-review.googlesource.com/565522

[modify] https://crrev.com/5cc04a7030e27c7be2c496b7946dde2ddeeb6565/arch/x86/mm/fault.c

Project Member

Comment 122 by bugdroid1@chromium.org, Jul 10 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/18f3e2846cf87d1dc79ffec2873114478431a780

commit 18f3e2846cf87d1dc79ffec2873114478431a780
Author: Hugh Dickins <hughd@google.com>
Date: Mon Jul 10 16:54:01 2017

UPSTREAM: mm: larger stack guard gap, between vmas

commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream.

Stack guard page is a useful feature to reduce a risk of stack smashing
into a different mapping. We have been using a single page gap which
is sufficient to prevent having stack adjacent to a different mapping.
But this seems to be insufficient in the light of the stack usage in
userspace. E.g. glibc uses as large as 64kB alloca() in many commonly
used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX]
which is 256kB or stack strings with MAX_ARG_STRLEN.

This will become especially dangerous for suid binaries and the default
no limit for the stack size limit because those applications can be
tricked to consume a large portion of the stack and a single glibc call
could jump over the guard page. These attacks are not theoretical,
unfortunatelly.

Make those attacks less probable by increasing the stack guard gap
to 1MB (on systems with 4k pages; but make it depend on the page size
because systems with larger base pages might cap stack allocations in
the PAGE_SIZE units) which should cover larger alloca() and VLA stack
allocations. It is obviously not a full fix because the problem is
somehow inherent, but it should reduce attack space a lot.

One could argue that the gap size should be configurable from userspace,
but that can be done later when somebody finds that the new 1MB is wrong
for some special case applications.  For now, add a kernel command line
option (stack_guard_gap) to specify the stack gap size (in page units).

Implementation wise, first delete all the old code for stack guard page:
because although we could get away with accounting one extra page in a
stack vma, accounting a larger gap can break userspace - case in point,
a program run with "ulimit -S -v 20000" failed when the 1MB gap was
counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK
and strict non-overcommit mode.

Instead of keeping gap inside the stack vma, maintain the stack guard
gap as a gap between vmas: using vm_start_gap() in place of vm_start
(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few
places which need to respect the gap - mainly arch_get_unmapped_area(),
and and the vma tree's subtree_gap support for that.

CQ-DEPEND=CL:556052
BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: I483e3136829e7a95cd7b1fbad17a9c0f1dc24a3a
Original-patch-by: Oleg Nesterov <oleg@redhat.com>
Original-patch-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Tested-by: Helge Deller <deller@gmx.de> # parisc
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[wt: backport to 4.11: adjust context]
[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide]
[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes]
Signed-off-by: Willy Tarreau <w@1wt.eu>
[gkh: minor build fixes for 4.4]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 4b359430674c,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545097
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 44b0c157700e612aed07ca5a35260cf385990f75)
Reviewed-on: https://chromium-review.googlesource.com/565520

[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/include/linux/mm.h
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/mips/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/sparc/kernel/sys_sparc_64.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/mm/gup.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/tile/mm/hugetlbpage.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/x86/mm/hugetlbpage.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/fs/hugetlbfs/inode.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/xtensa/kernel/syscall.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/s390/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/powerpc/mm/slice.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/sh/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/parisc/kernel/sys_parisc.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/arm/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/fs/proc/task_mmu.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/sparc/mm/hugetlbpage.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/x86/kernel/sys_x86_64.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/Documentation/kernel-parameters.txt
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/arc/mm/mmap.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/mm/memory.c
[modify] https://crrev.com/18f3e2846cf87d1dc79ffec2873114478431a780/arch/frv/mm/elf-fdpic.c

Project Member

Comment 123 by bugdroid1@chromium.org, Jul 10 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e6c7193d61d7affc144ad703b74524ddd574d2ee

commit e6c7193d61d7affc144ad703b74524ddd574d2ee
Author: Hugh Dickins <hughd@google.com>
Date: Mon Jul 10 16:54:06 2017

UPSTREAM: mm: fix new crash in unmapped_area_topdown()

commit f4cb767d76cf7ee72f97dd76f6cfa6c76a5edc89 upstream.

Trinity gets kernel BUG at mm/mmap.c:1963! in about 3 minutes of
mmap testing.  That's the VM_BUG_ON(gap_end < gap_start) at the
end of unmapped_area_topdown().  Linus points out how MAP_FIXED
(which does not have to respect our stack guard gap intentions)
could result in gap_end below gap_start there.  Fix that, and
the similar case in its alternative, unmapped_area().

BUG=chromium:726072, chromium:724093
TEST=Build and run

Change-Id: Ib30cb5cb70c80f7186caf63f7ac1def7ded76e8b
Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Debugged-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
(cherry picked from commit 1f2284fac218,
 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git)
Reviewed-on: https://chromium-review.googlesource.com/545099
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
(cherry picked from commit 2dd361385e91df1d33e208e35708a9150684ab1f)
Reviewed-on: https://chromium-review.googlesource.com/565521

[modify] https://crrev.com/e6c7193d61d7affc144ad703b74524ddd574d2ee/mm/mmap.c

Status: Fixed (was: Started)
Project Member

Comment 125 by sheriffbot@chromium.org, Oct 17 2017

Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Status: Archived (was: Fixed)
Status: Fixed (was: Archived)
Showing comments 28 - 127 of 127 Older

Sign in to add a comment