From owner-dev-commits-src-all@freebsd.org Mon Aug 23 09:21:54 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 048E666726C; Mon, 23 Aug 2021 09:21:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GtRZn5NbPz4RKL; Mon, 23 Aug 2021 09:21:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 980FE11CA0; Mon, 23 Aug 2021 09:21:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 17N9Lr7R067133; Mon, 23 Aug 2021 09:21:53 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 17N9Lr3k067132; Mon, 23 Aug 2021 09:21:53 GMT (envelope-from git) Date: Mon, 23 Aug 2021 09:21:53 GMT Message-Id: <202108230921.17N9Lr3k067132@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: edb509a026bd - stable/13 - rtld: Switch to the standard symbol lookup behavior if LD_DYNAMIC_WEAK is set MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: edb509a026bd9cd2f6a81fd4d5af1a332f96a00d Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Aug 2021 09:21:54 -0000 The branch stable/13 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=edb509a026bd9cd2f6a81fd4d5af1a332f96a00d commit edb509a026bd9cd2f6a81fd4d5af1a332f96a00d Author: Fangrui Song AuthorDate: 2021-08-15 04:13:33 +0000 Commit: Konstantin Belousov CommitDate: 2021-08-23 09:20:56 +0000 rtld: Switch to the standard symbol lookup behavior if LD_DYNAMIC_WEAK is set (cherry picked from commit 7da378f9de1a042ec0c81ba7ad39a392540d4721) --- libexec/rtld-elf/rtld.1 | 20 +++++++++++++++++++- libexec/rtld-elf/rtld.c | 40 ++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 index b6572caac811..8bc4cfade070 100644 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 24, 2021 +.Dd August 15, 2021 .Dt RTLD 1 .Os .Sh NAME @@ -143,6 +143,24 @@ If set, .Nm will print a table containing all relocations before symbol binding and relocation. +.It Ev LD_DYNAMIC_WEAK +If set, use the ELF standard-compliant symbol lookup behavior: +resolve to the first found symbol definition. +.Pp +By default, +.Fx +provides the non-standard symbol lookup behavior: +when a weak symbol definition is found, remember the definition and +keep searching in the remaining shared objects for a non-weak definition. +If found, the non-weak definition is preferred, otherwise the remembered +weak definition is returned. +.Pp +Symbols exported by dynamic linker itself (see +.Xr dlfcn 3 ) +are always resolved using +.Fx +rules regardless of the presence of the variable. +This variable is unset for set-user-ID and set-group-ID programs. .It Ev LD_LIBMAP A library replacement list in the same format as .Xr libmap.conf 5 . diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 23482e07fc5f..61b823aaacf8 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -209,6 +209,8 @@ static bool dangerous_ld_env; /* True if environment variables have been bool ld_bind_not; /* Disable PLT update */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ +static bool ld_dynamic_weak = true; /* True if non-weak definition overrides + weak definition */ static char *ld_library_path; /* Environment variable for search path */ static char *ld_library_dirs; /* Environment variable for library descriptors */ static char *ld_preload; /* Environment variable for libraries to @@ -583,7 +585,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) || unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) || unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH")) || - unsetenv(_LD("PRELOAD_FDS"))) { + unsetenv(_LD("PRELOAD_FDS")) || unsetenv(_LD("DYNAMIC_WEAK"))) { _rtld_error("environment corrupt; aborting"); rtld_die(); } @@ -591,6 +593,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) ld_debug = getenv(_LD("DEBUG")); if (ld_bind_now == NULL) ld_bind_not = getenv(_LD("BIND_NOT")) != NULL; + ld_dynamic_weak = getenv(_LD("DYNAMIC_WEAK")) == NULL; libmap_disable = getenv(_LD("LIBMAP_DISABLE")) != NULL; libmap_override = getenv(_LD("LIBMAP")); ld_library_path = getenv(_LD("LIBRARY_PATH")); @@ -610,7 +613,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) } dangerous_ld_env = libmap_disable || (libmap_override != NULL) || (ld_library_path != NULL) || (ld_preload != NULL) || - (ld_elf_hints_path != NULL) || ld_loadfltr; + (ld_elf_hints_path != NULL) || ld_loadfltr || ld_dynamic_weak; ld_tracing = getenv(_LD("TRACE_LOADED_OBJECTS")); ld_utrace = getenv(_LD("UTRACE")); @@ -3673,11 +3676,12 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, continue; res = symlook_obj(&req, obj); if (res == 0) { - if (def == NULL || - ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK) { + if (def == NULL || (ld_dynamic_weak && + ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK)) { def = req.sym_out; defobj = req.defobj_out; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) + if (!ld_dynamic_weak || + ELF_ST_BIND(def->st_info) != STB_WEAK) break; } } @@ -3686,6 +3690,8 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, * Search the dynamic linker itself, and possibly resolve the * symbol from there. This is how the application links to * dynamic linker services such as dlopen. + * Note that we ignore ld_dynamic_weak == false case, + * always overriding weak symbols by rtld definitions. */ if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { res = symlook_obj(&req, &obj_rtld); @@ -4288,10 +4294,10 @@ symlook_global(SymLook *req, DoneList *donelist) symlook_init_from_req(&req1, req); /* Search all objects loaded at program start up. */ - if (req->defobj_out == NULL || - ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { + if (req->defobj_out == NULL || (ld_dynamic_weak && + ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK)) { res = symlook_list(&req1, &list_main, donelist); - if (res == 0 && (req->defobj_out == NULL || + if (res == 0 && (!ld_dynamic_weak || req->defobj_out == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; @@ -4301,8 +4307,8 @@ symlook_global(SymLook *req, DoneList *donelist) /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ STAILQ_FOREACH(elm, &list_global, link) { - if (req->defobj_out != NULL && - ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) + if (req->defobj_out != NULL && (!ld_dynamic_weak || + ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK)) break; res = symlook_list(&req1, &elm->obj->dagmembers, donelist); if (res == 0 && (req->defobj_out == NULL || @@ -4351,8 +4357,8 @@ symlook_default(SymLook *req, const Obj_Entry *refobj) /* Search all dlopened DAGs containing the referencing object. */ STAILQ_FOREACH(elm, &refobj->dldags, link) { - if (req->sym_out != NULL && - ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) + if (req->sym_out != NULL && (!ld_dynamic_weak || + ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK)) break; res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); if (res == 0 && (req->sym_out == NULL || @@ -4397,10 +4403,11 @@ symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) continue; symlook_init_from_req(&req1, req); if ((res = symlook_obj(&req1, elm->obj)) == 0) { - if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { + if (def == NULL || (ld_dynamic_weak && + ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { def = req1.sym_out; defobj = req1.defobj_out; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) + if (!ld_dynamic_weak || ELF_ST_BIND(def->st_info) != STB_WEAK) break; } } @@ -4435,10 +4442,11 @@ symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) if (n->obj == NULL || (res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0) continue; - if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { + if (def == NULL || (ld_dynamic_weak && + ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { def = req1.sym_out; defobj = req1.defobj_out; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) + if (!ld_dynamic_weak || ELF_ST_BIND(def->st_info) != STB_WEAK) break; } }