From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 729623858D20 for ; Tue, 30 May 2023 11:24:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 729623858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1685445842; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LzjiAc+L5+eCuqfttZrt6pn/4ey3Mwi3QhTVovJyXrM=; b=GOIgtbI/kLHUIiFx4wOm05Ivtri/Hldwh5WKcB2lJmsqpM4YQdhkJXpXxSioEs1oDpv7c0 cphdtg7/huNjJYLGZDkS/0oA2JP6MnJR2ndLEgqTmRJ6ASrHBfk7ecIKkP0yO5jtPESjMB OYuRV5F10bavKLCImQUF7B0769eUi+o= Received: from mail-yw1-f198.google.com (mail-yw1-f198.google.com [209.85.128.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-631-8PqPPCnFMKKMcIN7wVPqIA-1; Tue, 30 May 2023 07:23:11 -0400 X-MC-Unique: 8PqPPCnFMKKMcIN7wVPqIA-1 Received: by mail-yw1-f198.google.com with SMTP id 00721157ae682-5655d99da53so98391537b3.0 for ; Tue, 30 May 2023 04:23:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685445790; x=1688037790; h=content-transfer-encoding:in-reply-to:organization:from:references :to:content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=LzjiAc+L5+eCuqfttZrt6pn/4ey3Mwi3QhTVovJyXrM=; b=Gv8pzc57CiDUoUDkbN7juTWl4wmaGWufzOcQJsh1B89gqvQyXa1Pf4uO0FRfP5SOM7 PBeKYAalVqRHp8DNayb7xAdppr9RTFgex1gwydqMn5aPWxeZFkCgjfvXYHXQt1XbNeHB pfjNCvdoVxFLNK+rBMGk+wgLSAlx1E19LgUOPsFomX8oS1r6R6b7Y+bfw+AbM4H5pAE3 Tm3LMPwunpoDn6VJYQKzdjc59cDU75FO32VQ8Di5WNeoJtLfG73B6Y37jdgLietLdCa3 sR8Xxfz0aM26Y1sayAmVUluMSrZ21r4p+7te1dC/50TELNPTXy6tEkfJ5wWpeUhIUil+ Cy4Q== X-Gm-Message-State: AC+VfDz2CqrL84BvQIf1wLyNlSxrvZz5POVMuGBGIQj6CNUwKyqSld+b V1tqM1fS3T3vMN62zKBzwvNEok0ub27SJwYuRYkYBRsqLZosWHDv0vb/GbuY7MprRIOjM4683Ng 5mJ1WfDHDr/QVsNlQpklQ59E00NLE X-Received: by 2002:a0d:e690:0:b0:564:c747:64f4 with SMTP id p138-20020a0de690000000b00564c74764f4mr2136197ywe.11.1685445790554; Tue, 30 May 2023 04:23:10 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6jIygVSWQo1Ba6u9uRLR9TNaT35DJIA+8VSsaPCDV0jIt5R2EbENTrJnF1IRxg2W41P9gBaA== X-Received: by 2002:a0d:e690:0:b0:564:c747:64f4 with SMTP id p138-20020a0de690000000b00564c74764f4mr2136184ywe.11.1685445790207; Tue, 30 May 2023 04:23:10 -0700 (PDT) Received: from [192.168.0.241] ([198.48.244.52]) by smtp.gmail.com with ESMTPSA id w14-20020a81a20e000000b0054f50f71834sm3952905ywg.124.2023.05.30.04.23.09 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 30 May 2023 04:23:09 -0700 (PDT) Message-ID: <695abfe1-2cd5-2515-ca0f-fcbb34666c26@redhat.com> Date: Tue, 30 May 2023 07:23:08 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: [PATCH v3] elf: Make more functions available for binding during dlclose (bug 30425) To: Florian Weimer , libc-alpha@sourceware.org References: <875y8aw3ut.fsf@oldenburg.str.redhat.com> From: Carlos O'Donell Organization: Red Hat In-Reply-To: <875y8aw3ut.fsf@oldenburg.str.redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 5/30/23 05:44, Florian Weimer via Libc-alpha wrote: > Previously, after destructors for a DSO have been invoked, ld.so refused > to bind against that DSO in all cases. Relax this restriction somewhat > if the referencing object is itself a DSO that is being unloaded. This > assumes that the symbol reference is not going to be stored anywhere. > > The situation in the test case can arise fairly easily with C++ and > objects that are built with different optimization levels and therefore > define different functions with vague linkage. Thanks for the v3! Passes pre-commit CI for 32-bit i686. LGTM. Reviewed-by: Carlos O'Donell > > --- > v3: Comment updates. > > elf/Makefile | 8 ++++++++ > elf/dl-lookup.c | 21 +++++++++++++++++-- > elf/tst-dlclose-lazy-mod1.c | 36 +++++++++++++++++++++++++++++++++ > elf/tst-dlclose-lazy-mod2.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ > elf/tst-dlclose-lazy.c | 47 +++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 159 insertions(+), 2 deletions(-) > > diff --git a/elf/Makefile b/elf/Makefile > index 264737110b..3bfc305d98 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -396,6 +396,7 @@ tests += \ > tst-debug1 \ > tst-deep1 \ > tst-dl-is_dso \ > + tst-dlclose-lazy \ OK. > tst-dlmodcount \ > tst-dlmopen-dlerror \ > tst-dlmopen-gethostbyname \ > @@ -816,6 +817,8 @@ modules-names += \ > tst-dl_find_object-mod7 \ > tst-dl_find_object-mod8 \ > tst-dl_find_object-mod9 \ > + tst-dlclose-lazy-mod1 \ > + tst-dlclose-lazy-mod2 \ OK. > tst-dlmopen-dlerror-mod \ > tst-dlmopen-gethostbyname-mod \ > tst-dlmopen-twice-mod1 \ > @@ -3001,3 +3004,8 @@ $(objpfx)tst-sprof-basic.out: tst-sprof-basic.sh $(objpfx)tst-sprof-basic > '$(run-program-env)' > $@; \ > $(evaluate-test) > generated += tst-sprof-mod.so.profile > + > +LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed > +$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so > +$(objpfx)tst-dlclose-lazy.out: \ > + $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so > diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c > index 05f36a2507..a8f48fed12 100644 > --- a/elf/dl-lookup.c > +++ b/elf/dl-lookup.c > @@ -366,8 +366,25 @@ do_lookup_x (const char *undef_name, unsigned int new_hash, > if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable) > continue; > > - /* Do not look into objects which are going to be removed. */ > - if (map->l_removed) > + /* Do not look into objects which are going to be removed, > + except when the referencing object itself is being removed. > + > + The second part covers the situation when an object lazily > + binds to another object while running its destructor, but the > + destructor of the other object has already run, so that > + dlclose has set l_removed. It may not always be obvious how > + to avoid such a scenario to programmers creating DSOs, > + particularly if C++ vague linkage is involved and triggers > + symbol interposition. > + > + Accepting these to-be-removed objects makes the lazy and > + BIND_NOW cases more similar. (With BIND_NOW, the symbol is > + resolved early, before the destructor call, so the issue does > + not arise.). Behavior matches the constructor scenario: the > + implementation allows binding to symbols of objects whose > + constructors have not run. In fact, not doing this would be > + mostly incompatible with symbol interposition. */ > + if (map->l_removed && !(undef_map != NULL && undef_map->l_removed)) > continue; > > /* Print some debugging info if wanted. */ > diff --git a/elf/tst-dlclose-lazy-mod1.c b/elf/tst-dlclose-lazy-mod1.c > new file mode 100644 > index 0000000000..8439dc1925 > --- /dev/null > +++ b/elf/tst-dlclose-lazy-mod1.c > @@ -0,0 +1,36 @@ > +/* Lazy binding during dlclose. Directly loaded module. > + Copyright (C) 2023 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + . */ > + > +/* This function is called from exported_function below. It is only > + defined in this module. The weak attribute mimics how G++ > + implements vague linkage for C++. */ OK. > +void __attribute__ ((weak)) > +lazily_bound_exported_function (void) > +{ > +} > + > +/* Called from tst-dlclose-lazy-mod2.so. */ > +void > +exported_function (int call_it) > +{ > + if (call_it) > + /* Previous to the fix this would crash when called during dlclose > + since symbols from the DSO were no longer available for binding > + (bug 30425) after the DSO started being closed by dlclose. */ > + lazily_bound_exported_function (); > +} > diff --git a/elf/tst-dlclose-lazy-mod2.c b/elf/tst-dlclose-lazy-mod2.c > new file mode 100644 > index 0000000000..767f69ffdb > --- /dev/null > +++ b/elf/tst-dlclose-lazy-mod2.c > @@ -0,0 +1,49 @@ > +/* Lazy binding during dlclose. Indirectly loaded module. > + Copyright (C) 2023 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + . */ > + > +#include > +#include > + > +void > +exported_function (int ignored) > +{ > + /* This function is interposed from tst-dlclose-lazy-mod1.so and > + thus never called. */ > + abort (); > +} > + > +static void __attribute__ ((constructor)) > +init (void) > +{ > + puts ("info: tst-dlclose-lazy-mod2.so constructor called"); > + > + /* Trigger lazy binding to the definition in > + tst-dlclose-lazy-mod1.so, but not for > + lazily_bound_exported_function in that module. */ > + exported_function (0); > +} > + > +static void __attribute__ ((destructor)) > +fini (void) > +{ > + puts ("info: tst-dlclose-lazy-mod2.so destructor called"); > + > + /* Trigger the lazily_bound_exported_function call in > + exported_function in tst-dlclose-lazy-mod1.so. */ > + exported_function (1); > +} > diff --git a/elf/tst-dlclose-lazy.c b/elf/tst-dlclose-lazy.c > new file mode 100644 > index 0000000000..976a6bb6f6 > --- /dev/null > +++ b/elf/tst-dlclose-lazy.c > @@ -0,0 +1,47 @@ > +/* Test lazy binding during dlclose (bug 30425). > + Copyright (C) 2023 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + . */ > + > +/* This test re-creates a situation that can arise naturally for C++ > + applications due to the use of vague linkage and differences in the > + set of compiler-emitted functions. A function in > + tst-dlclose-lazy-mod1.so (exported_function) interposes a function > + in tst-dlclose-lazy-mod2.so. This function is called from the > + destructor in tst-dlclose-lazy-mod2.so, after the destructor for > + tst-dlclose-lazy-mod1.so has already completed. Prior to the fix > + for bug 30425, this would lead to a lazy binding failure in > + tst-dlclose-lazy-mod1.so because dlclose had already marked the DSO > + as unavailable for binding (by setting l_removed). */ OK. > + > +#include > +#include > +#include > + > +int > +main (void) > +{ > + /* Load tst-dlclose-lazy-mod1.so, indirectly loading > + tst-dlclose-lazy-mod2.so. */ > + void *handle = xdlopen ("tst-dlclose-lazy-mod1.so", RTLD_GLOBAL | RTLD_LAZY); > + > + /* Invoke the destructor of tst-dlclose-lazy-mod2.so, which calls > + into tst-dlclose-lazy-mod1.so after its destructor has been > + called. */ > + xdlclose (handle); > + > + return 0; > +} > > base-commit: 3eed5f3a1ee356969afb403a1cf18d06f8d2d98a > -- Cheers, Carlos.