Overallocation bug in "valloc" #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
while (region) {
if (region->next == NULL ||
region->start + (region->pages * PAGE_SIZE) < region->next->start) {
new = (vregion_t*)palloc(1, true);
if (!new)
return NULL;
memset(new, 0, sizeof(vregion_t));
new->pages = pages;
new->flags = VFLAGS_TO_PFLAGS(flags);
new->start = region->start + (region->pages * PAGE_SIZE);
new->next = region->next;
new->prev = region;
region->next = new;
for (uint64_t i = 0; i < pages; i++) {
uint64_t page = (uint64_t)palloc(1, false);
if (page == 0)
return NULL;
vmap(ctx->pagemap, new->start + (i * PAGE_SIZE), page,
new->flags);
}
return (void*)new->start;
}
region = region->next;
}
At line 49, it checks if the next region is NULL, or if the region's start address + the region's size is smaller than the next region, and it only check if there's a gap between
region->start + region->size
andregion->next->start
, but not if the gap is big enough to fit the requested number of pages in.For example: let's say the user allocated 3 memory blocks of 1 page each from
0x10000
to0x12000
and then freed the memory block at0x11000
. If the user requests a memory block of 3 pages, it will check if there's a gap between 0x10000 and 0x12000, and then will proceed to allocate those 3 blocks. But there's only a gap of 1 page, not 3, and so, the VMA will overwrite 0x12000 to be part of the requested 3 pages.Here's a demo of the VMA bug:

We can see from the line
vma: vaddr 15000, vflags 3 -> pflags 3, pm: ...
that ramfs_lookup allocated a new vnode at 0x15000. And when vma_alloc was called to allocate a 12 page-sized buffer, and found that there's a free region at 0x13000, it didn't check if there was enough space, and overwrote the vnode, resulting in a vfs_read error:Read -1 bytes from /dir/hey:
The requested fix
The fix would be that instead of checking if there's a gap between 2 regions, like defined here at line 49 of vmm.c:
, it checks if the region is big enough to hold
pages
, like in the now patched version in Soaplin:Fixed in
4b102ad684