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 <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2022-11-07 12:47:43 -08:00 committed by Fabio Baltieri
commit 100eacca07

View file

@ -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);
}