From patchwork Wed Jul 7 18:26:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 44210 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D303D396E837 for ; Wed, 7 Jul 2021 18:29:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D303D396E837 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1625682594; bh=cs2KKroWMWXktGb+fCfLLskmj8w6pVKkpkwu7esfFxw=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=JW3mWJQh+QIwFYmEucbRnGWoGMl5DomfVO1GdPp09FE45Gb5toihea/wAizSeAW8Q R1Yq7AtoA0unrDD24iDAHFPDRjp6I6OwQZkuiQlmIxaE7skIxergz9lRaruL1/aWDB xMXZwlrBWCL2LDTnfNl5YPpKQuVgctEtRdU25rDY= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 0A0B7396E05C for ; Wed, 7 Jul 2021 18:29:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0A0B7396E05C Received: by mail-pf1-x42e.google.com with SMTP id a127so2986934pfa.10 for ; Wed, 07 Jul 2021 11:29:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cs2KKroWMWXktGb+fCfLLskmj8w6pVKkpkwu7esfFxw=; b=Lur4ZarYeP1BoLOTgBhZuLI1Lgk2USuM1wmeaktxs/tTbdxVq7SMoe0r+DVV5bQ3ax 9y7CQn8DrFY4tLl8Fsk854UXfb8o6gweUwKTlKUZkX5EacuIW49aArzWFdAPiV0Pj9UQ YIv3gw0xV3wwmnpiR7oLrb5/wrhEVZ9A3EpDKdv6H2viCMXQUi+mOxtIcDXfjp4ihlCn e3uN5JROLQaG2ROMw5NBAzofBaa6hYM1l9XC8ulg3ZD4EtJ1YH+9LzFw+Jix1kyP8nd9 ay/87KvB5jCIiNEA48XX37n2KCPdm+Tz3TB0BLaTna5/d7oLzbxkcqgz1JosqjAEtnT0 uJ3w== X-Gm-Message-State: AOAM530UryLjq1FozT6lJeuFOZZ9aCoxR2jwBQNbpvqcoEawKZAD6eTC 5YHgO3hVX4wFlzrfzZQNRxxIj5i7TSg3JQ== X-Google-Smtp-Source: ABdhPJxLA8+7irv7OJA8LfPLu3A5zqLYjYn02DBku5JDt5c3VAlPtJpsXHmvXzVxuh/qj82Sxka+Lw== X-Received: by 2002:aa7:8491:0:b029:310:927a:df90 with SMTP id u17-20020aa784910000b0290310927adf90mr26884004pfn.46.1625682570920; Wed, 07 Jul 2021 11:29:30 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id fv8sm18868662pjb.21.2021.07.07.11.29.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jul 2021 11:29:30 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 2/5] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Date: Wed, 7 Jul 2021 15:26:07 -0300 Message-Id: <20210707182610.3940620-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210707182610.3940620-1-adhemerval.zanella@linaro.org> References: <20210707182610.3940620-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Cc: Alexander Monakov , John Mellor-Crummey Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The rtld-audit interfaces introduce a slowdown due to enabling profiling instrumentation (as if LD_AUDIT implied LD_PROFILE). However, instrumenting is only necessary if one of audit libraries provides PLT (la_plt{enter,exit} symbols) or symbol bynding (la_symbind{32,64})hooks. Otherwise, the slowdown can be avoided. The following patch adjusts the logic that enables profiling to iterate over all audit modules and check if any of those provides a PLT hook. Co-authored-by: Alexander Monakov --- elf/Makefile | 13 +++++++++++- elf/dl-reloc.c | 13 +++++++++++- elf/rtld.c | 8 +------- elf/tst-audit18a.c | 39 +++++++++++++++++++++++++++++++++++ elf/tst-audit18b.c | 30 +++++++++++++++++++++++++++ elf/tst-audit18bmod.c | 22 ++++++++++++++++++++ elf/tst-auditmod18a.c | 25 ++++++++++++++++++++++ elf/tst-auditmod18b.c | 48 +++++++++++++++++++++++++++++++++++++++++++ include/link.h | 2 ++ 9 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 elf/tst-audit18a.c create mode 100644 elf/tst-audit18b.c create mode 100644 elf/tst-audit18bmod.c create mode 100644 elf/tst-auditmod18a.c create mode 100644 elf/tst-auditmod18b.c diff --git a/elf/Makefile b/elf/Makefile index 5214196de6..a26f5ce320 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -219,7 +219,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \ tst-dlopenfail-2 \ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ - tst-audit14 tst-audit15 tst-audit16 tst-audit17 \ + tst-audit14 tst-audit15 tst-audit16 tst-audit17 tst-audit18a \ + tst-audit18b \ tst-single_threaded tst-single_threaded-pthread \ tst-tls-ie tst-tls-ie-dlmopen argv0test \ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ @@ -294,6 +295,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-unique1mod1 tst-unique1mod2 \ tst-unique2mod1 tst-unique2mod2 \ tst-auditmod9a tst-auditmod9b \ + tst-auditmod18a tst-audit18bmod tst-auditmod18b \ $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ tst-nodelete-uniquemod tst-nodelete-rtldmod \ tst-nodelete-zmod \ @@ -1478,6 +1480,15 @@ $(objpfx)tst-auditmod17.so: $(objpfx)tst-auditmod17.os mv -f $@.new $@ tst-audit17-ENV = LD_AUDIT=$(objpfx)tst-auditmod17.so +$(objpfx)tst-audit18a.out: $(objpfx)tst-auditmod18a.so +tst-audit18a-ENV = LD_AUDIT=$(objpfx)tst-auditmod18a.so +$(objpfx)tst-audit18b.out: $(objpfx)tst-auditmod18b.so \ + $(objpfx)tst-audit18bmod.so +$(objpfx)tst-audit18b: $(objpfx)tst-audit18bmod.so +LDFLAGS-tst-audit18bmod.so = -Wl,-z,now +LDFLAGS-tst-audit18b = -Wl,-z,now +tst-audit18b-ENV = LD_AUDIT=$(objpfx)tst-auditmod18b.so + # tst-sonamemove links against an older implementation of the library. LDFLAGS-tst-sonamemove-linkmod1.so = \ -Wl,--version-script=tst-sonamemove-linkmod1.map \ diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index e13a672ade..998cfef099 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -181,7 +181,18 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], #ifdef SHARED /* If we are auditing, install the same handlers we need for profiling. */ if ((reloc_mode & __RTLD_AUDIT) == 0) - consider_profiling |= GLRO(dl_audit) != NULL; + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + /* Profiling is needed only if PLT hooks are provided. */ + if (afct->symbind != NULL + || afct->ARCH_LA_PLTENTER != NULL + || afct->ARCH_LA_PLTEXIT != NULL) + consider_profiling = 1; + afct = afct->next; + } + } #elif defined PROF /* Never use dynamic linker profiling for gprof profiling code. */ # define consider_profiling 0 diff --git a/elf/rtld.c b/elf/rtld.c index fbbd60b446..bf9eb5a33e 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1014,13 +1014,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); "la_objsearch\0" "la_objopen\0" "la_preinit\0" -#if __ELF_NATIVE_CLASS == 32 - "la_symbind32\0" -#elif __ELF_NATIVE_CLASS == 64 - "la_symbind64\0" -#else -# error "__ELF_NATIVE_CLASS must be defined" -#endif + LA_SYMBIND "\0" #define STRING(s) __STRING (s) "la_" STRING (ARCH_LA_PLTENTER) "\0" "la_" STRING (ARCH_LA_PLTEXIT) "\0" diff --git a/elf/tst-audit18a.c b/elf/tst-audit18a.c new file mode 100644 index 0000000000..36b781f9be --- /dev/null +++ b/elf/tst-audit18a.c @@ -0,0 +1,39 @@ +/* Check if DT_AUDIT a module without la_plt{enter,exit} symbols does not incur + in profiling (BZ#15533). + Copyright (C) 2021 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 + +/* We interpose the profile resolver and if it is called it means profiling is + enabled. */ +void +_dl_runtime_profile (ElfW(Word) addr) +{ + volatile int *p = NULL; + *p = 0; +} + +static int +do_test (void) +{ + printf ("..."); + return 0; +} + +#include diff --git a/elf/tst-audit18b.c b/elf/tst-audit18b.c new file mode 100644 index 0000000000..21381fe950 --- /dev/null +++ b/elf/tst-audit18b.c @@ -0,0 +1,30 @@ +/* Check if DT_AUDIT a module built with bind-now does trigger la_symbind. + Copyright (C) 2021 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 + . */ + +extern int foo (void); + +int +do_test (void) +{ + foo (); + /* If audit la_symbind() callback is called it will exit the test with + EXIT_SUCCESS. */ + return 1; +} + +#include diff --git a/elf/tst-audit18bmod.c b/elf/tst-audit18bmod.c new file mode 100644 index 0000000000..91f171b5bc --- /dev/null +++ b/elf/tst-audit18bmod.c @@ -0,0 +1,22 @@ +/* Check if DT_AUDIT a module built with bind-now does trigger la_symbind. + Copyright (C) 2021 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 + . */ + +int foo (void) +{ + return 0; +} diff --git a/elf/tst-auditmod18a.c b/elf/tst-auditmod18a.c new file mode 100644 index 0000000000..333db0077c --- /dev/null +++ b/elf/tst-auditmod18a.c @@ -0,0 +1,25 @@ +/* Check if DT_ADIT a module without la_plt{enter,exit} symbols does not incur + in profiling (BZ#15533). + Copyright (C) 2021 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 + . */ + +unsigned int +la_version (unsigned int version) +{ + return version; +} + diff --git a/elf/tst-auditmod18b.c b/elf/tst-auditmod18b.c new file mode 100644 index 0000000000..40ebcd5be2 --- /dev/null +++ b/elf/tst-auditmod18b.c @@ -0,0 +1,48 @@ +/* Check if DT_AUDIT a module built with bind-now does trigger la_symbind. + Copyright (C) 2021 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 +#include + +unsigned int +la_version (unsigned int version) +{ + return version; +} + +unsigned int +la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie) +{ + return LA_FLG_BINDFROM | LA_FLG_BINDTO; +} + +uintptr_t +#if __ELF_NATIVE_CLASS == 32 +la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, unsigned int *flags, const char *symname) +#else +la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, unsigned int *flags, const char *symname) +#endif +{ + /* Filter out glibc own symbols libc.so is not built with -z,now. */ + if (strcmp (symname, "foo") == 0) + exit (EXIT_SUCCESS); + return sym->st_value; +} diff --git a/include/link.h b/include/link.h index 4af16cb596..ebd0f511e2 100644 --- a/include/link.h +++ b/include/link.h @@ -355,8 +355,10 @@ struct auditstate #if __ELF_NATIVE_CLASS == 32 # define symbind symbind32 +# define LA_SYMBIND "la_symbind32" #elif __ELF_NATIVE_CLASS == 64 # define symbind symbind64 +# define LA_SYMBIND "la_symbind64" #else # error "__ELF_NATIVE_CLASS must be defined" #endif