@@ -445,6 +445,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
return __pte_mkdirty(pte, true);
}
+#define pte_mkwrite_shstk pte_mkwrite_shstk
static inline pte_t pte_mkwrite_shstk(pte_t pte)
{
/* pte_clear_cow() also sets Dirty=1 */
@@ -589,6 +590,7 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
return __pmd_mkdirty(pmd, true);
}
+#define pmd_mkwrite_shstk pmd_mkwrite_shstk
static inline pmd_t pmd_mkwrite_shstk(pmd_t pmd)
{
return pmd_clear_cow(pmd);
@@ -1106,12 +1106,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);
@@ -532,6 +532,20 @@ static inline pte_t pte_sw_mkyoung(pte_t pte)
#define pte_sw_mkyoung pte_sw_mkyoung
#endif
+#ifndef pte_mkwrite_shstk
+static inline pte_t pte_mkwrite_shstk(pte_t pte)
+{
+ return pte;
+}
+#endif
+
+#ifndef pmd_mkwrite_shstk
+static inline pmd_t pmd_mkwrite_shstk(pmd_t pmd)
+{
+ return pmd;
+}
+#endif
+
#ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline void pmdp_set_wrprotect(struct mm_struct *mm,
@@ -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