From 32ba0b02ca002c6105d27910d350df4d9e0e5cc6 Mon Sep 17 00:00:00 2001 From: kettenis <> Date: Wed, 18 Jun 2014 19:01:10 +0000 Subject: [PATCH] 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 and Elliott Hughes . ok matthew@ --- src/lib/libc/stdlib/atexit.c | 15 ++++++--------- src/lib/libc/stdlib/atexit.h | 7 ++----- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c index 049da326..9b08ebd7 100644 --- a/src/lib/libc/stdlib/atexit.c +++ b/src/lib/libc/stdlib/atexit.c @@ -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 * All rights reserved. @@ -90,7 +90,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso) __atexit = p; } fnp = &p->fns[p->ind++]; - fnp->fn_ptr.cxa_func = func; + fnp->fn_ptr = func; fnp->fn_arg = arg; fnp->fn_dso = dso; if (mprotect(p, pgsize, PROT_READ)) @@ -118,7 +118,7 @@ __cxa_finalize(void *dso) for (p = __atexit; p != NULL; p = p->next) { 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 */ if (dso != NULL && dso != p->fns[n].fn_dso) continue; /* wrong DSO */ @@ -129,13 +129,10 @@ __cxa_finalize(void *dso) */ fn = p->fns[n]; 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); } - 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)) 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_dso = NULL; mprotect(p, pgsize, PROT_READ); diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h index c44005de..3de2aa3b 100644 --- a/src/lib/libc/stdlib/atexit.h +++ b/src/lib/libc/stdlib/atexit.h @@ -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 @@ -35,10 +35,7 @@ struct atexit { int ind; /* next index in this table */ int max; /* max entries >= ATEXIT_SIZE */ 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_dso; /* shared module handle */ } fns[1]; /* the table itself */