Skip to content

Commit

Permalink
add memory protection for pthread_atfork handlers
Browse files Browse the repository at this point in the history
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
  • Loading branch information
thestinger committed Jun 7, 2021
1 parent 2e613cc commit e239c7d
Showing 1 changed file with 32 additions and 2 deletions.
34 changes: 32 additions & 2 deletions libc/bionic/pthread_atfork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct atfork_t {
};

static atfork_t* pool;
static atfork_t* page_list;

class atfork_list_t {
public:
Expand Down Expand Up @@ -160,25 +161,38 @@ void __bionic_atfork_run_parent() {
// __register_atfork is the name used by glibc
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
void(*child)(void), void* dso) {
size_t page_size = getpagesize();

pthread_mutex_lock(&g_atfork_list_mutex);

for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
}

if (!pool) {
size_t page_size = getpagesize();
char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
if (page == MAP_FAILED) {
for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
mprotect(page_it, page_size, PROT_READ);
}

pthread_mutex_unlock(&g_atfork_list_mutex);
return ENOMEM;
}

prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
"atfork handlers");

for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
for (char* it = page + sizeof(atfork_t); it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
atfork_t* node = reinterpret_cast<atfork_t*>(it);
node->next = pool;
pool = node;
}

atfork_t* page_node = reinterpret_cast<atfork_t*>(page);
page_node->next = page_list;
page_list = page_node;
}

atfork_t* entry = pool;
Expand All @@ -191,15 +205,31 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),

g_atfork_list.push_back(entry);

for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
mprotect(page_it, page_size, PROT_READ);
}

pthread_mutex_unlock(&g_atfork_list_mutex);

return 0;
}

extern "C" __LIBC_HIDDEN__ void __unregister_atfork(void* dso) {
pthread_mutex_lock(&g_atfork_list_mutex);

size_t page_size = getpagesize();

for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
}

g_atfork_list.remove_if([&](const atfork_t* entry) {
return entry->dso_handle == dso;
});

for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
mprotect(page_it, page_size, PROT_READ);
}

pthread_mutex_unlock(&g_atfork_list_mutex);
}

0 comments on commit e239c7d

Please sign in to comment.