diff options
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gem.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_userptr.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/core/umem_odp.c | 8 | ||||
-rw-r--r-- | fs/exec.c | 8 | ||||
-rw-r--r-- | include/linux/mm.h | 5 | ||||
-rw-r--r-- | kernel/events/uprobes.c | 10 | ||||
-rw-r--r-- | mm/gup.c | 27 | ||||
-rw-r--r-- | mm/memory.c | 2 | ||||
-rw-r--r-- | mm/process_vm_access.c | 11 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 9 | ||||
-rw-r--r-- | virt/kvm/async_pf.c | 8 |
11 files changed, 77 insertions, 27 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 4b519e4309b2..97d4457be8d2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c | |||
@@ -753,9 +753,9 @@ static struct page **etnaviv_gem_userptr_do_get_pages( | |||
753 | 753 | ||
754 | down_read(&mm->mmap_sem); | 754 | down_read(&mm->mmap_sem); |
755 | while (pinned < npages) { | 755 | while (pinned < npages) { |
756 | ret = get_user_pages(task, mm, ptr, npages - pinned, | 756 | ret = get_user_pages_remote(task, mm, ptr, npages - pinned, |
757 | !etnaviv_obj->userptr.ro, 0, | 757 | !etnaviv_obj->userptr.ro, 0, |
758 | pvec + pinned, NULL); | 758 | pvec + pinned, NULL); |
759 | if (ret < 0) | 759 | if (ret < 0) |
760 | break; | 760 | break; |
761 | 761 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 59e45b3a6937..90dbf8121210 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c | |||
@@ -584,11 +584,11 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) | |||
584 | 584 | ||
585 | down_read(&mm->mmap_sem); | 585 | down_read(&mm->mmap_sem); |
586 | while (pinned < npages) { | 586 | while (pinned < npages) { |
587 | ret = get_user_pages(work->task, mm, | 587 | ret = get_user_pages_remote(work->task, mm, |
588 | obj->userptr.ptr + pinned * PAGE_SIZE, | 588 | obj->userptr.ptr + pinned * PAGE_SIZE, |
589 | npages - pinned, | 589 | npages - pinned, |
590 | !obj->userptr.read_only, 0, | 590 | !obj->userptr.read_only, 0, |
591 | pvec + pinned, NULL); | 591 | pvec + pinned, NULL); |
592 | if (ret < 0) | 592 | if (ret < 0) |
593 | break; | 593 | break; |
594 | 594 | ||
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index e69bf266049d..75077a018675 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c | |||
@@ -572,10 +572,10 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt, | |||
572 | * complex (and doesn't gain us much performance in most use | 572 | * complex (and doesn't gain us much performance in most use |
573 | * cases). | 573 | * cases). |
574 | */ | 574 | */ |
575 | npages = get_user_pages(owning_process, owning_mm, user_virt, | 575 | npages = get_user_pages_remote(owning_process, owning_mm, |
576 | gup_num_pages, | 576 | user_virt, gup_num_pages, |
577 | access_mask & ODP_WRITE_ALLOWED_BIT, 0, | 577 | access_mask & ODP_WRITE_ALLOWED_BIT, |
578 | local_page_list, NULL); | 578 | 0, local_page_list, NULL); |
579 | up_read(&owning_mm->mmap_sem); | 579 | up_read(&owning_mm->mmap_sem); |
580 | 580 | ||
581 | if (npages < 0) | 581 | if (npages < 0) |
@@ -198,8 +198,12 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
198 | return NULL; | 198 | return NULL; |
199 | } | 199 | } |
200 | #endif | 200 | #endif |
201 | ret = get_user_pages(current, bprm->mm, pos, | 201 | /* |
202 | 1, write, 1, &page, NULL); | 202 | * We are doing an exec(). 'current' is the process |
203 | * doing the exec and bprm->mm is the new process's mm. | ||
204 | */ | ||
205 | ret = get_user_pages_remote(current, bprm->mm, pos, 1, write, | ||
206 | 1, &page, NULL); | ||
203 | if (ret <= 0) | 207 | if (ret <= 0) |
204 | return NULL; | 208 | return NULL; |
205 | 209 | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index b1d4b8c7f7cd..faf3b709eead 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1225,6 +1225,10 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1225 | unsigned long start, unsigned long nr_pages, | 1225 | unsigned long start, unsigned long nr_pages, |
1226 | unsigned int foll_flags, struct page **pages, | 1226 | unsigned int foll_flags, struct page **pages, |
1227 | struct vm_area_struct **vmas, int *nonblocking); | 1227 | struct vm_area_struct **vmas, int *nonblocking); |
1228 | long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
1229 | unsigned long start, unsigned long nr_pages, | ||
1230 | int write, int force, struct page **pages, | ||
1231 | struct vm_area_struct **vmas); | ||
1228 | long get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 1232 | long get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
1229 | unsigned long start, unsigned long nr_pages, | 1233 | unsigned long start, unsigned long nr_pages, |
1230 | int write, int force, struct page **pages, | 1234 | int write, int force, struct page **pages, |
@@ -2170,6 +2174,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, | |||
2170 | #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ | 2174 | #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ |
2171 | #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ | 2175 | #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ |
2172 | #define FOLL_MLOCK 0x1000 /* lock present pages */ | 2176 | #define FOLL_MLOCK 0x1000 /* lock present pages */ |
2177 | #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ | ||
2173 | 2178 | ||
2174 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, | 2179 | typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, |
2175 | void *data); | 2180 | void *data); |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 0167679182c0..8eef5f55d3f0 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -299,7 +299,7 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, | |||
299 | 299 | ||
300 | retry: | 300 | retry: |
301 | /* Read the page with vaddr into memory */ | 301 | /* Read the page with vaddr into memory */ |
302 | ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); | 302 | ret = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); |
303 | if (ret <= 0) | 303 | if (ret <= 0) |
304 | return ret; | 304 | return ret; |
305 | 305 | ||
@@ -1700,7 +1700,13 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr) | |||
1700 | if (likely(result == 0)) | 1700 | if (likely(result == 0)) |
1701 | goto out; | 1701 | goto out; |
1702 | 1702 | ||
1703 | result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); | 1703 | /* |
1704 | * The NULL 'tsk' here ensures that any faults that occur here | ||
1705 | * will not be accounted to the task. 'mm' *is* current->mm, | ||
1706 | * but we treat this as a 'remote' access since it is | ||
1707 | * essentially a kernel access to the memory. | ||
1708 | */ | ||
1709 | result = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &page, NULL); | ||
1704 | if (result < 0) | 1710 | if (result < 0) |
1705 | return result; | 1711 | return result; |
1706 | 1712 | ||
@@ -870,7 +870,7 @@ long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm, | |||
870 | EXPORT_SYMBOL(get_user_pages_unlocked); | 870 | EXPORT_SYMBOL(get_user_pages_unlocked); |
871 | 871 | ||
872 | /* | 872 | /* |
873 | * get_user_pages() - pin user pages in memory | 873 | * get_user_pages_remote() - pin user pages in memory |
874 | * @tsk: the task_struct to use for page fault accounting, or | 874 | * @tsk: the task_struct to use for page fault accounting, or |
875 | * NULL if faults are not to be recorded. | 875 | * NULL if faults are not to be recorded. |
876 | * @mm: mm_struct of target mm | 876 | * @mm: mm_struct of target mm |
@@ -924,12 +924,29 @@ EXPORT_SYMBOL(get_user_pages_unlocked); | |||
924 | * should use get_user_pages because it cannot pass | 924 | * should use get_user_pages because it cannot pass |
925 | * FAULT_FLAG_ALLOW_RETRY to handle_mm_fault. | 925 | * FAULT_FLAG_ALLOW_RETRY to handle_mm_fault. |
926 | */ | 926 | */ |
927 | long get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 927 | long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, |
928 | unsigned long start, unsigned long nr_pages, int write, | 928 | unsigned long start, unsigned long nr_pages, |
929 | int force, struct page **pages, struct vm_area_struct **vmas) | 929 | int write, int force, struct page **pages, |
930 | struct vm_area_struct **vmas) | ||
930 | { | 931 | { |
931 | return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force, | 932 | return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force, |
932 | pages, vmas, NULL, false, FOLL_TOUCH); | 933 | pages, vmas, NULL, false, |
934 | FOLL_TOUCH | FOLL_REMOTE); | ||
935 | } | ||
936 | EXPORT_SYMBOL(get_user_pages_remote); | ||
937 | |||
938 | /* | ||
939 | * This is the same as get_user_pages_remote() for the time | ||
940 | * being. | ||
941 | */ | ||
942 | long get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | ||
943 | unsigned long start, unsigned long nr_pages, | ||
944 | int write, int force, struct page **pages, | ||
945 | struct vm_area_struct **vmas) | ||
946 | { | ||
947 | return __get_user_pages_locked(tsk, mm, start, nr_pages, | ||
948 | write, force, pages, vmas, NULL, false, | ||
949 | FOLL_TOUCH); | ||
933 | } | 950 | } |
934 | EXPORT_SYMBOL(get_user_pages); | 951 | EXPORT_SYMBOL(get_user_pages); |
935 | 952 | ||
diff --git a/mm/memory.c b/mm/memory.c index 38090ca37a08..8bfbad0cca8c 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -3685,7 +3685,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, | |||
3685 | void *maddr; | 3685 | void *maddr; |
3686 | struct page *page = NULL; | 3686 | struct page *page = NULL; |
3687 | 3687 | ||
3688 | ret = get_user_pages(tsk, mm, addr, 1, | 3688 | ret = get_user_pages_remote(tsk, mm, addr, 1, |
3689 | write, 1, &page, &vma); | 3689 | write, 1, &page, &vma); |
3690 | if (ret <= 0) { | 3690 | if (ret <= 0) { |
3691 | #ifndef CONFIG_HAVE_IOREMAP_PROT | 3691 | #ifndef CONFIG_HAVE_IOREMAP_PROT |
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 5d453e58ddbf..07514d41ebcc 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c | |||
@@ -98,9 +98,14 @@ static int process_vm_rw_single_vec(unsigned long addr, | |||
98 | int pages = min(nr_pages, max_pages_per_loop); | 98 | int pages = min(nr_pages, max_pages_per_loop); |
99 | size_t bytes; | 99 | size_t bytes; |
100 | 100 | ||
101 | /* Get the pages we're interested in */ | 101 | /* |
102 | pages = get_user_pages_unlocked(task, mm, pa, pages, | 102 | * Get the pages we're interested in. We must |
103 | vm_write, 0, process_pages); | 103 | * add FOLL_REMOTE because task/mm might not |
104 | * current/current->mm | ||
105 | */ | ||
106 | pages = __get_user_pages_unlocked(task, mm, pa, pages, | ||
107 | vm_write, 0, process_pages, | ||
108 | FOLL_REMOTE); | ||
104 | if (pages <= 0) | 109 | if (pages <= 0) |
105 | return -EFAULT; | 110 | return -EFAULT; |
106 | 111 | ||
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 38651454ed08..ade7c6cad172 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -874,7 +874,14 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, | |||
874 | } | 874 | } |
875 | /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ | 875 | /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ |
876 | #ifdef CONFIG_MMU | 876 | #ifdef CONFIG_MMU |
877 | if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) | 877 | /* |
878 | * This is called at execve() time in order to dig around | ||
879 | * in the argv/environment of the new proceess | ||
880 | * (represented by bprm). 'current' is the process doing | ||
881 | * the execve(). | ||
882 | */ | ||
883 | if (get_user_pages_remote(current, bprm->mm, pos, 1, | ||
884 | 0, 1, &page, NULL) <= 0) | ||
878 | return false; | 885 | return false; |
879 | #else | 886 | #else |
880 | page = bprm->page[pos / PAGE_SIZE]; | 887 | page = bprm->page[pos / PAGE_SIZE]; |
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c index 353159922456..d604e87a510a 100644 --- a/virt/kvm/async_pf.c +++ b/virt/kvm/async_pf.c | |||
@@ -79,7 +79,13 @@ static void async_pf_execute(struct work_struct *work) | |||
79 | 79 | ||
80 | might_sleep(); | 80 | might_sleep(); |
81 | 81 | ||
82 | get_user_pages_unlocked(NULL, mm, addr, 1, 1, 0, NULL); | 82 | /* |
83 | * This work is run asynchromously to the task which owns | ||
84 | * mm and might be done in another context, so we must | ||
85 | * use FOLL_REMOTE. | ||
86 | */ | ||
87 | __get_user_pages_unlocked(NULL, mm, addr, 1, 1, 0, NULL, FOLL_REMOTE); | ||
88 | |||
83 | kvm_async_page_present_sync(vcpu, apf); | 89 | kvm_async_page_present_sync(vcpu, apf); |
84 | 90 | ||
85 | spin_lock(&vcpu->async_pf.lock); | 91 | spin_lock(&vcpu->async_pf.lock); |