Skip to content

Commit 5b78ed2

Browse files
Luigi Rizzotorvalds
Luigi Rizzo
authored andcommitted
mm/pagemap: add mmap_assert_locked() annotations to find_vma*()
find_vma() and variants need protection when used. This patch adds mmap_assert_lock() calls in the functions. To make sure the invariant is satisfied, we also need to add a mmap_read_lock() around the get_user_pages_remote() call in get_arg_page(). The lock is not strictly necessary because the mm has been newly created, but the extra cost is limited because the same mutex was also acquired shortly before in __bprm_mm_init(), so it is hot and uncontended. [[email protected]: TOMOYO needs the same protection which get_arg_page() needs] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Luigi Rizzo <[email protected]> Cc: David Rientjes <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent e15710b commit 5b78ed2

File tree

3 files changed

+13
-4
lines changed

3 files changed

+13
-4
lines changed

fs/exec.c

+2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,10 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
217217
* We are doing an exec(). 'current' is the process
218218
* doing the exec and bprm->mm is the new process's mm.
219219
*/
220+
mmap_read_lock(bprm->mm);
220221
ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,
221222
&page, NULL, NULL);
223+
mmap_read_unlock(bprm->mm);
222224
if (ret <= 0)
223225
return NULL;
224226

mm/mmap.c

+2
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ static int find_vma_links(struct mm_struct *mm, unsigned long addr,
534534
{
535535
struct rb_node **__rb_link, *__rb_parent, *rb_prev;
536536

537+
mmap_assert_locked(mm);
537538
__rb_link = &mm->mm_rb.rb_node;
538539
rb_prev = __rb_parent = NULL;
539540

@@ -2303,6 +2304,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
23032304
struct rb_node *rb_node;
23042305
struct vm_area_struct *vma;
23052306

2307+
mmap_assert_locked(mm);
23062308
/* Check the cache first. */
23072309
vma = vmacache_find(mm, addr);
23082310
if (likely(vma))

security/tomoyo/domain.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,9 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
897897
struct tomoyo_page_dump *dump)
898898
{
899899
struct page *page;
900+
#ifdef CONFIG_MMU
901+
int ret;
902+
#endif
900903

901904
/* dump->data is released by tomoyo_find_next_domain(). */
902905
if (!dump->data) {
@@ -909,11 +912,13 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
909912
/*
910913
* This is called at execve() time in order to dig around
911914
* in the argv/environment of the new proceess
912-
* (represented by bprm). 'current' is the process doing
913-
* the execve().
915+
* (represented by bprm).
914916
*/
915-
if (get_user_pages_remote(bprm->mm, pos, 1,
916-
FOLL_FORCE, &page, NULL, NULL) <= 0)
917+
mmap_read_lock(bprm->mm);
918+
ret = get_user_pages_remote(bprm->mm, pos, 1,
919+
FOLL_FORCE, &page, NULL, NULL);
920+
mmap_read_unlock(bprm->mm);
921+
if (ret <= 0)
917922
return false;
918923
#else
919924
page = bprm->page[pos / PAGE_SIZE];

0 commit comments

Comments
 (0)