Task::alloc_ku_mem_chunk() calls free_ku_mem_chunk in case of errors. However, free_ku_mem_chunk() will try to unmap the entire area which is wrong when called from Task::alloc_ku_mem_chunk().
diff --git a/src/kernel/fiasco/src/kern/task.cpp b/src/kernel/fiasco/src/kern/task.cpp index 35fef8c..4537450 100644 --- a/src/kernel/fiasco/src/kern/task.cpp +++ b/src/kernel/fiasco/src/kern/task.cpp @@ -146,18 +146,18 @@ Task::alloc_ku_mem_chunk(User<void>::Ptr u_addr, unsigned size, void **k_addr) { case Mem_space::Insert_ok: break; case Mem_space::Insert_err_nomem: - free_ku_mem_chunk(p, u_addr, size); + free_ku_mem_chunk(p, u_addr, size, i); return -L4_err::ENomem;
case Mem_space::Insert_err_exists: - free_ku_mem_chunk(p, u_addr, size); + free_ku_mem_chunk(p, u_addr, size, i); return -L4_err::EExists;
default: printf("UTCB mapping failed: va=%p, ph=%p, res=%d\n", (void*)user_va, (void*)kern_va, res); kdb_ke("BUG in utcb allocation"); - free_ku_mem_chunk(p, u_addr, size); + free_ku_mem_chunk(p, u_addr, size, i); return 0; } } @@ -208,13 +208,14 @@ PRIVATE inline NOEXPORT void Task::free_ku_mem(Ku_mem *m) { - free_ku_mem_chunk(m->k_addr, m->u_addr, m->size); + free_ku_mem_chunk(m->k_addr, m->u_addr, m->size, m->size); m->free(ram_quota()); }
PRIVATE void -Task::free_ku_mem_chunk(void *k_addr, User<void>::Ptr u_addr, unsigned size) +Task::free_ku_mem_chunk(void *k_addr, User<void>::Ptr u_addr, unsigned size, + unsigned mapped_size) {
Mapped_allocator * const alloc = Mapped_allocator::allocator(); @@ -226,7 +227,7 @@ Task::free_ku_mem_chunk(void *k_addr, User<void>::Ptr u_addr, unsigned size) if (size >= Config::SUPERPAGE_SIZE) page_size = Config::SUPERPAGE_SIZE;
- for (unsigned long i = 0; i < size; i += page_size) + for (unsigned long i = 0; i < mapped_size; i += page_size) { Address user_va = (Address)u_addr.get() + i; mem_space()->v_delete(Mem_space::Addr(user_va),