Skip to content

Commit

Permalink
add memory protection for at_quick_exit
Browse files Browse the repository at this point in the history
  • Loading branch information
thestinger committed Jun 23, 2019
1 parent 83cd86d commit 1ebb165
Showing 1 changed file with 36 additions and 5 deletions.
41 changes: 36 additions & 5 deletions libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@

#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>

#include "private/bionic_prctl.h"

/**
* Linked list of quick exit handlers. This is simpler than the atexit()
Expand All @@ -39,6 +43,10 @@ struct quick_exit_handler {
void (*cleanup)(void);
};

static struct quick_exit_handler *pool_page;
static struct quick_exit_handler *pool;
static size_t pool_size;

/**
* Lock protecting the handlers list.
*/
Expand All @@ -51,16 +59,39 @@ static struct quick_exit_handler *handlers;
int
at_quick_exit(void (*func)(void))
{
size_t page_size = getpagesize();
struct quick_exit_handler *h;

h = malloc(sizeof(*h));

if (NULL == h)
return (1);
h->cleanup = func;
pthread_mutex_lock(&atexit_mutex);

if (pool_size < sizeof(*h)) {
void *ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED) {
pthread_mutex_unlock(&atexit_mutex);
return (1);
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, page_size,
"at_quick_exit handlers");
pool_page = pool = ptr;
pool_size = page_size;
} else {
if (mprotect(pool_page, page_size, PROT_READ|PROT_WRITE)) {
pthread_mutex_unlock(&atexit_mutex);
return (1);
}
}

h = pool++;
pool_size -= sizeof(*h);

h->cleanup = func;

h->next = handlers;
handlers = h;

mprotect(pool_page, page_size, PROT_READ);

pthread_mutex_unlock(&atexit_mutex);
return (0);
}
Expand Down

0 comments on commit 1ebb165

Please sign in to comment.