From patchwork Fri Nov 29 16:55:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1202528 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-107553-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="JOpxCIfp"; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="HAnRmwNr"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47PgcN54jHz9sPj for ; Sat, 30 Nov 2019 03:55:32 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type:content-transfer-encoding; q=dns; s=default; b=iiF abenMResMFyazidv4BQrwsd6ztSkadiZTjAu7gg79hn3EojJ4MWvbZWU8RF1x+v8 ahCe7Z1GJbqNkxZ00yedOuuu6eapSQ1ViH6tTJM4Mx4VxX6RhO7/w4aBfArKxZqm aVGSalxuVlqAfe11oKLwc1NrTGCh8dVafXvUkE9Q= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type:content-transfer-encoding; s=default; bh=vyCTqiEXT ovpswzK/4EONW7hRiQ=; b=JOpxCIfp9MbEpom4dfwVarsb9f76hzRfkyxVWMc/o UofiiwNxeLOUh2rotEDFmA/MKsQMtFLqFO/s+TCqHA4Mj5pAZOj2UIVGUqXLnoPk GDQdDCQGcETR8KLI+G5GCfQmlMQrpSQ7MyHtY02hELXqEm19S1Jpm3GzAFuqj0q1 e4= Received: (qmail 3385 invoked by alias); 29 Nov 2019 16:55:26 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 3371 invoked by uid 89); 29 Nov 2019 16:55:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.1 spammy=6158 X-HELO: us-smtp-delivery-1.mimecast.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1575046522; 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; bh=SLBwXaq3sVuC8keDn0s/zNQFMzg5ygtUyxVBOghUGzo=; b=HAnRmwNrQavPMzd/YMalhcZPaELH7eMjWLb9MY2c9XPmCjDZQ2KowCo7qOYg+oGm9ua6Ia TWHvKhyoZTWCSn9elEsP+Mk3mJeoDiN31IDnEjfg/duVG2MzJ30D9HqPyEM+k0i5gHwFjs yH8oD4hRXIRYZgj3v+yovx0X2HEfCWs= From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH] elf: Do not run IFUNC resolvers for LD_DEBUG=unused [BZ #24214] Date: Fri, 29 Nov 2019 17:55:17 +0100 Message-ID: <87y2vy1v2i.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 Tested on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, s390-linux-gnu, s390x-linux-gnu, powerpc64le-linux-gnu. build-many-glibcs.py is still running, but looks good so far. Thanks, Florian 8<------------------------------------------------------------------8< This commit adds missing skip_ifunc checks to aarch64, arm, i386, sparc, and x86_64. A new test case ensures that IRELATIVE IFUNC resolvers do not run in various diagnostic modes of the dynamic loader. ----- elf/Makefile | 16 +++++++++++ elf/tst-ifunc-fault-bindnow.c | 21 ++++++++++++++ elf/tst-ifunc-fault-lazy.c | 57 ++++++++++++++++++++++++++++++++++++++ sysdeps/aarch64/dl-machine.h | 3 +- sysdeps/arm/dl-machine.h | 6 ++-- sysdeps/i386/dl-machine.h | 6 ++-- sysdeps/sparc/sparc32/dl-machine.h | 6 ++-- sysdeps/sparc/sparc64/dl-machine.h | 6 ++-- sysdeps/x86_64/dl-machine.h | 3 +- 9 files changed, 114 insertions(+), 10 deletions(-) diff --git a/elf/Makefile b/elf/Makefile index 305bed2d38..f825354d3f 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -348,6 +348,7 @@ tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \ tests-static += $(tests-ifuncstatic) tests-internal += $(tests-ifuncstatic) ifeq (yes,$(build-shared)) +tests += tst-ifunc-fault-lazy tst-ifunc-fault-bindnow # Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8. tests-internal += \ ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ @@ -1354,6 +1355,21 @@ $(objpfx)ifuncmain5static: $(addprefix $(objpfx),ifuncdep5.o) $(objpfx)ifuncmain5staticpic: $(addprefix $(objpfx),ifuncdep5pic.o) $(objpfx)ifuncmain5picstatic: $(addprefix $(objpfx),ifuncdep5pic.o) +LDFLAGS-tst-ifunc-fault-lazy = -Wl,-z,lazy +LDFLAGS-tst-ifunc-fault-bindnow = -Wl,-z,now +define tst-ifunc-fault-script +( $(objpfx)ld.so --verify --library-path $(objpfx) $^ \ + && LD_TRACE_LOADED_OBJECTS=1 $(objpfx)ld.so --library-path $(objpfx) $^ \ + && LD_TRACE_LOADED_OBJECTS=1 LD_DEBUG=unused \ + $(objpfx)ld.so --library-path $(objpfx) $^ \ +) > $@; $(evaluate-test) +endef +$(objpfx)tst-ifunc-fault-lazy.out: $(objpfx)tst-ifunc-fault-lazy $(objpfx)ld.so + $(tst-ifunc-fault-script) +$(objpfx)tst-ifunc-fault-bindnow.out: $(objpfx)tst-ifunc-fault-bindnow \ + $(objpfx)ld.so + $(tst-ifunc-fault-script) + $(objpfx)tst-unique1: $(libdl) $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \ $(objpfx)tst-unique1mod2.so diff --git a/elf/tst-ifunc-fault-bindnow.c b/elf/tst-ifunc-fault-bindnow.c new file mode 100644 index 0000000000..d767c1f1c1 --- /dev/null +++ b/elf/tst-ifunc-fault-bindnow.c @@ -0,0 +1,21 @@ +/* Program with local IFUNC resolver which crashes. BIND_NOW variant. + Copyright (C) 2019 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 + . */ + +/* The code is the same as the lazy variant. It is just linked + differently. */ +#include "tst-ifunc-fault-lazy.c" diff --git a/elf/tst-ifunc-fault-lazy.c b/elf/tst-ifunc-fault-lazy.c new file mode 100644 index 0000000000..3389de273f --- /dev/null +++ b/elf/tst-ifunc-fault-lazy.c @@ -0,0 +1,57 @@ +/* Program with local IFUNC resolver which crashes, for testing bug 24214. + Copyright (C) 2019 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 + . */ + +/* The construct below is expected to produce an IRELATIVE relocation + with an IFUNC resolver that crashes. ldd should not performs such + relocations. */ + +#include + +#ifdef HAVE_GCC_IFUNC + +# include + +static void +implementation (void) +{ + /* Produce a crash, without depending on any relocations. */ + volatile char *volatile p = NULL; + *p = 0; +} + +static __typeof__ (implementation) * +resolver (void) +{ + /* Produce a crash, without depending on any relocations. */ + volatile char *volatile p = NULL; + *p = 0; + return implementation; +} + +static void magic (void) __attribute__ ((ifunc ("resolver"))); + +void (*magic_ptr) (void) = magic; + +#endif /* HAVE_GCC_IFUNC */ + +/* The program is expected not to run. */ +int +main (void) +{ + return 1; +} diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h index 10b91c33ae..bf6b9d0e7d 100644 --- a/sysdeps/aarch64/dl-machine.h +++ b/sysdeps/aarch64/dl-machine.h @@ -358,7 +358,8 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, case AARCH64_R(IRELATIVE): value = map->l_addr + reloc->r_addend; - value = elf_ifunc_invoke (value); + if (__glibc_likely (!skip_ifunc)) + value = elf_ifunc_invoke (value); *reloc_addr = value; break; diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index eeb3adfff2..27dffc71bf 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -522,7 +522,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, break; case R_ARM_IRELATIVE: value = map->l_addr + *reloc_addr; - value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); *reloc_addr = value; break; #endif @@ -614,7 +615,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, break; case R_ARM_IRELATIVE: value = map->l_addr + reloc->r_addend; - value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); *reloc_addr = value; break; #endif diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 1e2a3b333d..e225aa3739 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -480,7 +480,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, break; case R_386_IRELATIVE: value = map->l_addr + *reloc_addr; - value = ((Elf32_Addr (*) (void)) value) (); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (void)) value) (); *reloc_addr = value; break; default: @@ -627,7 +628,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, # endif /* !RESOLVE_CONFLICT_FIND_MAP */ case R_386_IRELATIVE: value = map->l_addr + reloc->r_addend; - value = ((Elf32_Addr (*) (void)) value) (); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (void)) value) (); *reloc_addr = value; break; default: diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h index 1d8da32c47..359a004271 100644 --- a/sysdeps/sparc/sparc32/dl-machine.h +++ b/sysdeps/sparc/sparc32/dl-machine.h @@ -425,11 +425,13 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, *reloc_addr = value; break; case R_SPARC_IRELATIVE: - value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); *reloc_addr = value; break; case R_SPARC_JMP_IREL: - value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); /* Fall thru */ case R_SPARC_JMP_SLOT: { diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h index ce1261d2a0..0acaf92a53 100644 --- a/sysdeps/sparc/sparc64/dl-machine.h +++ b/sysdeps/sparc/sparc64/dl-machine.h @@ -450,11 +450,13 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, *reloc_addr = value; break; case R_SPARC_IRELATIVE: - value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap)); *reloc_addr = value; break; case R_SPARC_JMP_IREL: - value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap)); + if (__glibc_likely (!skip_ifunc)) + value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap)); /* 'high' is always zero, for large PLT entries the linker emits an R_SPARC_IRELATIVE. */ #ifdef RESOLVE_CONFLICT_FIND_MAP diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index f17f5fb7cd..58260c7876 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -512,7 +512,8 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, # endif case R_X86_64_IRELATIVE: value = map->l_addr + reloc->r_addend; - value = ((ElfW(Addr) (*) (void)) value) (); + if (__glibc_likely (!skip_ifunc)) + value = ((ElfW(Addr) (*) (void)) value) (); *reloc_addr = value; break; default: