summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-06-13 23:53:22 -0400
committerIan Moffett <ian@osmora.org>2025-06-14 00:28:43 -0400
commita9fb11245f3ccc422089ed60a1ce57b7cb2d1c2a (patch)
tree32901fc4dd37427ff982a4aef41eedaa1c2f1a2c
parentfdeb7fd1ba1c515eaf84b6b46388231d980ce756 (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.c25
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;
}