@@ -420,6 +420,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
return pte_set_flags(pte, dirty | _PAGE_SOFT_DIRTY);
}
+#define pte_mkwrite_shstk pte_mkwrite_shstk
static inline pte_t pte_mkwrite_shstk(pte_t pte)
{
/* pte_clear_cow() also sets Dirty=1 */
@@ -556,6 +557,7 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
return pmd_set_flags(pmd, dirty | _PAGE_SOFT_DIRTY);
}
+#define pmd_mkwrite_shstk pmd_mkwrite_shstk
static inline pmd_t pmd_mkwrite_shstk(pmd_t pmd)
{
return pmd_clear_cow(pmd);
@@ -1004,12 +1004,19 @@ void free_compound_page(struct page *page);
* servicing faults for write access. In the normal case, do always want
* pte_mkwrite. But get_user_pages can cause write faults for mappings
* that do not have writing enabled, when used by access_process_vm.
+ *
+ * If a vma is shadow stack (a type of writable memory), mark the pte shadow
+ * stack.
*/
static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
{
- if (likely(vma->vm_flags & VM_WRITE))
- pte = pte_mkwrite(pte);
- return pte;
+ if (!(vma->vm_flags & VM_WRITE))
+ return pte;
+
+ if (vma->vm_flags & VM_SHADOW_STACK)
+ return pte_mkwrite_shstk(pte);
+
+ return pte_mkwrite(pte);
}
vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page);
@@ -524,6 +524,13 @@ static inline pte_t pte_sw_mkyoung(pte_t pte)
#define pte_mk_savedwrite pte_mkwrite
#endif
+#ifndef pte_mkwrite_shstk
+static inline pte_t pte_mkwrite_shstk(pte_t pte)
+{
+ return pte;
+}
+#endif
+
#ifndef pte_clear_savedwrite
#define pte_clear_savedwrite pte_wrprotect
#endif
@@ -532,6 +539,13 @@ static inline pte_t pte_sw_mkyoung(pte_t pte)
#define pmd_savedwrite pmd_write
#endif
+#ifndef pmd_mkwrite_shstk
+static inline pmd_t pmd_mkwrite_shstk(pmd_t pmd)
+{
+ return pmd;
+}
+#endif
+
#ifndef pmd_mk_savedwrite
#define pmd_mk_savedwrite pmd_mkwrite
#endif
@@ -553,9 +553,13 @@ __setup("transparent_hugepage=", setup_transparent_hugepage);
pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
{
- if (likely(vma->vm_flags & VM_WRITE))
- pmd = pmd_mkwrite(pmd);
- return pmd;
+ if (!(vma->vm_flags & VM_WRITE))
+ return pmd;
+
+ if (vma->vm_flags & VM_SHADOW_STACK)
+ return pmd_mkwrite_shstk(pmd);
+
+ return pmd_mkwrite(pmd);
}
#ifdef CONFIG_MEMCG