Clean up abort.

* A dlmalloc usage error shouldn't call abort(3) because we want to
  cause a SIGSEGV by writing the address dlmalloc didn't like to an
  address the kernel won't like, so that debuggerd will dump the
  memory around the address that upset dlmalloc.

* Switch to the simpler FreeBSD/NetBSD style of registering stdio
  cleanup. Hopefully this will let us simplify more of the stdio
  implementation.

* Clear the stdio cleanup handler before we abort because of a dlmalloc
  corruption error. This fixes the reported bug, where we'd hang inside
  dlmalloc because the stdio cleanup reentered dlmalloc.

Bug: 9301265
Change-Id: Ief31b389455d6876e5a68f0f5429567d37277dbc
This commit is contained in:
Elliott Hughes
2013-06-12 14:05:46 -07:00
parent 5cde15eb17
commit 61e699a133
10 changed files with 67 additions and 108 deletions

View File

@@ -44,7 +44,8 @@ struct atexit *__atexit;
* Function pointers are stored in a linked list of pages. The list
* is initially empty, and pages are allocated on demand. The first
* function pointer in the first allocated page (the last one in
* the linked list) is reserved for the cleanup function.
* the linked list) was reserved for the cleanup function.
* TODO: switch to the regular FreeBSD/NetBSD atexit implementation.
*
* Outside the following functions, all pages are mprotect()'ed
* to prevent unintentional/malicious corruption.
@@ -172,42 +173,3 @@ __cxa_finalize(void *dso)
}
_ATEXIT_UNLOCK();
}
/*
* Register the cleanup function
*/
void
__atexit_register_cleanup(void (*func)(void))
{
struct atexit *p;
int pgsize = getpagesize();
if (pgsize < (int)sizeof(*p))
return;
_ATEXIT_LOCK();
p = __atexit;
while (p != NULL && p->next != NULL)
p = p->next;
if (p == NULL) {
p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
p->ind = 1;
p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
sizeof(p->fns[0]);
p->next = NULL;
__atexit = p;
if (__atexit_invalid)
__atexit_invalid = 0;
} else {
if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
goto unlock;
}
p->fns[0].fn_ptr.std_func = func;
p->fns[0].fn_arg = NULL;
p->fns[0].fn_dso = NULL;
mprotect(p, pgsize, PROT_READ);
unlock:
_ATEXIT_UNLOCK();
}