git: fe05296fc3d0 - main - arm64: Add pmap integration for KMSAN
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 08 Feb 2024 16:36:40 UTC
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=fe05296fc3d0ec4079a51ecf1250fcde0f54fc5f commit fe05296fc3d0ec4079a51ecf1250fcde0f54fc5f Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2024-02-08 16:11:02 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2024-02-08 16:35:11 +0000 arm64: Add pmap integration for KMSAN - In pmap_bootstrap_san(), allocate the root PTPs for the shadow maps. (For KASAN, this is done earlier since we need to do some special bootstrapping for the kernel stack.) - Adjust ifdefs to include KMSAN. - Expand the shadow maps when pmap_growkernel() is called. MFC after: 2 weeks Sponsored by: Klara, Inc. Sponsored by: Juniper Networks, Inc. Differential Revision: https://reviews.freebsd.org/D43405 --- sys/arm64/arm64/machdep.c | 2 +- sys/arm64/arm64/pmap.c | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index c543f0764e3b..92f9e5692be4 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -972,7 +972,7 @@ initarm(struct arm64_bootparams *abp) * we'll end up searching for segments that we can safely use. Those * segments also get excluded from phys_avail. */ -#if defined(KASAN) +#if defined(KASAN) || defined(KMSAN) pmap_bootstrap_san(); #endif diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 93f513832b97..d9b6425cc20e 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -114,6 +114,7 @@ #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mman.h> +#include <sys/msan.h> #include <sys/msgbuf.h> #include <sys/mutex.h> #include <sys/physmem.h> @@ -1321,9 +1322,9 @@ pmap_bootstrap(vm_size_t kernlen) cpu_tlb_flushID(); } -#ifdef KASAN +#if defined(KASAN) || defined(KMSAN) static void -pmap_bootstrap_allocate_kasan_l2(vm_paddr_t start_pa, vm_paddr_t end_pa, +pmap_bootstrap_allocate_san_l2(vm_paddr_t start_pa, vm_paddr_t end_pa, vm_offset_t *vap, vm_offset_t eva) { vm_paddr_t pa; @@ -1392,7 +1393,7 @@ pmap_bootstrap_san1(vm_offset_t va, int scale) if (kernstart >= plow && kernstart < phigh) phigh = kernstart; if (phigh - plow >= L2_SIZE) { - pmap_bootstrap_allocate_kasan_l2(plow, phigh, &va, eva); + pmap_bootstrap_allocate_san_l2(plow, phigh, &va, eva); if (va >= eva) break; } @@ -1403,7 +1404,7 @@ pmap_bootstrap_san1(vm_offset_t va, int scale) /* * Done. We should now have a valid shadow address mapped for all KVA * that has been mapped so far, i.e., KERNBASE to virtual_avail. Thus, - * shadow accesses by the kasan(9) runtime will succeed for this range. + * shadow accesses by the sanitizer runtime will succeed for this range. * When the kernel virtual address range is later expanded, as will * happen in vm_mem_init(), the shadow map will be grown as well. This * is handled by pmap_san_enter(). @@ -1413,7 +1414,32 @@ pmap_bootstrap_san1(vm_offset_t va, int scale) void pmap_bootstrap_san(void) { +#ifdef KASAN pmap_bootstrap_san1(KASAN_MIN_ADDRESS, KASAN_SHADOW_SCALE); +#else + static uint8_t kmsan_shad_ptp[PAGE_SIZE * 2] __aligned(PAGE_SIZE); + static uint8_t kmsan_orig_ptp[PAGE_SIZE * 2] __aligned(PAGE_SIZE); + pd_entry_t *l0, *l1; + + if (virtual_avail - VM_MIN_KERNEL_ADDRESS > L1_SIZE) + panic("initial kernel map is too large"); + + l0 = pmap_l0(kernel_pmap, KMSAN_SHAD_MIN_ADDRESS); + pmap_store(l0, L0_TABLE | PHYS_TO_PTE( + pmap_early_vtophys((vm_offset_t)kmsan_shad_ptp))); + l1 = pmap_l0_to_l1(l0, KMSAN_SHAD_MIN_ADDRESS); + pmap_store(l1, L1_TABLE | PHYS_TO_PTE( + pmap_early_vtophys((vm_offset_t)kmsan_shad_ptp + PAGE_SIZE))); + pmap_bootstrap_san1(KMSAN_SHAD_MIN_ADDRESS, 1); + + l0 = pmap_l0(kernel_pmap, KMSAN_ORIG_MIN_ADDRESS); + pmap_store(l0, L0_TABLE | PHYS_TO_PTE( + pmap_early_vtophys((vm_offset_t)kmsan_orig_ptp))); + l1 = pmap_l0_to_l1(l0, KMSAN_ORIG_MIN_ADDRESS); + pmap_store(l1, L1_TABLE | PHYS_TO_PTE( + pmap_early_vtophys((vm_offset_t)kmsan_orig_ptp + PAGE_SIZE))); + pmap_bootstrap_san1(KMSAN_ORIG_MIN_ADDRESS, 1); +#endif } #endif @@ -2717,8 +2743,10 @@ pmap_growkernel(vm_offset_t addr) addr = roundup2(addr, L2_SIZE); if (addr - 1 >= vm_map_max(kernel_map)) addr = vm_map_max(kernel_map); - if (kernel_vm_end < addr) + if (kernel_vm_end < addr) { kasan_shadow_map(kernel_vm_end, addr - kernel_vm_end); + kmsan_shadow_map(kernel_vm_end, addr - kernel_vm_end); + } while (kernel_vm_end < addr) { l0 = pmap_l0(kernel_pmap, kernel_vm_end); KASSERT(pmap_load(l0) != 0, @@ -7856,7 +7884,7 @@ pmap_pte_bti(pmap_t pmap, vm_offset_t va __diagused) return (0); } -#if defined(KASAN) +#if defined(KASAN) || defined(KMSAN) static pd_entry_t *pmap_san_early_l2; #define SAN_BOOTSTRAP_L2_SIZE (1 * L2_SIZE) @@ -7930,7 +7958,7 @@ pmap_san_enter_alloc_l2(void) Ln_ENTRIES, 0, ~0ul, L2_SIZE, 0, VM_MEMATTR_DEFAULT)); } -void __nosanitizeaddress +void __nosanitizeaddress __nosanitizememory pmap_san_enter(vm_offset_t va) { pd_entry_t *l1, *l2; @@ -7992,7 +8020,7 @@ pmap_san_enter(vm_offset_t va) PMAP_SAN_PTE_BITS | L3_PAGE); dmb(ishst); } -#endif /* KASAN */ +#endif /* KASAN || KMSAN */ /* * Track a range of the kernel's virtual address space that is contiguous