From patchwork Thu Oct 10 21:44:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 1995781 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=cX711tey; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XPjwD2hxQz1xv0 for ; Fri, 11 Oct 2024 08:45:00 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 913EB385AC30 for ; Thu, 10 Oct 2024 21:44:58 +0000 (GMT) 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 8DB2B3857001 for ; Thu, 10 Oct 2024 21:44:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8DB2B3857001 Authentication-Results: sourceware.org; dmarc=pass (p=none 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 8DB2B3857001 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728596682; cv=none; b=dZXRKLQ70MG8wKfPX8CWmZPSmQYYgf3RopmGJ+sTVvU0cm8WbwkvBR4O2RkQgg7ttVDxc6I6YHXjesl3+bYBidEC9elkUJeyu8HNyaAshgmyZJ+drKmJD9KECozxtAA4UpGI/qIswJNmU//A8zeojdJrVnVHdGZWYjRq7wIqz+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728596682; c=relaxed/simple; bh=/CKA5hQdLihxPxqTy4rFEmHTiwAadFjjc1sotk/Mmvk=; h=DKIM-Signature:Date:From:To:Message-ID:Subject; b=vSpZ36ka8k2q/VSPOKNJ4FrUN8GDzp8RmrGDRtP7E39Tl/IcvBHdZhjMRdYnfcsvjzbM6ZnBUai7wdLNsmsl8SIGwiIO6O7Z1ceXAEVx1q34D1g3ZyzxbAd2m2FsspZj1UOaCXLryJc2s1ys0+ahR/0nAlYx+2sTtSzgWxZIcrg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1728596679; 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=3e69PB34LLRi10Ivc4vzadlRBwoSniE3RpyyQwEhmFw=; b=cX711teyfKzvJpJ1bDoHAKYS1yJ+1NPPMkJr41Rzd4jAjPP9iJ+uXoP9rkdicD/0IqilB3 XP9z8QzzgT+j/Y5mJyTVTaTCHXEgpfDTkdN9mtImfuA5HCM1En68h23JG2PFTJ924Gl5mW czWLy53/BgWiX3gFXhUJTeEx+sm0GoE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-21-ZprFsz7bMCe6h6dIkOpqzA-1; Thu, 10 Oct 2024 17:44:37 -0400 X-MC-Unique: ZprFsz7bMCe6h6dIkOpqzA-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1DDEC19560BA for ; Thu, 10 Oct 2024 21:44:37 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.8.53]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C25DF1956089 for ; Thu, 10 Oct 2024 21:44:36 +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 49ALiZgD4137454 for ; Thu, 10 Oct 2024 17:44:35 -0400 Date: Thu, 10 Oct 2024 17:44:35 -0400 From: DJ Delorie To: libc-alpha@sourceware.org Message-ID: <942ee8135bdc44add90fc98758574bdcbbc3771f.1728595809.git.dj@redhat.com> In-Reply-To: References: Subject: [PATCH v3 4/4] Add system-wide tunables: Filters X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.6 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_H3, RCVD_IN_MSPIKE_WL, 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~incoming=patchwork.ozlabs.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 d784de0f0b..8496b00622 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 e27eed674f..36d1635cb5 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -323,6 +323,7 @@ tests := \ tests-internal := \ $(tests-static-internal) \ tst-tls1 \ + tst-tunconf1 \ # tests-internal tests-static := $(tests-static-normal) $(tests-static-internal) @@ -333,6 +334,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) @@ -532,6 +535,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 1146bba877..08557f8a5e 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 fafd684115..31a0f8edba 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; - #ifdef SHARED + 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 d6d1ef94bd..6424ba970c 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 6ba00e413d..c6bd8c58a4 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -99,7 +99,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 a8ec2d7c18..ccb6114ab6 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -108,7 +108,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 ();