summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkettenis <>2014-06-18 19:01:10 +0000
committerkettenis <>2014-06-18 19:01:10 +0000
commitea52171d7ee0bb85a996dc2021440e122bf0357d (patch)
tree25ba00731ee7e34a8f0bb9da9731d10eba63a790 /src
parent067b361c7dbce14db401c57d13ca4e1146dedc3c (diff)
downloadopenbsd-ea52171d7ee0bb85a996dc2021440e122bf0357d.tar.gz
openbsd-ea52171d7ee0bb85a996dc2021440e122bf0357d.tar.bz2
openbsd-ea52171d7ee0bb85a996dc2021440e122bf0357d.zip
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@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/atexit.c15
-rw-r--r--src/lib/libc/stdlib/atexit.h7
-rw-r--r--src/regress/lib/libc/atexit/atexit_test.c10
3 files changed, 13 insertions, 19 deletions
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index 049da3261d..9b08ebd7e6 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: atexit.c,v 1.17 2013/12/28 18:38:42 kettenis Exp $ */ 1/* $OpenBSD: atexit.c,v 1.18 2014/06/18 19:01:10 kettenis Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Daniel Hartmeier 3 * Copyright (c) 2002 Daniel Hartmeier
4 * All rights reserved. 4 * All rights reserved.
@@ -90,7 +90,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
90 __atexit = p; 90 __atexit = p;
91 } 91 }
92 fnp = &p->fns[p->ind++]; 92 fnp = &p->fns[p->ind++];
93 fnp->fn_ptr.cxa_func = func; 93 fnp->fn_ptr = func;
94 fnp->fn_arg = arg; 94 fnp->fn_arg = arg;
95 fnp->fn_dso = dso; 95 fnp->fn_dso = dso;
96 if (mprotect(p, pgsize, PROT_READ)) 96 if (mprotect(p, pgsize, PROT_READ))
@@ -118,7 +118,7 @@ __cxa_finalize(void *dso)
118 118
119 for (p = __atexit; p != NULL; p = p->next) { 119 for (p = __atexit; p != NULL; p = p->next) {
120 for (n = p->ind; --n >= 0;) { 120 for (n = p->ind; --n >= 0;) {
121 if (p->fns[n].fn_ptr.cxa_func == NULL) 121 if (p->fns[n].fn_ptr == NULL)
122 continue; /* already called */ 122 continue; /* already called */
123 if (dso != NULL && dso != p->fns[n].fn_dso) 123 if (dso != NULL && dso != p->fns[n].fn_dso)
124 continue; /* wrong DSO */ 124 continue; /* wrong DSO */
@@ -129,13 +129,10 @@ __cxa_finalize(void *dso)
129 */ 129 */
130 fn = p->fns[n]; 130 fn = p->fns[n];
131 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) { 131 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
132 p->fns[n].fn_ptr.cxa_func = NULL; 132 p->fns[n].fn_ptr = NULL;
133 mprotect(p, pgsize, PROT_READ); 133 mprotect(p, pgsize, PROT_READ);
134 } 134 }
135 if (fn.fn_dso != NULL) 135 (*fn.fn_ptr)(fn.fn_arg);
136 (*fn.fn_ptr.cxa_func)(fn.fn_arg);
137 else
138 (*fn.fn_ptr.std_func)();
139 } 136 }
140 } 137 }
141 138
@@ -185,7 +182,7 @@ __atexit_register_cleanup(void (*func)(void))
185 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) 182 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
186 goto unlock; 183 goto unlock;
187 } 184 }
188 p->fns[0].fn_ptr.std_func = func; 185 p->fns[0].fn_ptr = (void (*)(void *))func;
189 p->fns[0].fn_arg = NULL; 186 p->fns[0].fn_arg = NULL;
190 p->fns[0].fn_dso = NULL; 187 p->fns[0].fn_dso = NULL;
191 mprotect(p, pgsize, PROT_READ); 188 mprotect(p, pgsize, PROT_READ);
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
index c44005deda..3de2aa3bf6 100644
--- a/src/lib/libc/stdlib/atexit.h
+++ b/src/lib/libc/stdlib/atexit.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: atexit.h,v 1.8 2013/06/02 21:08:36 matthew Exp $ */ 1/* $OpenBSD: atexit.h,v 1.9 2014/06/18 19:01:10 kettenis Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Daniel Hartmeier 4 * Copyright (c) 2002 Daniel Hartmeier
@@ -35,10 +35,7 @@ struct atexit {
35 int ind; /* next index in this table */ 35 int ind; /* next index in this table */
36 int max; /* max entries >= ATEXIT_SIZE */ 36 int max; /* max entries >= ATEXIT_SIZE */
37 struct atexit_fn { 37 struct atexit_fn {
38 union { 38 void (*fn_ptr)(void *);
39 void (*std_func)(void);
40 void (*cxa_func)(void *);
41 } fn_ptr;
42 void *fn_arg; /* argument for CXA callback */ 39 void *fn_arg; /* argument for CXA callback */
43 void *fn_dso; /* shared module handle */ 40 void *fn_dso; /* shared module handle */
44 } fns[1]; /* the table itself */ 41 } fns[1]; /* the table itself */
diff --git a/src/regress/lib/libc/atexit/atexit_test.c b/src/regress/lib/libc/atexit/atexit_test.c
index 3dd0b62c3e..f374dee9eb 100644
--- a/src/regress/lib/libc/atexit/atexit_test.c
+++ b/src/regress/lib/libc/atexit/atexit_test.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: atexit_test.c,v 1.6 2007/09/03 14:42:44 millert Exp $ */ 1/* $OpenBSD: atexit_test.c,v 1.7 2014/06/18 19:01:10 kettenis Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Daniel Hartmeier 4 * Copyright (c) 2002 Daniel Hartmeier
@@ -43,7 +43,7 @@
43void handle_first(void); 43void handle_first(void);
44void handle_middle(void); 44void handle_middle(void);
45void handle_last(void); 45void handle_last(void);
46void handle_invalid(void); 46void handle_invalid(void *);
47void handle_cleanup(void); 47void handle_cleanup(void);
48void handle_signal(int); 48void handle_signal(int);
49 49
@@ -79,7 +79,7 @@ main(int argc, char *argv[])
79 /* this is supposed to segfault */ 79 /* this is supposed to segfault */
80 if (!strcmp(argv[1], "-invalid-atexit")) { 80 if (!strcmp(argv[1], "-invalid-atexit")) {
81 signal(SIGSEGV, handle_signal); 81 signal(SIGSEGV, handle_signal);
82 __atexit->fns[0].fn_ptr.std_func = handle_invalid; 82 __atexit->fns[0].fn_ptr = handle_invalid;
83 } else if (!strcmp(argv[1], "-invalid-cleanup")) { 83 } else if (!strcmp(argv[1], "-invalid-cleanup")) {
84 struct atexit *p = __atexit; 84 struct atexit *p = __atexit;
85 85
@@ -88,7 +88,7 @@ main(int argc, char *argv[])
88 p = p->next; 88 p = p->next;
89 if (p == NULL) 89 if (p == NULL)
90 fprintf(stderr, "p == NULL, no page found\n"); 90 fprintf(stderr, "p == NULL, no page found\n");
91 p->fns[0].fn_ptr.std_func = handle_invalid; 91 p->fns[0].fn_ptr = handle_invalid;
92 } 92 }
93 __atexit_register_cleanup(handle_cleanup); 93 __atexit_register_cleanup(handle_cleanup);
94 counter = 0; 94 counter = 0;
@@ -121,7 +121,7 @@ handle_cleanup(void)
121} 121}
122 122
123void 123void
124handle_invalid(void) 124handle_invalid(void *arg)
125{ 125{
126 fprintf(stderr, "handle_invalid() THIS SHOULD HAVE SEGFAULTED INSTEAD!\n"); 126 fprintf(stderr, "handle_invalid() THIS SHOULD HAVE SEGFAULTED INSTEAD!\n");
127} 127}