From a9fb11245f3ccc422089ed60a1ce57b7cb2d1c2a Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 13 Jun 2025 23:53:22 -0400 Subject: kernel: Prevent physmem clobbers + zero memory To prevent a situation where there is a data race between one thread freeing physical memory and one allocating physical memory. Do not immediately reuse freed physical memory. Instead, keep allocating upwards and once there is no more room, wrap the last_idx back to the bitmap free index. We now also zero allocated physical memory for security reasons. Signed-off-by: Ian Moffett --- sys/vm/vm_physmem.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'sys/vm') diff --git a/sys/vm/vm_physmem.c b/sys/vm/vm_physmem.c index c13130f..89f9ee6 100644 --- a/sys/vm/vm_physmem.c +++ b/sys/vm/vm_physmem.c @@ -39,6 +39,7 @@ static size_t highest_frame_idx = 0; static size_t bitmap_size = 0; static size_t bitmap_free_start = 0; +static ssize_t last_idx = 0; static uint8_t *bitmap; static struct limine_memmap_response *resp = NULL; @@ -137,15 +138,14 @@ physmem_init_bitmap(void) * * @count: Number of frames to allocate. */ -uintptr_t -vm_alloc_frame(size_t count) +static uintptr_t +__vm_alloc_frame(size_t count) { size_t frames = 0; ssize_t idx = -1; uintptr_t ret = 0; - spinlock_acquire(&lock); - for (size_t i = 0; i < highest_frame_idx; ++i) { + for (size_t i = last_idx; i < highest_frame_idx; ++i) { if (!testbit(bitmap, i)) { if (idx < 0) idx = i; @@ -167,9 +167,24 @@ vm_alloc_frame(size_t count) for (size_t i = idx; i < idx + count; ++i) { setbit(bitmap, i); } - ret = idx * DEFAULT_PAGESIZE; + last_idx = idx; + memset(PHYS_TO_VIRT(ret), 0, count * DEFAULT_PAGESIZE); done: + return ret; +} + +uintptr_t +vm_alloc_frame(size_t count) +{ + uintptr_t ret; + + spinlock_acquire(&lock); + if ((ret = __vm_alloc_frame(count)) == 0) { + last_idx = 0; + ret = __vm_alloc_frame(count); + } + spinlock_release(&lock); return ret; } -- cgit v1.2.3