Skip to content
Snippets Groups Projects
Commit 064e99d5 authored by Nadav Har'El's avatar Nadav Har'El
Browse files

Fix bug in leak detection interaction with mmap() code

mmu::allocate(), implementing mmap(), used to first evacuate the
region (marking it free), then allocate a tiny vma object (a start,end
pair), and finally populate the region.

But it turns out that the allocation, if it calls backtrace() for the first
time, ends up calling mmap() too :-) These two running mmap()s aren't
protected by the mutex (it's the same thread), and the second mmap could
take the region just freed by the first mmap - before returning to the
first mmap who would reuse this region.

We solve this bug by allocating the vma object before evacuating the
region, so the other mmap picks different memory.

Before this fix, "--leak tests/tst-mmap.so" crashes with assertion
failure. With this fix, it succeeds.
parent d25789d5
No related branches found
No related tags found
No related merge requests found
......@@ -594,20 +594,24 @@ struct fill_file_page : fill_page {
uintptr_t allocate(uintptr_t start, size_t size, bool search,
fill_page& fill, unsigned perm)
{
std::lock_guard<mutex> guard(vma_list_mutex);
// To support memory allocation tracking - where operator new() might end
// up indirectly calling mmap(), we need to allocate the vma object here,
// and not between the evacuate() and populate().
vma *v = new vma(start, start + size);
std::lock_guard<mutex> guard(vma_list_mutex);
if (search) {
// search for unallocated hole around start
if (!start) {
start = 0x200000000000ul;
}
start = find_hole(start, size);
v->set(start, start+size);
} else {
// we don't know if the given range is free, need to evacuate it first
evacuate(start, start+size);
}
vma* v = new vma(start, start+size);
vma_list.insert(*v);
populate(&fill, perm).operate((void*)start, size);
......@@ -710,6 +714,12 @@ vma::vma(uintptr_t start, uintptr_t end)
{
}
void vma::set(uintptr_t start, uintptr_t end)
{
_start = align_down(start);
_end = align_up(end);
}
uintptr_t vma::start() const
{
return _start;
......
......@@ -33,12 +33,13 @@ enum {
class vma {
public:
vma(uintptr_t start, uintptr_t end);
void set(uintptr_t start, uintptr_t end);
uintptr_t start() const;
uintptr_t end() const;
void* addr() const;
uintptr_t size() const;
void split(uintptr_t edge);
private:
private:
uintptr_t _start;
uintptr_t _end;
public:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment