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;