[PATCH v1 RFC Zisslpcfi 12/20] riscv mm: manufacture shadow stack pte and is vma shadowstack

Deepak Gupta
2023-02-13T04:54:46Z

This patch implements creating shadow stack pte (on riscv) if
CONFIG_USER_SHADOW_STACK is selected. Creating shadow stack PTE on riscv
means that clearing RWX and then setting W=1.
Additionally this patch implements `arch_is_shadow_stack_vma`. Each arch
can decide which combination of VMA flags are treated as shadow stack.
riscv is choosing to following PTE encodings for VMA flags as well i.e.
VM_WRITE only (no VM_READ or VM_EXEC) means its a shadow stack vma on
riscv.

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
---
arch/riscv/include/asm/pgtable.h | 8 ++++++++
arch/riscv/mm/pageattr.c | 7 +++++++
2 files changed, 15 insertions(+)

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 13b325253c99..11a423e78d52 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -344,6 +344,14 @@ static inline pte_t pte_mkwrite(pte_t pte)
return __pte(pte_val(pte) | _PAGE_WRITE);
}

+#ifdef CONFIG_USER_SHADOW_STACK
+static inline pte_t pte_mkshdwstk(pte_t pte)
+{
+ /* shadow stack on risc-v is XWR = 010. Clear everything and only set _PAGE_WRITE */
+ return __pte((pte_val(pte) & ~(_PAGE_LEAF)) | _PAGE_WRITE);
+}
+#endif
+
/* static inline pte_t pte_mkexec(pte_t pte) */

static inline pte_t pte_mkdirty(pte_t pte)
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 86c56616e5de..582e17c4dc28 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -233,3 +233,10 @@ bool kernel_page_present(struct page *page)
pte = pte_offset_kernel(pmd, addr);
return pte_present(*pte);
}
+
+#ifdef CONFIG_USER_SHADOW_STACK
+bool arch_is_shadow_stack_vma(struct vm_area_struct *vma)
+{
+ return ((vma->vm_flags & (VM_WRITE | VM_READ | VM_EXEC)) == VM_WRITE);
+}
+#endif
\ No newline at end of file