security: bug fix: incorrect bprm->vma_pages prevent capturing all stack pages

The bprm->vma_pages field is used for quota only and not accurate for
the number of pages used on the stack. Instead, the vma_pages function
should be used to get an exact count.

BUG=b/160721250
TEST=Ran test on GKE and internal pipeline.

Signed-off-by: Thomas Garnier <thgarnie@chromium.org>
Change-Id: I3fd5a93a4dd633df50eb057988a1f571ed100378
Reviewed-on: https://cos-review.googlesource.com/c/third_party/kernel/+/2380
Reviewed-by: Vaibhav Rustagi <vaibhavrustagi@google.com>
diff --git a/security/container/process.c b/security/container/process.c
index 24886f1..f6ed2a9 100644
--- a/security/container/process.c
+++ b/security/container/process.c
@@ -65,12 +65,14 @@
 {
 	char *argv;
 	int err;
-	unsigned long i, pos;
+	unsigned long i, pos, count;
 	void *map;
 	struct page *page;
 
-	/* vma_pages holds the number of pages reserved for the stack */
-	if (likely(bprm->vma_pages == 1)) {
+	/* vma_pages() returns the number of pages reserved for the stack */
+	count = vma_pages(bprm->vma);
+
+	if (likely(count == 1)) {
 		err = get_user_pages_remote(current, bprm->mm, bprm->p, 1,
 					    FOLL_FORCE, &page, NULL, NULL);
 		if (err != 1)
@@ -84,11 +86,11 @@
 		 * of pages. Parsing the argument across kmap pages in different
 		 * addresses would make it impractical.
 		 */
-		argv = vmalloc(bprm->vma_pages * PAGE_SIZE);
+		argv = vmalloc(count * PAGE_SIZE);
 		if (!argv)
 			return NULL;
 
-		for (i = 0; i < bprm->vma_pages; i++) {
+		for (i = 0; i < count; i++) {
 			pos = ALIGN_DOWN(bprm->p, PAGE_SIZE) + i * PAGE_SIZE;
 			err = get_user_pages_remote(current, bprm->mm, pos, 1,
 						    FOLL_FORCE, &page, NULL,
@@ -117,7 +119,7 @@
 	if (!addr)
 		return;
 
-	if (likely(bprm->vma_pages == 1)) {
+	if (likely(vma_pages(bprm->vma) == 1)) {
 		page = (struct page *)ctx;
 		kunmap(addr);
 		put_page(ctx);
@@ -174,7 +176,7 @@
 	int i;
 	struct linux_binprm *bprm = ctx->bprm;
 	unsigned long offset = bprm->p % PAGE_SIZE;
-	unsigned long end = bprm->vma_pages * PAGE_SIZE;
+	unsigned long end = vma_pages(bprm->vma) * PAGE_SIZE;
 	char *argv = ctx->stack;
 	char *entry;
 	size_t limit, used = 0;
@@ -258,7 +260,7 @@
 	int i;
 	struct linux_binprm *bprm = ctx->bprm;
 	unsigned long offset = bprm->p % PAGE_SIZE;
-	unsigned long end = bprm->vma_pages * PAGE_SIZE;
+	unsigned long end = vma_pages(bprm->vma) * PAGE_SIZE;
 	char *argv = ctx->stack;
 	char *entry;
 	size_t limit, used = 0;