summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorDave Hansen <dave.hansen@linux.intel.com>2016-02-12 16:01:54 -0500
committerIngo Molnar <mingo@kernel.org>2016-02-16 04:04:09 -0500
commit1e9877902dc7e11d2be038371c6fbf2dfcd469d7 (patch)
tree715a45eca4c79168f0351421a7584c95212331f8 /mm
parent1fe3f29e4a908461be16a9388e73837157cc7942 (diff)
mm/gup: Introduce get_user_pages_remote()
For protection keys, we need to understand whether protections should be enforced in software or not. In general, we enforce protections when working on our own task, but not when on others. We call these "current" and "remote" operations. This patch introduces a new get_user_pages() variant: get_user_pages_remote() Which is a replacement for when get_user_pages() is called on non-current tsk/mm. We also introduce a new gup flag: FOLL_REMOTE which can be used for the "__" gup variants to get this new behavior. The uprobes is_trap_at_addr() location holds mmap_sem and calls get_user_pages(current->mm) on an instruction address. This makes it a pretty unique gup caller. Being an instruction access and also really originating from the kernel (vs. the app), I opted to consider this a 'remote' access where protection keys will not be enforced. Without protection keys, this patch should not change any behavior. Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave@sr71.net> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: jack@suse.cz Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20160212210154.3F0E51EA@viggo.jf.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/gup.c27
-rw-r--r--mm/memory.c2
-rw-r--r--mm/process_vm_access.c11
3 files changed, 31 insertions, 9 deletions
diff --git a/mm/gup.c b/mm/gup.c
index 7bf19ffa2199..36ca850936c9 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -870,7 +870,7 @@ long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
870EXPORT_SYMBOL(get_user_pages_unlocked); 870EXPORT_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 */
927long get_user_pages(struct task_struct *tsk, struct mm_struct *mm, 927long 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}
936EXPORT_SYMBOL(get_user_pages_remote);
937
938/*
939 * This is the same as get_user_pages_remote() for the time
940 * being.
941 */
942long 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}
934EXPORT_SYMBOL(get_user_pages); 951EXPORT_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