summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2019-06-02 01:03:02 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2019-06-02 01:03:02 +0000
commit4a80a8ec4a5d6d7d4690398d18ba3e11a49f0d8d (patch)
treeba6f9621a1170d5b6b13543f937687973ef87a85 /lib
parenta8565da1091ea7a7792ae6d3d19d0fa477404ab6 (diff)
Complete the ld.so boot cleanup: move most libc initialization from
_csu_finish() to _libc_preinit(), which is an .init_array function in shared libc (and mark it INITFIRST) or a .preinit_array function in static libc, grabbing the _dl_cb callback there from ld.so. Then in _csu_finish(), invoke the dl_clean_boot() callback to free ld.so's startup bits before main() gets control. Other cleanups this permits: - move various startup structures into .data.rel.ro - the dl* stubs in libc can be strong and call the callbacks provided via _dl_cb - no longer need to conditionalize dlctl() calls on presence of _DYNAMIC original concept and full diff ok kettenis@ ok deraadt@
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/dlfcn/dlfcn_stubs.c43
-rw-r--r--lib/libc/dlfcn/init.c83
-rw-r--r--lib/libc/hidden/dlfcn.h30
-rw-r--r--lib/libc/hidden/link_elf.h26
-rw-r--r--lib/libc/hidden/tib.h5
-rw-r--r--lib/libc/include/namespace.h4
-rw-r--r--lib/libc/stdlib/thread_atexit.c9
8 files changed, 153 insertions, 50 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 891fdc7ee05..bd812632e37 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.40 2017/01/22 23:56:44 jsg Exp $
+# $OpenBSD: Makefile,v 1.41 2019/06/02 01:03:01 guenther Exp $
#
# The YP functions are always in libc. To choose that getpwent() and friends
# actually call the YP functions, put -DYP on the CFLAGS line below.
@@ -16,6 +16,7 @@ LDADD+=-lcompiler_rt
.else
LDADD+=-lgcc
.endif
+LDADD+=-Wl,-zinitfirst
VERSION_SCRIPT= Symbols.map
SYMBOL_LISTS= ${LIBCSRCDIR}/Symbols.list \
diff --git a/lib/libc/dlfcn/dlfcn_stubs.c b/lib/libc/dlfcn/dlfcn_stubs.c
index e04a2aa0706..78d728f66cb 100644
--- a/lib/libc/dlfcn/dlfcn_stubs.c
+++ b/lib/libc/dlfcn/dlfcn_stubs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dlfcn_stubs.c,v 1.14 2016/09/06 18:49:34 guenther Exp $ */
+/* $OpenBSD: dlfcn_stubs.c,v 1.15 2019/06/02 01:03:01 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -28,34 +28,19 @@
#include <sys/types.h>
#include <stddef.h>
+#include <stdio.h>
#include <link.h>
+#include <dlfcn.h>
+#include <tib.h>
#include "init.h"
-/*
- * All functions here are just stubs that will be overridden
- * by the real functions in ld.so when dynamic loading is
- * performed at exec. The symbols here are provided as a link
- * helper so we can link a program using the dl functions
- * without getting any unresolved references.
- */
-
-void *dlopen(const char *libname, int how) __attribute__((weak));
-int dlclose(void *handle) __attribute__((weak));
-void *dlsym(void *handle, const char *name) __attribute__((weak));
-int dlctl(void *handle, int command, void *data) __attribute__((weak));
-char *dlerror(void) __attribute__((weak));
-
-struct dl_info;
-int dladdr(const void *addr, struct dl_info *info) __attribute__((weak));
-
-int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *date) __attribute__((weak));
-
-#include <stdio.h>
void *
dlopen(const char *libname, int how)
{
+ if (_dl_cb != NULL && _dl_cb->dlopen != NULL)
+ return _dl_cb->dlopen(libname, how);
printf("Wrong dl symbols!\n");
return NULL;
}
@@ -63,6 +48,8 @@ dlopen(const char *libname, int how)
int
dlclose(void *handle)
{
+ if (_dl_cb != NULL && _dl_cb->dlclose != NULL)
+ return _dl_cb->dlclose(handle);
printf("Wrong dl symbols!\n");
return 0;
}
@@ -70,6 +57,8 @@ dlclose(void *handle)
void *
dlsym(void *handle, const char *name)
{
+ if (_dl_cb != NULL && _dl_cb->dlsym != NULL)
+ return _dl_cb->dlsym(handle, name);
printf("Wrong dl symbols!\n");
return NULL;
}
@@ -77,12 +66,17 @@ dlsym(void *handle, const char *name)
int
dlctl(void *handle, int command, void *data)
{
+ if (_dl_cb != NULL && _dl_cb->dlctl != NULL)
+ return _dl_cb->dlctl(handle, command, data);
return -1;
}
+DEF_WEAK(dlctl);
char *
dlerror(void)
{
+ if (_dl_cb != NULL && _dl_cb->dlerror != NULL)
+ return _dl_cb->dlerror();
return "Wrong dl symbols!\n";
}
@@ -90,6 +84,8 @@ int
dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
void *data)
{
+ if (_dl_cb != NULL && _dl_cb->dl_iterate_phdr != NULL)
+ return _dl_cb->dl_iterate_phdr(callback, data);
#ifndef PIC
if (_static_phdr_info.dlpi_phdr != NULL)
return callback(&_static_phdr_info, sizeof(_static_phdr_info),
@@ -97,14 +93,18 @@ dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
#endif /* !PIC */
return -1;
}
+DEF_WEAK(dl_iterate_phdr);
int
dladdr(const void *addr, struct dl_info *info)
{
+ if (_dl_cb != NULL && _dl_cb->dladdr != NULL)
+ return _dl_cb->dladdr(addr, info);
printf("Wrong dl symbols!\n");
return -1;
}
+#if 0
/* Thread Local Storage argument structure */
typedef struct {
unsigned long int ti_module;
@@ -131,3 +131,4 @@ ___tls_get_addr(tls_index *ti)
}
#endif /* __i386 */
#endif /* arch with TLS support enabled */
+#endif
diff --git a/lib/libc/dlfcn/init.c b/lib/libc/dlfcn/init.c
index 3c387a60d6b..270f54aada5 100644
--- a/lib/libc/dlfcn/init.c
+++ b/lib/libc/dlfcn/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.6 2017/12/01 23:30:05 guenther Exp $ */
+/* $OpenBSD: init.c,v 1.7 2019/06/02 01:03:01 guenther Exp $ */
/*
* Copyright (c) 2014,2015 Philip Guenther <guenther@openbsd.org>
*
@@ -57,7 +57,7 @@ char *__progname __attribute__((weak)) = NULL;
#ifndef PIC
-struct dl_phdr_info _static_phdr_info = { .dlpi_name = "a.out" };
+struct dl_phdr_info _static_phdr_info __relro = { .dlpi_name = "a.out" };
static inline void early_static_init(char **_argv, char **_envp);
static inline void setup_static_tib(Elf_Phdr *_phdr, int _phnum);
@@ -66,13 +66,12 @@ static inline void setup_static_tib(Elf_Phdr *_phdr, int _phnum);
extern Elf_Ehdr __executable_start[] __attribute__((weak));
#endif /* PIC */
-/*
- * extract useful bits from the auxiliary vector and either
- * a) register ld.so's cleanup in dynamic links, or
- * b) init __progname, environ, and the TIB in static links.
- */
-char ***
-_csu_finish(char **argv, char **envp, void (*cleanup)(void))
+/* provide definitions for these */
+const dl_cb *_dl_cb __relro = NULL;
+
+void _libc_preinit(int, char **, char **, dl_cb_cb *) __dso_hidden;
+void
+_libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
{
AuxInfo *aux;
#ifndef PIC
@@ -80,10 +79,13 @@ _csu_finish(char **argv, char **envp, void (*cleanup)(void))
int phnum = 0;
/* static libc in a static link? */
- if (cleanup == NULL)
+ if (cb == NULL)
early_static_init(argv, envp);
#endif /* !PIC */
+ if (cb != NULL)
+ _dl_cb = cb(DL_CB_CUR);
+
/* Extract useful bits from the auxiliary vector */
while (*envp++ != NULL)
;
@@ -98,30 +100,73 @@ _csu_finish(char **argv, char **envp, void (*cleanup)(void))
break;
case AUX_phdr:
phdr = (void *)aux->au_v;
- _static_phdr_info.dlpi_phdr = phdr;
break;
case AUX_phnum:
phnum = aux->au_v;
- _static_phdr_info.dlpi_phnum = phnum;
break;
#endif /* !PIC */
}
}
#ifndef PIC
- if (cleanup == NULL && phdr == NULL && __executable_start != NULL) {
+ if (cb == NULL && phdr == NULL && __executable_start != NULL) {
/*
* Static non-PIE processes don't get an AUX vector,
* so find the phdrs through the ELF header
*/
+ _static_phdr_info.dlpi_addr = (Elf_Addr)__executable_start;
phdr = (void *)((char *)__executable_start +
__executable_start->e_phoff);
phnum = __executable_start->e_phnum;
}
+ _static_phdr_info.dlpi_phdr = phdr;
+ _static_phdr_info.dlpi_phnum = phnum;
+
/* static libc in a static link? */
- if (cleanup == NULL)
+ if (cb == NULL)
setup_static_tib(phdr, phnum);
#endif /* !PIC */
+}
+
+/* ARM just had to be different... */
+#ifndef __arm__
+# define TYPE "@"
+#else
+# define TYPE "%"
+#endif
+
+#ifdef __LP64__
+# define VALUE_ALIGN ".balign 8"
+# define VALUE_DIRECTIVE ".quad"
+#else
+# define VALUE_ALIGN ".balign 4"
+# ifdef __hppa__
+ /* hppa just had to be different: func pointers prefix with 'P%' */
+# define VALUE_DIRECTIVE ".int P%"
+# else
+# define VALUE_DIRECTIVE ".int"
+# endif
+#endif
+
+#define ADD_TO_ARRAY(func, which) \
+ __asm( " .section ."#which",\"a\","TYPE#which"\n " \
+ VALUE_ALIGN"\n "VALUE_DIRECTIVE" "#func"\n .previous")
+
+#ifdef PIC
+ADD_TO_ARRAY(_libc_preinit, init_array);
+#else
+ADD_TO_ARRAY(_libc_preinit, preinit_array);
+#endif
+
+/*
+ * In dynamic links, invoke ld.so's dl_clean_boot() callback, if any,
+ * and register its cleanup.
+ */
+char ***
+_csu_finish(char **argv, char **envp, void (*cleanup)(void))
+{
+ if (_dl_cb != NULL && _dl_cb->dl_clean_boot != NULL)
+ _dl_cb->dl_clean_boot();
if (cleanup != NULL)
atexit(cleanup);
@@ -163,12 +208,12 @@ early_static_init(char **argv, char **envp)
#define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1))
/* for static binaries, the location and size of the TLS image */
-static void *static_tls;
-static size_t static_tls_fsize;
+static void *static_tls __relro;
+static size_t static_tls_fsize __relro;
-size_t _static_tls_size = 0;
-int _static_tls_align;
-int _static_tls_align_offset;
+size_t _static_tls_size __relro = 0;
+int _static_tls_align __relro;
+int _static_tls_align_offset __relro;
static inline void
setup_static_tib(Elf_Phdr *phdr, int phnum)
diff --git a/lib/libc/hidden/dlfcn.h b/lib/libc/hidden/dlfcn.h
new file mode 100644
index 00000000000..bb6dc23c266
--- /dev/null
+++ b/lib/libc/hidden/dlfcn.h
@@ -0,0 +1,30 @@
+/* $OpenBSD: dlfcn.h,v 1.1 2019/06/02 01:03:01 guenther Exp $ */
+/*
+ * Copyright (c) 2019 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBC_DLFCN_H_
+#define _LIBC_DLFCN_H_
+
+#include_next <dlfcn.h>
+
+PROTO_DEPRECATED(dladdr);
+PROTO_DEPRECATED(dlclose);
+PROTO_DEPRECATED(dlerror);
+PROTO_DEPRECATED(dlopen);
+PROTO_DEPRECATED(dlsym);
+PROTO_NORMAL(dlctl);
+
+#endif /* _LIBC_DLFCN_H_ */
diff --git a/lib/libc/hidden/link_elf.h b/lib/libc/hidden/link_elf.h
new file mode 100644
index 00000000000..04143ec91d2
--- /dev/null
+++ b/lib/libc/hidden/link_elf.h
@@ -0,0 +1,26 @@
+/* $OpenBSD: link_elf.h,v 1.1 2019/06/02 01:03:01 guenther Exp $ */
+/*
+ * Copyright (c) 2019 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBC_LINK_ELF_H_
+#define _LIBC_LINK_ELF_H_
+
+#include_next <link_elf.h>
+
+PROTO_NORMAL(dl_iterate_phdr);
+PROTO_DEPRECATED(dl_unwind_find_exidx);
+
+#endif /* _LIBC_LINK_ELF_H_ */
diff --git a/lib/libc/hidden/tib.h b/lib/libc/hidden/tib.h
index 9c4be95fb96..26463db020c 100644
--- a/lib/libc/hidden/tib.h
+++ b/lib/libc/hidden/tib.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tib.h,v 1.2 2017/12/01 23:30:05 guenther Exp $ */
+/* $OpenBSD: tib.h,v 1.3 2019/06/02 01:03:01 guenther Exp $ */
/*
* Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
*
@@ -39,6 +39,9 @@ extern int _static_tls_align;
extern int _static_tls_align_offset;
#endif
+/* saved handle to callbacks from ld.so */
+extern const dl_cb *_dl_cb;
+
#if ! TCB_HAVE_MD_GET
/*
* For archs without a fast TCB_GET(): the pointer to the TCB in
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index 79692af0bca..330af4050ad 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: namespace.h,v 1.13 2019/05/13 20:00:32 guenther Exp $ */
+/* $OpenBSD: namespace.h,v 1.14 2019/06/02 01:03:01 guenther Exp $ */
#ifndef _LIBC_NAMESPACE_H_
#define _LIBC_NAMESPACE_H_
@@ -59,6 +59,8 @@
#define MAKE_CLONE(dst, src) __dso_hidden typeof(dst) HIDDEN(dst) \
__attribute__((alias (HIDDEN_STRING(src))))
+#define __relro __attribute__((section(".data.rel.ro")))
+
/*
* gcc and clang will generate calls to the functions below.
diff --git a/lib/libc/stdlib/thread_atexit.c b/lib/libc/stdlib/thread_atexit.c
index 2e00428eba4..ef0423c4284 100644
--- a/lib/libc/stdlib/thread_atexit.c
+++ b/lib/libc/stdlib/thread_atexit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: thread_atexit.c,v 1.1 2017/12/16 20:06:56 guenther Exp $ */
+/* $OpenBSD: thread_atexit.c,v 1.2 2019/06/02 01:03:01 guenther Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
@@ -16,15 +16,11 @@
*/
#include <dlfcn.h>
-#include <elf.h>
-#pragma weak _DYNAMIC
#include <stdlib.h>
#include <tib.h>
#include "atexit.h"
-typeof(dlctl) dlctl asm("_dlctl") __attribute__((weak));
-
__weak_alias(__cxa_thread_atexit, __cxa_thread_atexit_impl);
int
@@ -37,8 +33,7 @@ __cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso)
if (fnp == NULL)
return -1;
- if (_DYNAMIC)
- dlctl(NULL, DL_REFERENCE, dso);
+ dlctl(NULL, DL_REFERENCE, dso);
fnp->func = func;
fnp->arg = arg;