-/* $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
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;
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;
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) {