]>
Commit | Line | Data |
---|---|---|
2b834b08 FG |
1 | From 361de9fb44163c4e693022786af380a2b2298c6d Mon Sep 17 00:00:00 2001 |
2 | From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> | |
3 | Date: Fri, 24 Feb 2017 14:59:19 -0800 | |
4 | Subject: [PATCH 4/4] mm/ksm: handle protnone saved writes when making page | |
5 | write protect | |
6 | ||
7 | Without this KSM will consider the page write protected, but a numa | |
8 | fault can later mark the page writable. This can result in memory | |
9 | corruption. | |
10 | ||
11 | Link: http://lkml.kernel.org/r/1487498625-10891-3-git-send-email-aneesh.kumar@linux.vnet.ibm.com | |
12 | Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | |
13 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
14 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
15 | (backported from commit 595cd8f256d24face93b2722927ec9c980419c26) | |
16 | Signed-off-by: Seth Forshee <seth.forshee@canonical.com> | |
17 | --- | |
18 | include/asm-generic/pgtable.h | 8 ++++++++ | |
19 | mm/ksm.c | 9 +++++++-- | |
20 | 2 files changed, 15 insertions(+), 2 deletions(-) | |
21 | ||
22 | diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h | |
23 | index b6f3a8a4b738..8c8ba48bef0b 100644 | |
24 | --- a/include/asm-generic/pgtable.h | |
25 | +++ b/include/asm-generic/pgtable.h | |
26 | @@ -200,6 +200,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres | |
27 | #define pte_mk_savedwrite pte_mkwrite | |
28 | #endif | |
29 | ||
30 | +#ifndef pte_clear_savedwrite | |
31 | +#define pte_clear_savedwrite pte_wrprotect | |
32 | +#endif | |
33 | + | |
34 | #ifndef pmd_savedwrite | |
35 | #define pmd_savedwrite pmd_write | |
36 | #endif | |
37 | @@ -208,6 +212,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres | |
38 | #define pmd_mk_savedwrite pmd_mkwrite | |
39 | #endif | |
40 | ||
41 | +#ifndef pmd_clear_savedwrite | |
42 | +#define pmd_clear_savedwrite pmd_wrprotect | |
43 | +#endif | |
44 | + | |
45 | #ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT | |
46 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | |
47 | static inline void pmdp_set_wrprotect(struct mm_struct *mm, | |
48 | diff --git a/mm/ksm.c b/mm/ksm.c | |
49 | index fed4afd8293b..099dfa45d596 100644 | |
50 | --- a/mm/ksm.c | |
51 | +++ b/mm/ksm.c | |
52 | @@ -878,7 +878,8 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |
53 | if (!ptep) | |
54 | goto out_mn; | |
55 | ||
56 | - if (pte_write(*ptep) || pte_dirty(*ptep)) { | |
57 | + if (pte_write(*ptep) || pte_dirty(*ptep) || | |
58 | + (pte_protnone(*ptep) && pte_savedwrite(*ptep))) { | |
59 | pte_t entry; | |
60 | ||
61 | swapped = PageSwapCache(page); | |
62 | @@ -903,7 +904,11 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |
63 | } | |
64 | if (pte_dirty(entry)) | |
65 | set_page_dirty(page); | |
66 | - entry = pte_mkclean(pte_wrprotect(entry)); | |
67 | + | |
68 | + if (pte_protnone(entry)) | |
69 | + entry = pte_mkclean(pte_clear_savedwrite(entry)); | |
70 | + else | |
71 | + entry = pte_mkclean(pte_wrprotect(entry)); | |
72 | set_pte_at_notify(mm, addr, ptep, entry); | |
73 | } | |
74 | *orig_pte = *ptep; | |
75 | -- | |
76 | 2.7.4 | |
77 |