Browse Source

Always call atexit handlers as if they were registered with __cxa_atexit.

The extra argument doesn't hurt genuine atexit handlers and this fixes a
bug where we didn't provide the argument (effectively passing garbage) for
functions registered with __cxa_atexit in the main executable.
Pointed out by Dmitriy Ivanov <dimitry@google.com> and Elliott Hughes
<enh@google.com>.
ok matthew@
OPENBSD_5_6
kettenis 10 years ago
parent
commit
32ba0b02ca
2 changed files with 8 additions and 14 deletions
  1. +6
    -9
      src/lib/libc/stdlib/atexit.c
  2. +2
    -5
      src/lib/libc/stdlib/atexit.h

+ 6
- 9
src/lib/libc/stdlib/atexit.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: atexit.c,v 1.17 2013/12/28 18:38:42 kettenis Exp $ */
/* $OpenBSD: atexit.c,v 1.18 2014/06/18 19:01:10 kettenis Exp $ */
/* /*
* Copyright (c) 2002 Daniel Hartmeier * Copyright (c) 2002 Daniel Hartmeier
* All rights reserved. * All rights reserved.
@ -90,7 +90,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
__atexit = p; __atexit = p;
} }
fnp = &p->fns[p->ind++]; fnp = &p->fns[p->ind++];
fnp->fn_ptr.cxa_func = func;
fnp->fn_ptr = func;
fnp->fn_arg = arg; fnp->fn_arg = arg;
fnp->fn_dso = dso; fnp->fn_dso = dso;
if (mprotect(p, pgsize, PROT_READ)) if (mprotect(p, pgsize, PROT_READ))
@ -118,7 +118,7 @@ __cxa_finalize(void *dso)
for (p = __atexit; p != NULL; p = p->next) { for (p = __atexit; p != NULL; p = p->next) {
for (n = p->ind; --n >= 0;) { for (n = p->ind; --n >= 0;) {
if (p->fns[n].fn_ptr.cxa_func == NULL)
if (p->fns[n].fn_ptr == NULL)
continue; /* already called */ continue; /* already called */
if (dso != NULL && dso != p->fns[n].fn_dso) if (dso != NULL && dso != p->fns[n].fn_dso)
continue; /* wrong DSO */ continue; /* wrong DSO */
@ -129,13 +129,10 @@ __cxa_finalize(void *dso)
*/ */
fn = p->fns[n]; fn = p->fns[n];
if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) { if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
p->fns[n].fn_ptr.cxa_func = NULL;
p->fns[n].fn_ptr = NULL;
mprotect(p, pgsize, PROT_READ); mprotect(p, pgsize, PROT_READ);
} }
if (fn.fn_dso != NULL)
(*fn.fn_ptr.cxa_func)(fn.fn_arg);
else
(*fn.fn_ptr.std_func)();
(*fn.fn_ptr)(fn.fn_arg);
} }
} }
@ -185,7 +182,7 @@ __atexit_register_cleanup(void (*func)(void))
if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
goto unlock; goto unlock;
} }
p->fns[0].fn_ptr.std_func = func;
p->fns[0].fn_ptr = (void (*)(void *))func;
p->fns[0].fn_arg = NULL; p->fns[0].fn_arg = NULL;
p->fns[0].fn_dso = NULL; p->fns[0].fn_dso = NULL;
mprotect(p, pgsize, PROT_READ); mprotect(p, pgsize, PROT_READ);


+ 2
- 5
src/lib/libc/stdlib/atexit.h View File

@ -1,4 +1,4 @@
/* $OpenBSD: atexit.h,v 1.8 2013/06/02 21:08:36 matthew Exp $ */
/* $OpenBSD: atexit.h,v 1.9 2014/06/18 19:01:10 kettenis Exp $ */
/* /*
* Copyright (c) 2002 Daniel Hartmeier * Copyright (c) 2002 Daniel Hartmeier
@ -35,10 +35,7 @@ struct atexit {
int ind; /* next index in this table */ int ind; /* next index in this table */
int max; /* max entries >= ATEXIT_SIZE */ int max; /* max entries >= ATEXIT_SIZE */
struct atexit_fn { struct atexit_fn {
union {
void (*std_func)(void);
void (*cxa_func)(void *);
} fn_ptr;
void (*fn_ptr)(void *);
void *fn_arg; /* argument for CXA callback */ void *fn_arg; /* argument for CXA callback */
void *fn_dso; /* shared module handle */ void *fn_dso; /* shared module handle */
} fns[1]; /* the table itself */ } fns[1]; /* the table itself */


Loading…
Cancel
Save