diff options
author | Dan Williams <dan.j.williams@intel.com> | 2017-11-29 19:10:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-29 21:40:42 -0500 |
commit | e7fe7b5cae90cf85bb6fed5ec5d4c5cf311a4fe9 (patch) | |
tree | 8019ca6ee6cd5adbe2bea8f7313c5601a2f87c7f | |
parent | e4e40e0263ea6a3bfefbfd15d1b6ff5c03f2b95e (diff) |
mm: replace pud_write with pud_access_permitted in fault + gup paths
The 'access_permitted' helper is used in the gup-fast path and goes
beyond the simple _PAGE_RW check to also:
- validate that the mapping is writable from a protection keys
standpoint
- validate that the pte has _PAGE_USER set since all fault paths where
pud_write is must be referencing user-memory.
[dan.j.williams@intel.com: fix powerpc compile error]
Link: http://lkml.kernel.org/r/151129127237.37405.16073414520854722485.stgit@dwillia2-desk3.amr.corp.intel.com
Link: http://lkml.kernel.org/r/151043110453.2842.2166049702068628177.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 6 | ||||
-rw-r--r-- | arch/sparc/mm/gup.c | 2 | ||||
-rw-r--r-- | mm/huge_memory.c | 2 | ||||
-rw-r--r-- | mm/memory.c | 2 |
4 files changed, 9 insertions, 3 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 0a6b0286c32e..57d7bc92e0b8 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -1264,6 +1264,12 @@ static inline pud_t pud_mkwrite(pud_t pud) | |||
1264 | return pud; | 1264 | return pud; |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | #define pud_write pud_write | ||
1268 | static inline int pud_write(pud_t pud) | ||
1269 | { | ||
1270 | return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0; | ||
1271 | } | ||
1272 | |||
1267 | static inline pud_t pud_mkclean(pud_t pud) | 1273 | static inline pud_t pud_mkclean(pud_t pud) |
1268 | { | 1274 | { |
1269 | if (pud_large(pud)) { | 1275 | if (pud_large(pud)) { |
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c index 5335ba3c850e..5ae2d0a01a70 100644 --- a/arch/sparc/mm/gup.c +++ b/arch/sparc/mm/gup.c | |||
@@ -114,7 +114,7 @@ static int gup_huge_pud(pud_t *pudp, pud_t pud, unsigned long addr, | |||
114 | if (!(pud_val(pud) & _PAGE_VALID)) | 114 | if (!(pud_val(pud) & _PAGE_VALID)) |
115 | return 0; | 115 | return 0; |
116 | 116 | ||
117 | if (write && !pud_write(pud)) | 117 | if (!pud_access_permitted(pud, write)) |
118 | return 0; | 118 | return 0; |
119 | 119 | ||
120 | refs = 0; | 120 | refs = 0; |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f22401fd83b5..4fe2491056a0 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1019,7 +1019,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, | |||
1019 | 1019 | ||
1020 | assert_spin_locked(pud_lockptr(mm, pud)); | 1020 | assert_spin_locked(pud_lockptr(mm, pud)); |
1021 | 1021 | ||
1022 | if (flags & FOLL_WRITE && !pud_write(*pud)) | 1022 | if (!pud_access_permitted(*pud, flags & FOLL_WRITE)) |
1023 | return NULL; | 1023 | return NULL; |
1024 | 1024 | ||
1025 | if (pud_present(*pud) && pud_devmap(*pud)) | 1025 | if (pud_present(*pud) && pud_devmap(*pud)) |
diff --git a/mm/memory.c b/mm/memory.c index b10c1d26f675..25d283d46ea3 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -4013,7 +4013,7 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address, | |||
4013 | 4013 | ||
4014 | /* NUMA case for anonymous PUDs would go here */ | 4014 | /* NUMA case for anonymous PUDs would go here */ |
4015 | 4015 | ||
4016 | if (dirty && !pud_write(orig_pud)) { | 4016 | if (dirty && !pud_access_permitted(orig_pud, WRITE)) { |
4017 | ret = wp_huge_pud(&vmf, orig_pud); | 4017 | ret = wp_huge_pud(&vmf, orig_pud); |
4018 | if (!(ret & VM_FAULT_FALLBACK)) | 4018 | if (!(ret & VM_FAULT_FALLBACK)) |
4019 | return ret; | 4019 | return ret; |