From patchwork Thu Aug 1 20:24:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 113550 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 2B897385840E for ; Tue, 3 Jun 2025 18:31:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2B897385840E 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=dmrqS6ch 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.133.124]) by sourceware.org (Postfix) with ESMTP id 1A25F385840E for ; Tue, 3 Jun 2025 18:29:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1A25F385840E 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 1A25F385840E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1748975359; cv=none; b=UnIkPiBkGMk5ABch8q11cOQfogqCE6IiF7WVZ5zSt/LxlYRK953bF3Sut0ZAGBJZDij3SMagCXeOfXjvq7p8iVIhXaxzSyfK8dQy2MmlVwmGFIixi+zb3UuoQrFIQtbBNZ1QZYvJutY+lc5f0u1TuXF6k0LLbiLYM8i2A7uFmGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1748975359; c=relaxed/simple; bh=0MRhS+bWNczBZbcI4gz76XeEWwxcyc4M8gpUWpsw/gM=; h=DKIM-Signature:From:To:Message-ID:Date:Subject; b=keaVuK/ODZKwXOZou3laH9qP7SU8d2ANK/Wb6CQaFzj3HznOMjBxkOA9ZPtOAsm4lyXP7f5JDScLGxYV7r5U6FJdNREBgpRbMyr7Uvg5BlMjZSIjFCBgcZLMNumZpG87AfCkpW9l+jBDcLw+wfYuLEks0e+DQwMRkCyewXDGcAo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1A25F385840E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1748975358; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type:in-reply-to:in-reply-to: references:references; bh=KByPgfljzU7wIE8FKB8kgXYZk6kCCK4yPlQF/8bsIVs=; b=dmrqS6ch8W2nKaz8TXpd1hE7LmXxZqoGXNfvNN0BCXKS5eAeITho0+4BxGYmKeqG3fX4at Pg4/FEF/HQdqcXROXVxR15zeFUVYsRwUKMLRXhOAB1/kK5tVMcY/J0VYzJhXY3AcPof2KK 5lJH3PEmeMSX2/5yY1dcTVRjP4U5Ig8= 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-554-faqBylN4NiWO_6NhgrZgVw-1; Tue, 03 Jun 2025 14:29:17 -0400 X-MC-Unique: faqBylN4NiWO_6NhgrZgVw-1 X-Mimecast-MFC-AGG-ID: faqBylN4NiWO_6NhgrZgVw_1748975357 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (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 007AC1800374 for ; Tue, 3 Jun 2025 18:29:17 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.88.144]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A4D8819560AB for ; Tue, 3 Jun 2025 18:29:16 +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 553ITEK21610580 for ; Tue, 3 Jun 2025 14:29:14 -0400 From: DJ Delorie To: libc-alpha@sourceware.org Message-ID: In-Reply-To: References: Date: Thu, 1 Aug 2024 16:24:22 -0400 Subject: [patch v4 4/4] Add system-wide tunables: Filters X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 2 X-Mimecast-MFC-PROC-ID: MZpqKTuQu7upNi2TupU7tuOrZwfS4lR43ISJEo6j1H0_1748975357 X-Mimecast-Originator: redhat.com Content-type: text/plain; charset=UTF-8 X-Spam-Status: No, score=-8.5 required=5.0 tests=BAYES_00, DATE_IN_PAST_96_XX, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 support for [prog] syntax where [prog] matches argv[0]. Tunables after such a line are limited to that prog. Note that this filter is reset when including a file or at end of file. --- csu/libc-start.c | 2 +- elf/Makefile | 4 + elf/cache.c | 3 +- elf/dl-tunables.c | 38 ++++++++-- elf/dl-tunables.h | 2 +- elf/tst-tunconf1.c | 17 +++++ elf/tst-tunconf1.root/etc/tunables.conf | 2 + elf/tst-tunconf1.root/ldconfig.run | 0 elf/tst-tunconf1.root/postclean.req | 0 elf/tunconf.c | 98 ++++++++++++++++++++++++- sysdeps/mach/hurd/dl-sysdep.c | 2 +- sysdeps/unix/sysv/linux/dl-sysdep.c | 2 +- 12 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 elf/tst-tunconf1.c create mode 100644 elf/tst-tunconf1.root/etc/tunables.conf create mode 100644 elf/tst-tunconf1.root/ldconfig.run create mode 100644 elf/tst-tunconf1.root/postclean.req diff --git a/csu/libc-start.c b/csu/libc-start.c index 6f3d52e223..a1c51a732f 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -264,7 +264,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), _dl_aux_init (auxvec); # endif - __tunables_init (__environ); + __tunables_init (__environ, argv); ARCH_INIT_CPU_FEATURES (); diff --git a/elf/Makefile b/elf/Makefile index 6538080b61..2785500eea 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -328,6 +328,7 @@ tests-internal := \ $(tests-static-internal) \ tst-tls1 \ tst-tls_tp_offset \ + tst-tunconf1 \ # tests-internal tests-static := $(tests-static-normal) $(tests-static-internal) @@ -338,6 +339,8 @@ tests-static += \ tst-tls9-static \ # tests-static +tst-tunconf1-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=5 + static-dlopen-environment = \ LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn tst-tls9-static-ENV = $(static-dlopen-environment) @@ -558,6 +561,7 @@ tests-container += \ tst-pldd \ tst-preload-pthread-libc \ tst-rootdir \ + tst-tunconf1 \ # tests-container test-srcs = \ diff --git a/elf/cache.c b/elf/cache.c index d3c47b5143..2c22f32548 100644 --- a/elf/cache.c +++ b/elf/cache.c @@ -300,9 +300,10 @@ print_extensions (struct cache_extension_all_loaded *ext, thc->signature, thc->version, thc->num_tunables); for (i = 0; i < count; ++ i) { - printf(" [%d] %s : %s [flags 0x%08x", + printf(" [%d] %s (%d) : %s [flags 0x%08x", i, cache_data + tec[i].name_offset, + tec[i].tunable_id, cache_data + tec[i].value_offset, tec[i].flags); if (tec[i].flag_offset != 0) diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index 5ed44387f9..8dc5aef5b9 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -318,13 +318,15 @@ dl_strlen(const char *s) ENV_ALIAS to find values. Later we will also use the tunable names to find values. */ void -__tunables_init (char **envp) +__tunables_init (char **envp, char **argv) { char *envname = NULL; char *envval = NULL; char **prev_envp = envp; - #if defined(SHARED) && defined (USE_LDCONFIG) + const char *prog_name = (argv && argv[0]) ? argv[0] : ""; + int prog_name_len = -1; + const struct tunable_header_cached *thc; const char *td; @@ -357,9 +359,31 @@ __tunables_init (char **envp) if (tid == -1) continue; } - /* At this point, TID is valid for the tunable we want. See - if the parsed type matches the desired type. */ - + /* At this point, TID is valid for the tunable we want. */ + + /* Apply selected filter, if any. */ + switch (tec->flags & TUNCONF_FLAG_FILTER) { + case TUNCONF_FILTER_PERPROC: + /* Perform one-time calculations that aren't needed if we + don't use this filter. */ + if (prog_name_len == -1 && prog_name != NULL) + { + const char *slash = NULL, *cp; + for (cp = prog_name; *cp; ++ cp) + if (*cp == '/') + slash = cp; + if (slash) + prog_name = slash + 1; + prog_name_len = dl_strlen (prog_name); + } + if (memcmp (prog_name, td + tec->flag_offset, prog_name_len) != 0) + goto skip_due_to_filter; + break; + default: + break; + } + + /* See if the parsed type matches the desired type. */ if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING) { /* This is a memory leak but there's no easy way around @@ -379,9 +403,11 @@ __tunables_init (char **envp) else { tunable_initialize (& tunable_list[tid], - value, dl_strlen(value)); + value, dl_strlen (value)); } } + + skip_due_to_filter: } } #endif diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h index 164bbba9e5..a097790e66 100644 --- a/elf/dl-tunables.h +++ b/elf/dl-tunables.h @@ -47,7 +47,7 @@ typedef void (*tunable_callback_t) (tunable_val_t *); #include "dl-tunable-list.h" -extern void __tunables_init (char **); +extern void __tunables_init (char **, char **); extern void __tunables_print (void); extern bool __tunable_is_initialized (tunable_id_t); extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t); diff --git a/elf/tst-tunconf1.c b/elf/tst-tunconf1.c new file mode 100644 index 0000000000..37e8927fa7 --- /dev/null +++ b/elf/tst-tunconf1.c @@ -0,0 +1,17 @@ +#include + +#include "dl-tunables.h" + +int +main(void) +{ + printf("tst-tunconf1 !\n"); + size_t tcache_count = TUNABLE_GET_FULL (glibc, malloc, tcache_count, size_t, NULL); + size_t tcache_max = TUNABLE_GET_FULL (glibc, malloc, tcache_max, size_t, NULL); + printf("tcache count is %ld (should be 5, from env)\n", (long)tcache_count); + printf("tcache max is %ld (should be 4, from /etc)\n", (long)tcache_max); + + + + return 0; +} diff --git a/elf/tst-tunconf1.root/etc/tunables.conf b/elf/tst-tunconf1.root/etc/tunables.conf new file mode 100644 index 0000000000..c08b89b4f9 --- /dev/null +++ b/elf/tst-tunconf1.root/etc/tunables.conf @@ -0,0 +1,2 @@ +glibc.malloc.tcache_max=4 +glibc.malloc.tcache_count=3 diff --git a/elf/tst-tunconf1.root/ldconfig.run b/elf/tst-tunconf1.root/ldconfig.run new file mode 100644 index 0000000000..e69de29bb2 diff --git a/elf/tst-tunconf1.root/postclean.req b/elf/tst-tunconf1.root/postclean.req new file mode 100644 index 0000000000..e69de29bb2 diff --git a/elf/tunconf.c b/elf/tunconf.c index 9ba35326f6..147ef2a7bb 100644 --- a/elf/tunconf.c +++ b/elf/tunconf.c @@ -65,12 +65,14 @@ typedef enum { struct tunable_entry_int { struct stringtable_entry *name; struct stringtable_entry *value; + struct stringtable_entry *filter; TOP top; int tunable_id; int value_is_negative:1; int value_was_parsed:1; unsigned long long value_ull; signed long long value_sll; + long filter_flags; struct tunable_entry_int *next; }; @@ -78,11 +80,80 @@ struct tunable_entry_int { struct tunable_entry_int *entry_list; struct tunable_entry_int **entry_list_next = &entry_list; +static int filter_flags = 0; +static char *filter_string = NULL; + /*----------------------------------------------------------------------*/ static void parse_tunconf_include (const char *tunconfig_file, unsigned int lineno, bool do_chroot, const char *pattern, const char *opt_chroot); + +static void +clear_filter (void) +{ + free (filter_string); + filter_string = NULL; + filter_flags = 0; +} + +/* Filters are lines the are bracketed, like + [prog:foo] +*/ +static void +parse_filter (char *line, const char *filename, int lineno) +{ + const char *colon = NULL; + const char *right_bracket = NULL; + const char *cp; + + for (cp=line; *cp != 0; cp++) + { + if (*cp == ':') + colon = cp; + if (*cp == ']') + { + right_bracket = cp; + break; + } + } + /* Special case: [] means "no filter" */ + if (right_bracket != NULL && right_bracket == line + 1) + { + clear_filter (); + return; + } + if (colon == NULL) + { + printf("%s:%d: syntax error, filter line ignored: `%s' (missing ':')\n", + filename, lineno, line); + return; + } + if (right_bracket == NULL) + { + printf("%s:%d: syntax error, filter line ignored: `%s' (missing ']')\n", + filename, lineno, line); + return; + } + + if (filter_string != NULL) + { + clear_filter (); + } + + if (memcmp ("proc", line + 1, colon - line - 1) == 0) + { + filter_string = (char *) malloc (right_bracket - colon); + memcpy (filter_string, colon + 1, right_bracket - colon - 1); + filter_string [right_bracket - colon] = 0; + filter_flags = TUNCONF_FILTER_PERPROC; + } + + else + printf("%s:%d: unrecognized filter `%.*s', ignored\n", filename, lineno, (int)(colon - line - 1), line + 1); +} + + static void add_tunable (char *line, const char *filename, int lineno) { @@ -95,11 +166,10 @@ add_tunable (char *line, const char *filename, int lineno) int i, id; orig_line = line; - printf("%s:%d: `%s'\n", filename, lineno, line); // Leading whitespace has already been stripped. - if (*line == '!' || *line == '+' || *line == '-') + if (*line == '!' || *line == '+' || *line == '-' || *line == '[') { switch (*line) { @@ -112,8 +182,10 @@ add_tunable (char *line, const char *filename, int lineno) case '-': top = TOP_DENY; break; + case '[': + parse_filter (line, filename, lineno); + return; } - printf("TOP: %d\n", top); line ++; while (*line && isspace(*line)) line ++; @@ -177,6 +249,12 @@ add_tunable (char *line, const char *filename, int lineno) entry->tunable_id = id; entry->top = top; + if (filter_flags) + { + entry->filter_flags = filter_flags; + entry->filter = cache_store_string (filter_string); + } + *entry_list_next = entry; entry_list_next = & (entry->next); } @@ -190,6 +268,9 @@ parse_tunconf (const char *filename, int do_chroot, char *opt_chroot) size_t len = 0; unsigned int lineno; + /* Filters do not live across file boundaries. */ + clear_filter (); + if (do_chroot && opt_chroot) { canon = chroot_canon (opt_chroot, filename); @@ -261,6 +342,7 @@ Warning: ignoring configuration file that cannot be opened: %s"), /* Free buffer and close file. */ free (line); fclose (file); + clear_filter (); } /* Handle one word in an `include' line, a glob pattern of additional @@ -392,7 +474,15 @@ get_tunconf_ext (uint32_t string_table_offset) tec->tunable_id = tei->tunable_id; tec->name_offset = tei->name->offset + string_table_offset; tec->value_offset = tei->value->offset + string_table_offset; - tec->flag_offset = 0; + + if (tei->filter_flags != 0) + { + tec->flag_offset = tei->filter->offset + string_table_offset; + tec->flags |= tei->filter_flags; + } + else + tec->flag_offset = 0; + tec->unused_1 = 0; if (tei->value_is_negative) tec->parsed_value = (uint64_t) tei->value_sll; diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index e629492583..596b0cfc07 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -98,7 +98,7 @@ _dl_sysdep_start (void **start_argptr, __libc_enable_secure = _dl_hurd_data->flags & EXEC_SECURE; - __tunables_init (_environ); + __tunables_init (_environ, _dl_argv); /* Initialize DSO sorting algorithm after tunables. */ _dl_sort_maps_init (); diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index f17a3e189c..7a6e7c84d7 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -107,7 +107,7 @@ _dl_sysdep_start (void **start_argptr, dl_hwcap_check (); - __tunables_init (_environ); + __tunables_init (_environ, (char **) (start_argptr + 1)); /* Initialize DSO sorting algorithm after tunables. */ _dl_sort_maps_init ();