summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLorenzo Stoakes <lorenzo.stoakes@oracle.com>2024-12-03 19:05:10 +0100
committerAndrew Morton <akpm@linux-foundation.org>2025-01-14 07:40:43 +0100
commit7a5714991872f0a4805cc6004a5bff19a71d0459 (patch)
treea745ab0a6f9257c6e63f805c71a7d6d8aef2d2dc /fs
parentmm/vma: move unmapped_area() internals to mm/vma.c (diff)
downloadlinux-7a5714991872f0a4805cc6004a5bff19a71d0459.tar.xz
linux-7a5714991872f0a4805cc6004a5bff19a71d0459.zip
mm: abstract get_arg_page() stack expansion and mmap read lock
Right now fs/exec.c invokes expand_downwards(), an otherwise internal implementation detail of the VMA logic in order to ensure that an arg page can be obtained by get_user_pages_remote(). In order to be able to move the stack expansion logic into mm/vma.c to make it available to userland testing we need to find an alternative approach here. We do so by providing the mmap_read_lock_maybe_expand() function which also helpfully documents what get_arg_page() is doing here and adds an additional check against VM_GROWSDOWN to make explicit that the stack expansion logic is only invoked when the VMA is indeed a downward-growing stack. This allows expand_downwards() to become a static function. Importantly, the VMA referenced by mmap_read_maybe_expand() must NOT be currently user-visible in any way, that is place within an rmap or VMA tree. It must be a newly allocated VMA. This is the case when exec invokes this function. Link: https://lkml.kernel.org/r/5295d1c70c58e6aa63d14be68d4e1de9fa1c8e6d.1733248985.git.lorenzo.stoakes@oracle.com Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Jan Kara <jack@suse.cz> Cc: Jann Horn <jannh@google.com> Cc: Kees Cook <kees@kernel.org> Cc: Liam R. Howlett <Liam.Howlett@Oracle.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/exec.c14
1 files changed, 3 insertions, 11 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 98cb7ba9983c..1e1f79c514de 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -205,18 +205,10 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
/*
* Avoid relying on expanding the stack down in GUP (which
* does not work for STACK_GROWSUP anyway), and just do it
- * by hand ahead of time.
+ * ahead of time.
*/
- if (write && pos < vma->vm_start) {
- mmap_write_lock(mm);
- ret = expand_downwards(vma, pos);
- if (unlikely(ret < 0)) {
- mmap_write_unlock(mm);
- return NULL;
- }
- mmap_write_downgrade(mm);
- } else
- mmap_read_lock(mm);
+ if (!mmap_read_lock_maybe_expand(mm, vma, pos, write))
+ return NULL;
/*
* We are doing an exec(). 'current' is the process