From 100eacca075f26eb2e05a3404c809d7926a439c8 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Mon, 7 Nov 2022 12:47:43 -0800 Subject: [PATCH] kernel: mmu: fix potential running out of virtual memory space In z_phys_unmap(), the call to virt_region_free() is not using aligned virtual address and space. This can result in freeing smaller region that allocated given that inputs to z_phys_unmap() may not be aligned. So use the already calculated aligned virtual address and size as input to virt_region_free(). Note that the assertion and if-block in virt_region_free() to check whether the to-be-unmapped region is within the virtual memory region needs to be trimmed by one byte at the end. The assertion and if-block are checking against the region end address but (start + size) is just one byte over the end. So subtract one. Signed-off-by: Daniel Leung --- kernel/mmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/mmu.c b/kernel/mmu.c index 9ab52a3030a..21bc27dbd91 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -238,10 +238,10 @@ static void virt_region_free(void *vaddr, size_t size) } __ASSERT((vaddr_u8 >= Z_VIRT_REGION_START_ADDR) - && ((vaddr_u8 + size) < Z_VIRT_REGION_END_ADDR), + && ((vaddr_u8 + size - 1) < Z_VIRT_REGION_END_ADDR), "invalid virtual address region %p (%zu)", vaddr_u8, size); if (!((vaddr_u8 >= Z_VIRT_REGION_START_ADDR) - && ((vaddr_u8 + size) < Z_VIRT_REGION_END_ADDR))) { + && ((vaddr_u8 + size - 1) < Z_VIRT_REGION_END_ADDR))) { return; } @@ -786,7 +786,7 @@ void z_phys_unmap(uint8_t *virt, size_t size) aligned_virt, aligned_size, addr_offset); arch_mem_unmap(UINT_TO_POINTER(aligned_virt), aligned_size); - virt_region_free(virt, size); + virt_region_free(UINT_TO_POINTER(aligned_virt), aligned_size); k_spin_unlock(&z_mm_lock, key); }