kern_hyp_va that converts kernel VA into a HYP VA relies on the top byte of kernel pointers being 0xff. Untag pointers passed to it with KHWASAN enabled. Also fix create_hyp_mappings() and create_hyp_io_mappings(), to use the untagged kernel pointers for address computations. Signed-off-by: Andrey Konovalov <andreyknvl@xxxxxxxxxx> --- arch/arm64/include/asm/kvm_mmu.h | 8 ++++++++ virt/kvm/arm/mmu.c | 20 +++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 7faed6e48b46..5149ff83b4c4 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -97,6 +97,9 @@ * Should be completely invisible on any viable CPU. */ .macro kern_hyp_va reg +#ifdef CONFIG_KASAN_TAGS + orr \reg, \reg, #KASAN_PTR_TAG_MASK +#endif alternative_if_not ARM64_HAS_VIRT_HOST_EXTN and \reg, \reg, #HYP_PAGE_OFFSET_HIGH_MASK alternative_else_nop_endif @@ -115,6 +118,11 @@ alternative_else_nop_endif static inline unsigned long __kern_hyp_va(unsigned long v) { +#ifdef CONFIG_KASAN_TAGS + asm volatile("orr %0, %0, %1" + : "+r" (v) + : "i" (KASAN_PTR_TAG_MASK)); +#endif asm volatile(ALTERNATIVE("and %0, %0, %1", "nop", ARM64_HAS_VIRT_HOST_EXTN) diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index b960acdd0c05..3dba9b60e0a0 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/hugetlb.h> #include <linux/sched/signal.h> +#include <linux/kasan.h> #include <trace/events/kvm.h> #include <asm/pgalloc.h> #include <asm/cacheflush.h> @@ -683,9 +684,13 @@ static phys_addr_t kvm_kaddr_to_phys(void *kaddr) int create_hyp_mappings(void *from, void *to, pgprot_t prot) { phys_addr_t phys_addr; - unsigned long virt_addr; - unsigned long start = kern_hyp_va((unsigned long)from); - unsigned long end = kern_hyp_va((unsigned long)to); + unsigned long virt_addr, start, end; + + from = khwasan_reset_tag(from); + to = khwasan_reset_tag(to); + + start = kern_hyp_va((unsigned long)from); + end = kern_hyp_va((unsigned long)to); if (is_kernel_in_hyp_mode()) return 0; @@ -719,8 +724,13 @@ int create_hyp_mappings(void *from, void *to, pgprot_t prot) */ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr) { - unsigned long start = kern_hyp_va((unsigned long)from); - unsigned long end = kern_hyp_va((unsigned long)to); + unsigned long start, end; + + from = khwasan_reset_tag(from); + to = khwasan_reset_tag(to); + + start = kern_hyp_va((unsigned long)from); + end = kern_hyp_va((unsigned long)to); if (is_kernel_in_hyp_mode()) return 0; -- 2.17.0.rc0.231.g781580f067-goog