From patchwork Tue Sep 15 02:12:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 143767 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 06CE04BAE7EE for ; Tue, 15 Sep 2026 02:16:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 06CE04BAE7EE Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=i+EY1BMj X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 7B7894BAE7DE for ; Tue, 15 Sep 2026 02:15:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7B7894BAE7DE Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7B7894BAE7DE Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1789438543; cv=none; b=FK97RxM8A8VYR5JGPOwIdaTWoY84ZviNNYPFznLlxkSnKULcAoxzuYLiHm6NcqfvWoBvrUN2WOA4++rC5b68BeOA4IMSMAixaS99dQ4+9eYtFtxfzt5T54xzGrpjmOXR7dvxmQGH+zEILFTX8ERO+FJBemSfZfIGRfG0vq8zdYA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1789438543; c=relaxed/simple; bh=7BB83vMWVJqgMRwvBK+2RsCA4h40gHIjEyA2UbE4zR8=; h=DKIM-Signature:Message-Id:From:Date:Subject:To; b=Q1yA13PV4/IIorbZAX7kuwX3evpQInA2E94UvxsC1lA93GtHnGtP2qLn4S5eGLhqC5sB2cgI/SpwRlO66UYK6c2wdt4VO1SOFvjI/XOhUQSfOHH4psdvgu6poF0FQChwdy5hymgW/IW2R/zjninsIFcFYM0MZKBtRI7mChpa7kE= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=i+EY1BMj DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7B7894BAE7DE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1789438543; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type; bh=BRYtoAifdNqfqLyEWPFBjIydFUaYob82SB1tRwV8D3Q=; b=i+EY1BMjv4JgDKM1El+GWbelk8s9lLXttMZsnArl+bO/yPoybKvuPs88OUsGhQnKPhH8W/ b2XY4kkMrG82XXjBBuqBwoQM9m4HP6T7UutGDZ9CNWaGpSM39bu2seE/I0cdPyxygtQXxB lXuXAZtCxrrUZOTI5esevqi5/dUC0qc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-449-fNVQRubiNya0yR5N3V5xvw-1; Mon, 14 Sep 2026 22:15:39 -0400 X-MC-Unique: fNVQRubiNya0yR5N3V5xvw-1 X-Mimecast-MFC-AGG-ID: fNVQRubiNya0yR5N3V5xvw_1789438539 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DF63E184B831 for ; Tue, 15 Sep 2026 02:15:38 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.88.18]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A060018005B5 for ; Tue, 15 Sep 2026 02:15:38 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.16.1/8.16.1) with ESMTP id 68F2FZAB1071774 for ; Mon, 14 Sep 2026 22:15:35 -0400 Message-Id: From: DJ Delorie Date: Mon, 14 Sep 2026 22:12:04 -0400 Subject: [PATCH v2 1/1] rtld: add tunable for audit-specific surplus TLS To: libc-alpha@sourceware.org X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 2 X-Mimecast-MFC-PROC-ID: rbql5wAQ3zVS73qn4FdHElRLRUvFZEsJ9bd64yRzURo_1789438539 X-Mimecast-Originator: redhat.com Content-type: text/plain; charset=UTF-8 X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Add glibc.rtld.audit_static_tls which specifies additional surplus TLS just for audit modules, as when audit modules are used the loader can't compute TLS space before the auditors run. This surplus exists until the loader can recompute the TLS needs, and is reduced for future threads. --- Changes in v2: - rebased - fix tst-rtld-list-tunables elf/dl-tls.c | 43 ++++++++++++++++++++++++++++++++-- elf/dl-tunables.list | 5 ++++ elf/rtld.c | 2 ++ elf/tst-rtld-list-tunables.exp | 1 + manual/tunables.texi | 22 +++++++++++++++++ sysdeps/generic/ldsodefs.h | 5 ++++ 6 files changed, 76 insertions(+), 2 deletions(-) diff --git a/elf/dl-tls.c b/elf/dl-tls.c index 31b26fe8d3..46bc76836c 100644 --- a/elf/dl-tls.c +++ b/elf/dl-tls.c @@ -130,6 +130,10 @@ tls_static_surplus (int nns, int opt_tls) tunable, and sets an additional minimum alignment on the TLS data. */ static size_t optional_static_tls_alignment = 0; +static size_t dl_audit_tls = 0; +static size_t dl_original_optional = 0; +static size_t dl_original_surplus = 0; +static size_t dl_original_align = 1; /* Calculate the size of the static TLS surplus, when the given number of audit modules are loaded. Must be called after the @@ -145,6 +149,8 @@ _dl_tls_static_surplus_init (size_t naudit) /* Ignore invalid requests. */ if (! powerof2 (optional_static_tls_alignment)) optional_static_tls_alignment = 0; + if (naudit) + dl_audit_tls = TUNABLE_GET (audit_static_tls, size_t, NULL); if (nns > DL_NNS) nns = DL_NNS; if (DL_NNS - nns < naudit) @@ -155,6 +161,33 @@ _dl_tls_static_surplus_init (size_t naudit) GL(dl_tls_static_optional) = opt_tls; assert (LEGACY_TLS >= 0); GLRO(dl_tls_static_surplus) = tls_static_surplus (nns, opt_tls) + LEGACY_TLS; + + if (dl_audit_tls > 0) + { + if (dl_audit_tls >= SIZE_MAX / 2) + _dl_fatal_printf ("glibc.rtld.audit_static_tls exceeds SIZE_MAX/2\n"); + dl_original_optional = GL(dl_tls_static_optional); + dl_original_surplus = GLRO(dl_tls_static_surplus); + } +} + +/* Undo as much of the audit-specific extra TLS space accounted for + above, as possible. After this function, the unused amount of TLS + must be at least the dl_tls_static_surplus amount. */ +void +_dl_tls_prune_audit_storage (void) +{ + if (dl_audit_tls > 0) + { + GL(dl_tls_static_optional) = dl_original_optional; + GLRO(dl_tls_static_surplus) = dl_original_surplus; + GLRO(dl_tls_static_size) = roundup (GL(dl_tls_static_used) + + dl_original_surplus, + dl_original_align); +#ifdef TLS_TCB_AT_TP + GLRO(dl_tls_static_size) += TLS_TCB_SIZE; +#endif + } } /* Out-of-memory handler. */ @@ -380,9 +413,12 @@ _dl_determine_tlsoffset (void) _dl_extra_tls_set_offset (-offset); GL(dl_tls_static_used) = offset; - GLRO (dl_tls_static_size) = (roundup (offset + GLRO(dl_tls_static_surplus), + GLRO (dl_tls_static_size) = (roundup (offset + + GLRO(dl_tls_static_surplus) + + dl_audit_tls, max_align) + TLS_TCB_SIZE); + dl_original_align = max_align; #elif TLS_DTV_AT_TP /* The TLS blocks start right after the TCB. */ size_t offset = TLS_TCB_SIZE; @@ -467,8 +503,11 @@ _dl_determine_tlsoffset (void) offset += extra_tls_size; GL(dl_tls_static_used) = offset; - GLRO (dl_tls_static_size) = roundup (offset + GLRO(dl_tls_static_surplus), + GLRO (dl_tls_static_size) = roundup (offset + + GLRO(dl_tls_static_surplus) + + dl_audit_tls, TCB_ALIGNMENT); + dl_original_align = TCP_ALIGNMENT; #else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" #endif diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list index 4c78444542..d8daf30ab0 100644 --- a/elf/dl-tunables.list +++ b/elf/dl-tunables.list @@ -106,6 +106,11 @@ glibc { minval: 0 default: 0 } + audit_static_tls { + type: SIZE_T + minval: 0 + default: 0 + } enable_secure { type: INT_32 minval: 0 diff --git a/elf/rtld.c b/elf/rtld.c index 324393d606..4f1c2374df 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -2353,6 +2353,8 @@ dl_main (const ElfW(Phdr) *phdr, _dl_debug_post_relocate (main_map); } + _dl_tls_prune_audit_storage (); + /* All ld.so initialization is complete. Apply RELRO. */ _dl_protect_relro (&_dl_rtld_map); diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp index 17520d6b31..d208804723 100644 --- a/elf/tst-rtld-list-tunables.exp +++ b/elf/tst-rtld-list-tunables.exp @@ -10,6 +10,7 @@ glibc.malloc.tcache_count: 0x0 (min: 0x0, max: 0x[f]+) glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+) glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0x[f]+) glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+) +glibc.rtld.audit_static_tls: 0x0 (min: 0x0, max: 0x[f]+) glibc.rtld.dynamic_sort: 2 (min: 1, max: 2) glibc.rtld.enable_secure: 0 (min: 0, max: 1) glibc.rtld.execstack: 1 (min: 0, max: 2) diff --git a/manual/tunables.texi b/manual/tunables.texi index 2cb516b1dc..12565c6ae8 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -429,6 +429,28 @@ for (for example) audit modules that have a higher-than-default alignment requirement. @end deftp +@deftp Tunable glibc.rtld.audit_static_tls +Sets an additional amount of memory to be allocated in the initial +thread's TLS when one or more auditing modules are to be loaded. +Since auditing modules must run before the loader is done loading +dynamic objects, the loader cannot know how much TLS space is needed +before it must create the first TLS area. If no auditing modules are +loaded, the initial TLS size can be computed after the dynamic objects +are loaded. When this tunable is used, the initial TLS size can be +very large, and the size computation is adjusted after loading is +complete, so that any additional threads created will have a more +suitable TLS size (including any optional space as specified by +@code{glibc.rtld.optional_static_tls}). The default is to not +allocate any additional TLS for audit modules. + +As an example, if a program required 1MB of TLS space and specified an +optional 1MB surplus, normally every thread would have 2MB of TLS +space. If an auditing module requires 3MB of TLS space, and 5MB of +audit TLS was specified by this tunable, the main thread would have +7MB of TLS space (2MB plus the specified 5MB) and every other thread +would have 5MB (2MB plus the actual 3MB). +@end deftp + @deftp Tunable glibc.rtld.dynamic_sort Sets the algorithm to use for DSO sorting, valid values are @samp{1} and @samp{2}. For value of @samp{1}, an older O(n^3) algorithm is used, which is diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 305ca6e0df..54535452b3 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1184,6 +1184,11 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; number of audit modules are loaded. */ void _dl_tls_static_surplus_init (size_t naudit) attribute_hidden; +/* After startup is complete but before user entry, the size of the + audit modules is more knowable so we can reduce the TLS size + accordingly. */ +void _dl_tls_prune_audit_storage (void) attribute_hidden; + /* This function is called very early from dl_main to set up TLS and other thread-related data structures. */ void __tls_pre_init_tp (void) attribute_hidden;