From patchwork Sat Sep 25 00:42:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fangrui Song X-Patchwork-Id: 45430 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 777DF385801A for ; Sat, 25 Sep 2021 00:43:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 777DF385801A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1632530587; bh=F2DAgt8MALvlSOCJ7p7xtNRTeF8MtjxV5TM8Do72ciQ=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=TIIrTehHvIQLLzJDSNrR6Im3/uBa0B/781iJV8CEyrCdhzNg1Svq7aKqtQQrwq55X hkjscPrTK9/uytXQMMHR9jKgGJoL7VvN6icZAPiRSddXKHRDg+BUf0PL9TVC/dJ8vY KADFR2x6K3A1P1ZC1srFHlyThv2Y/fHgmQAUMUro= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by sourceware.org (Postfix) with ESMTPS id 2D4F13858403 for ; Sat, 25 Sep 2021 00:42:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2D4F13858403 Received: by mail-yb1-xb49.google.com with SMTP id a23-20020a25ae17000000b005ad73346312so5752858ybj.18 for ; Fri, 24 Sep 2021 17:42:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=F2DAgt8MALvlSOCJ7p7xtNRTeF8MtjxV5TM8Do72ciQ=; b=N2VQcWL1yt5slAzvSjC8xGi/RlPGfAwPfVVmpn+iHnNz/ireaCqJMyz1hhHCW7nxMk UnhokBkWw9/9QR4p8hJldtArcjUYtycORy+3Jv5Fu6CEelhnEc25FsvqsVtBXCKD7Maf XxiPO+Drrr/WbXxApNgY+nzdChaMgiTdk8Jm1+uIHwaKKELx5KESuy/dAFB831UdqwMH rnHFCrDHd9WZEI9xOIBPWJdo1r6Hl+swMxU0i+fObGmzf6C2rDJfJyVM4yb/PLMaonjI Rl4lh51msC/j0qGgV3e68jWSilY2feHEis/2zsDQx6my5aGNTUFdzNEedE3SL7TiZdgC RF6w== X-Gm-Message-State: AOAM530f0MbpTWLGf8icwkGZvWuDMJ61j1Ashf2tGCHLHBwI6C2sg0Zc JkgCoKt0wJfhsXUKxICHMpBnNTI+p/xCMiyEHYqI5L2C7VJvaPTBiYvUyjPiCSsAE3MfHNLjtcR Bgt/rNQJmUTE9WtFJkazn7m8/U0pMuyj28M96mlv9663uM/tDIaru9tuMgJUzlTYEezuw X-Google-Smtp-Source: ABdhPJx5dCI0E+VXx7mw474Yksq+710Cp+NrNFskHf8Hqw7nDG+xyIj3gOp/wycK+vLRjhQIZaVj72X4Jgbm X-Received: from maskray1.svl.corp.google.com ([2620:15c:2ce:200:41b5:2ffa:dc87:4ffa]) (user=maskray job=sendgmr) by 2002:a25:2142:: with SMTP id h63mr16773325ybh.70.1632530564666; Fri, 24 Sep 2021 17:42:44 -0700 (PDT) Date: Fri, 24 Sep 2021 17:42:27 -0700 Message-Id: <20210925004227.1829014-1-maskray@google.com> Mime-Version: 1.0 Subject: [PATCH] elf: Add __libc_get_static_tls_bounds [BZ #16291] To: libc-alpha@sourceware.org, Adhemerval Zanella , Florian Weimer X-Spam-Status: No, score=-19.5 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_INFOUSMEBIZ, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL 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: Fangrui Song via Libc-alpha From: Fangrui Song Reply-To: Fangrui Song Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Sanitizer runtimes need static TLS boundaries for a variety of use cases. * asan/hwasan/msan/tsan need to unpoison static TLS blocks to prevent false positives due to reusing the TLS blocks with a previous thread. * lsan needs TCB for pointers into pthread_setspecific regions. See https://maskray.me/blog/2021-02-14-all-about-thread-local-storage for details. compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp GetTls has to infer the static TLS bounds from TP, _dl_get_tls_static_info, and hard-coded TCB sizes. Currently this is somewhat robust for aarch64/powerpc64/x86-64 but is brittle for many other architectures. This patch implements __libc_get_static_tls_bounds@@GLIBC_PRIVATE which is available in Android bionic since API level 31. This API allows the sanitizer code to be more robust. _dl_get_tls_static_info@@GLIBC_PRIVATE can probably be removed when Clang/GCC sanitizers drop reliance on it. I am unclear whether the version should be GLIBC_2.*. Tested that on x86_64-linux-gnu, __libc_get_static_tls_bounds output matches sanitizer's GetTls. --- csu/libc-tls.c | 2 ++ elf/Versions | 3 +++ elf/dl-tls.c | 13 +++++++++++++ sysdeps/generic/ldsodefs.h | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 5515204863..433c9bfcc6 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -46,6 +46,8 @@ bool _dl_tls_dtv_gaps; struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; /* Number of modules in the static TLS block. */ size_t _dl_tls_static_nelem; +/* Start of the static TLS block. */ +void *_dl_tls_static_start; /* Size of the static TLS block. */ size_t _dl_tls_static_size; /* Size actually allocated in the static TLS block. */ diff --git a/elf/Versions b/elf/Versions index 775aab62af..ec095022f9 100644 --- a/elf/Versions +++ b/elf/Versions @@ -72,5 +72,8 @@ ld { # Set value of a tunable. __tunable_get_val; + + # Used by sanitizers. + __libc_get_static_tls_bounds; } } diff --git a/elf/dl-tls.c b/elf/dl-tls.c index d554ae4497..49edb0e452 100644 --- a/elf/dl-tls.c +++ b/elf/dl-tls.c @@ -400,6 +400,15 @@ _dl_get_tls_static_info (size_t *sizep, size_t *alignp) *alignp = GLRO (dl_tls_static_align); } +/* Get start and stop addresses of the static TLS block. This + function will be used by Clang and GCC sanitizers. */ +void +__libc_get_static_tls_bounds (void **startp, void **endp) +{ + *startp = GLRO (dl_tls_static_start); + *endp = GLRO (dl_tls_static_start) + GLRO (dl_tls_static_size); +} + /* Derive the location of the pointer to the start of the original allocation (before alignment) from the pointer to the TCB. */ static inline void ** @@ -448,6 +457,8 @@ _dl_allocate_tls_storage (void) /* Clear the TCB data structure. We can't ask the caller (i.e. libpthread) to do it, because we will initialize the DTV et al. */ memset (result, '\0', TLS_TCB_SIZE); + + GLRO (dl_tls_static_start) = aligned; #elif TLS_DTV_AT_TP /* Pre-TCB and TCB come before the TLS blocks. The layout computed in _dl_determine_tlsoffset assumes that the TCB is aligned to the @@ -462,6 +473,8 @@ _dl_allocate_tls_storage (void) it. We can't ask the caller (i.e. libpthread) to do it, because we will initialize the DTV et al. */ memset (result - TLS_PRE_TCB_SIZE, '\0', TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); + + GLRO (dl_tls_static_start) = result - TLS_PRE_TCB_SIZE; #endif /* Record the value of the original pointer for later diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index d49529da0d..ad4672da26 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -609,6 +609,9 @@ struct rtld_global_ro binaries, don't honor for PIEs). */ EXTERN ElfW(Addr) _dl_use_load_bias; + /* Start of the static TLS block. */ + EXTERN void *_dl_tls_static_start; + /* Size of the static TLS block. */ EXTERN size_t _dl_tls_static_size; @@ -1229,6 +1232,9 @@ rtld_hidden_proto (_dl_allocate_tls) /* Get size and alignment requirements of the static TLS block. */ extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp); +/* Get start and end addresses of the static TLS block. */ +extern void __libc_get_static_tls_bounds (void **startp, void **endp); + extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; /* These are internal entry points to the two halves of _dl_allocate_tls,