summaryrefslogtreecommitdiff
path: root/libexec/ld.so/loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so/loader.c')
-rw-r--r--libexec/ld.so/loader.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 9f15530e2c4..de53dc85d58 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.218 2023/12/19 16:13:22 deraadt Exp $ */
+/* $OpenBSD: loader.c,v 1.219 2024/01/14 09:39:03 kettenis Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -70,6 +70,7 @@ int _dl_trust __relro = 0;
char **_dl_libpath __relro = NULL;
const char **_dl_argv __relro = NULL;
int _dl_argc __relro = 0;
+const char *_dl_libcname;
char *_dl_preload __boot_data = NULL;
char *_dl_tracefmt1 __boot_data = NULL;
@@ -358,6 +359,31 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
if (dynp->d_tag == DT_NEEDED)
liblist[loop++].dynp = dynp;
+ /*
+ * We can't support multiple versions of libc
+ * in a single process. So remember the first
+ * libc SONAME we encounter as a dependency
+ * and use it in further loads of libc. In
+ * practice this means we will always use the
+ * libc version that the binary was linked
+ * against. This isn't entirely correct, but
+ * it will keep most binaries running when
+ * transitioning over a libc major bump.
+ */
+ if (_dl_libcname == NULL) {
+ for (loop = 0; loop < libcount; loop++) {
+ const char *libname;
+ libname = dynobj->dyn.strtab;
+ libname +=
+ liblist[loop].dynp->d_un.d_val;
+ if (_dl_strncmp(libname,
+ "libc.so.", 8) == 0) {
+ _dl_libcname = libname;
+ break;
+ }
+ }
+ }
+
/* Randomize these */
for (loop = 0; loop < libcount; loop++)
randomlist[loop] = loop;
@@ -380,6 +406,10 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
liblist[randomlist[loop]].dynp->d_un.d_val;
DL_DEB(("loading: %s required by %s\n", libname,
dynobj->load_name));
+ if (_dl_strncmp(libname, "libc.so.", 8) == 0) {
+ if (_dl_libcname)
+ libname = _dl_libcname;
+ }
depobj = _dl_load_shlib(libname, dynobj,
OBJTYPE_LIB, depflags, nodelete);
if (depobj == 0) {