diff options
author | Ian Moffett <ian@osmora.org> | 2025-06-13 23:53:22 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-06-14 00:28:43 -0400 |
commit | a9fb11245f3ccc422089ed60a1ce57b7cb2d1c2a (patch) | |
tree | 32901fc4dd37427ff982a4aef41eedaa1c2f1a2c | |
parent | fdeb7fd1ba1c515eaf84b6b46388231d980ce756 (diff) |
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 <ian@osmora.org>
-rw-r--r-- | sys/vm/vm_physmem.c | 25 |
1 files changed, 20 insertions, 5 deletions
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; } |