From patchwork Wed Feb 28 04:43:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 86501 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 C978E3858426 for ; Wed, 28 Feb 2024 04:44:09 +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.133.124]) by sourceware.org (Postfix) with ESMTPS id BB1623858403 for ; Wed, 28 Feb 2024 04:43:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BB1623858403 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 BB1623858403 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=1709095423; cv=none; b=pGjk4jL65lbEpkcxgdYptad4796RYrfjDxtgWQ3UrcjatNc5cj3H0+dWaxVOdJSZ+/JhXlyD/5h4eXyc7gBIMBkJD+750GxFkkRS5T8bs1N6UkdtfeD56uDjtCvXjBmWk10c/9P+D2LduTpSy65jlnmQgFgg4n5fv9mQc+XaQrI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709095423; c=relaxed/simple; bh=DTbuR9hCabRWHEUNuJlpL9d3E1rcIMpDh01GsRl54K8=; h=DKIM-Signature:Date:Message-Id:From:To:Subject; b=oCfgmJalTavzm3yhP+FlOA2jJSDIN6dIUvu35o6F+Os3JJYJBOeXpwI5De+iIFiHxxftYnMsiYr85uijgrIwIl/kkXQLHGGGyBuYlWXWwU+7J+F1AZaYdEhmt3Y5iA/mHgpaddGEpx2EpsM2zkVwwhCnHl/0uHlrAWND8hnW8mc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1709095420; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type; bh=jziNhJyuPzk1PidyJtwQOI3h6gbt6Nw9mJVBdj3agtI=; b=J7qumi9+ib3Y8ZCKx/Zx8g1uEZKTd8hetTwkYCE2w7X++rF5HJbDeMpBCs5D/owy0HxH4j hSyHoaGPrLixUfgZKL31PxYDKnS03M6lRyaFVtVQJ/up/Wb8qPd4D5bDyXzTXpz+wlbxfa Mim8lanqrLhYpJm204uOm0xnJtHIepE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-620-AIkAl3WeOhSAHd95rZOpPQ-1; Tue, 27 Feb 2024 23:43:38 -0500 X-MC-Unique: AIkAl3WeOhSAHd95rZOpPQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id B076B83106C for ; Wed, 28 Feb 2024 04:43:38 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.8.122]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 93F0B1807 for ; Wed, 28 Feb 2024 04:43:38 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.15.2/8.15.2) with ESMTP id 41S4hcqZ2239557 for ; Tue, 27 Feb 2024 23:43:38 -0500 Date: Tue, 27 Feb 2024 23:43:38 -0500 Message-Id: From: DJ Delorie To: libc-alpha@sourceware.org Subject: [PATCH v1 1/3] Add system-wide tunables: ldconfig part X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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 Adds support for reading /etc/tunables.conf The file contains one line per tunable, like this: glibc.foo.bar=14 glibc.malloc.more=0 Additionally, each line can be prefixed with a single character that controls overridability by the GLIBC_TUNABLES env var: !glibc.foo=0 ^ May be made more secure +glibc.foo=0 ^ May be overridden -glibc.foo=0 ^ May not be overridden Internally, each tunable will later have a default "overridability" and logic for what "more secure" means. The tunable cache format allows for a filter to be assigned to each tunable, to be used at program start to decide if a tunable applies to that program. No such filters have yet been specified. The cache format also stores a pre-parsed value for the tunable, and the ID of the tunable, to improve load-time performance. --- elf/Makefile | 1 + elf/cache.c | 65 +++++- elf/ldconfig.c | 21 +- elf/tunconf.c | 408 +++++++++++++++++++++++++++++++++++++ elf/tunconf.h | 40 ++++ sysdeps/generic/dl-cache.h | 6 + sysdeps/generic/ldconfig.h | 2 + 7 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 elf/tunconf.c create mode 100644 elf/tunconf.h diff --git a/elf/Makefile b/elf/Makefile index 36c04baf02..eb2c2b3f58 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -225,6 +225,7 @@ ldconfig-modules := \ readlib \ static-stubs \ stringtable \ + tunconf \ xmalloc \ xstrdup \ # ldconfig-modules diff --git a/elf/cache.c b/elf/cache.c index 8a618e11fa..1146bba877 100644 --- a/elf/cache.c +++ b/elf/cache.c @@ -36,6 +36,7 @@ #include #include #include +#include /* Used to store library names, paths, and other strings. */ static struct stringtable strings; @@ -275,7 +276,8 @@ check_new_cache (struct cache_file_new *cache) /* Print the extension information in *EXT. */ static void -print_extensions (struct cache_extension_all_loaded *ext) +print_extensions (struct cache_extension_all_loaded *ext, + const char *cache_data) { if (ext->sections[cache_extension_tag_generator].base != NULL) { @@ -284,6 +286,30 @@ print_extensions (struct cache_extension_all_loaded *ext) ext->sections[cache_extension_tag_generator].size, stdout); putchar ('\n'); } + if (ext->sections[cache_extension_tag_tunables].base != NULL) + { + struct tunable_header_cached *thc; + struct tunable_entry_cached *tec; + int i, count; + + thc = (struct tunable_header_cached *) + ext->sections[cache_extension_tag_tunables].base; + tec = thc->tunables; + count = thc->num_tunables; + printf("tunables sig 0x%08x ver 0x%08x count %u\n", + thc->signature, thc->version, thc->num_tunables); + for (i = 0; i < count; ++ i) + { + printf(" [%d] %s : %s [flags 0x%08x", + i, + cache_data + tec[i].name_offset, + cache_data + tec[i].value_offset, + tec[i].flags); + if (tec[i].flag_offset != 0) + printf(" : %s", cache_data + tec[i].flag_offset); + printf("]\n"); + } + } } /* Print the whole cache file, if a file contains the new cache format @@ -394,7 +420,7 @@ print_cache (const char *cache_name) cache_new->libs[i].hwcap, hwcaps_string, cache_data + cache_new->libs[i].value); } - print_extensions (&ext); + print_extensions (&ext, cache_data); } /* Cleanup. */ munmap (cache, cache_size); @@ -498,6 +524,28 @@ write_extensions (int fd, uint32_t str_offset, ext->sections[xid].size = hwcaps_size; } + struct tunable_header_cached *tunable_data; + size_t tunable_size; + size_t tunable_aligner = 0; + + tunable_data = get_tunconf_ext (str_offset); + if (tunable_data != NULL) + { + uint32_t tunable_offset_ua; + uint32_t tunable_offset; + + tunable_size = TUNCONF_SIZE (tunable_data); + tunable_offset_ua = generator_offset + strlen (generator); + tunable_offset = ALIGN_UP (tunable_offset_ua, 8); + tunable_aligner = tunable_offset - tunable_offset_ua; + + ++xid; + ext->sections[xid].tag = cache_extension_tag_tunables; + ext->sections[xid].flags = 0; + ext->sections[xid].offset = tunable_offset; + ext->sections[xid].size = tunable_size; + } + ++xid; ext->count = xid; assert (xid <= cache_extension_count); @@ -509,6 +557,13 @@ write_extensions (int fd, uint32_t str_offset, || write (fd, generator, strlen (generator)) != strlen (generator)) error (EXIT_FAILURE, errno, _("Writing of cache extension data failed")); + if (tunable_data) + { + if (write (fd, " ", tunable_aligner) != tunable_aligner + || write (fd, tunable_data, tunable_size) != tunable_size) + error (EXIT_FAILURE, errno, _("Writing of cache tunable data failed")); + } + free (hwcaps_array); free (ext); } @@ -1106,3 +1161,9 @@ out_fail: free (temp_name); free (file_entries); } + +struct stringtable_entry * +cache_store_string (const char *string) +{ + return stringtable_add (&strings, string); +} diff --git a/elf/ldconfig.c b/elf/ldconfig.c index b64c54b53e..b6463b6464 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -43,6 +43,7 @@ #include #include #include +#include "tunconf.h" #include @@ -50,6 +51,10 @@ # define LD_SO_CONF SYSCONFDIR "/ld.so.conf" #endif +#ifndef TUNABLES_CONF +# define TUNABLES_CONF SYSCONFDIR "/tunables.conf" +#endif + /* Get libc version number. */ #include @@ -107,9 +112,12 @@ static int opt_ignore_aux_cache; /* Cache file to use. */ static char *cache_file; -/* Configuration file. */ +/* Configuration file for libraries. */ static const char *config_file; +/* Configuration file for tunables. */ +static const char *tunconfig_file; + /* Name and version of program. */ static void print_version (FILE *stream, struct argp_state *state); void (*argp_program_version_hook) (FILE *, struct argp_state *) @@ -127,7 +135,8 @@ static const struct argp_option options[] = { NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0}, { NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0}, { NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0}, - { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0}, + { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file for libraries"), 0}, + { NULL, 't', N_("TUNCONF"), 0, N_("Use TUNCONF as configuration file for tunables"), 0}, { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0}, { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0}, { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0}, @@ -164,6 +173,9 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'f': config_file = arg; break; + case 't': + tunconfig_file = arg; + break; case 'i': opt_ignore_aux_cache = 1; break; @@ -1240,6 +1252,9 @@ main (int argc, char **argv) if (config_file == NULL) config_file = LD_SO_CONF; + if (tunconfig_file == NULL) + tunconfig_file = TUNABLES_CONF; + if (opt_print_cache) { if (opt_chroot != NULL) @@ -1315,6 +1330,8 @@ main (int argc, char **argv) search_dirs (); + parse_tunconf (tunconfig_file, true, opt_chroot); + if (opt_build_cache) { save_cache (cache_file); diff --git a/elf/tunconf.c b/elf/tunconf.c new file mode 100644 index 0000000000..70e04e5328 --- /dev/null +++ b/elf/tunconf.c @@ -0,0 +1,408 @@ +/* Manage /etc/tunables.* + Copyright (C) 1999-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define TUNABLES_INTERNAL +#include +#include + +#include +#include +#include +#include + +#include "tunconf.h" + +/* Declared in chroot_canon.c. */ +extern char *chroot_canon (const char *chroot, const char *name); + +/*----------------------------------------------------------------------*/ + +#ifndef TUNABLES_CONF +# define TUNABLES_CONF SYSCONFDIR "/tunables.conf" +#endif + +#ifndef TUNABLES_CACHE +# define TUNABLES_CACHE SYSCONFDIR "/tunables.cache" +#endif + +// Tunable Override Policies +typedef enum { + TOP_DEFAULT = 0, // let the internal code decide + TOP_ALLOW, // let the environment variable override + TOP_STRICT, // internal code will only allow "stricter" setting + TOP_DENY // no override allowed +} TOP; + +struct tunable_entry_int { + struct stringtable_entry *name; + struct stringtable_entry *value; + 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; + + struct tunable_entry_int *next; +}; + +struct tunable_entry_int *entry_list; +struct tunable_entry_int **entry_list_next = &entry_list; + +/*----------------------------------------------------------------------*/ + +static void parse_tunconf_include (const char *tunconfig_file, unsigned int lineno, + bool do_chroot, const char *pattern, const char *opt_chroot); + +static void +add_tunable (char *line, const char *filename, int lineno) +{ + TOP top = TOP_DEFAULT; + char *name; + char *value; + char *eq; + char *orig_line; + struct tunable_entry_int *entry; + int i, id; + + orig_line = line; + printf("%s:%d: `%s'\n", filename, lineno, line); + + // Leading whitespace has already been stripped. + + if (*line == '!' || *line == '+' || *line == '-') + { + switch (*line) + { + case '!': + top = TOP_STRICT; + break; + case '+': + top = TOP_ALLOW; + break; + case '-': + top = TOP_DENY; + break; + } + printf("TOP: %d\n", top); + line ++; + while (*line && isspace(*line)) + line ++; + } + + // NAME now points to the start of the tunable name. + name = line; + + // Look for the '=' separator. + eq = strchr (line, '='); + if (eq == NULL) + { + printf("%s:%d: syntax error, line ignored: `%s' (missing '=')\n", + filename, lineno, orig_line); + return; + } + + if (eq == name) + { + printf("%s:%d: syntax error, line ignored: `%s' (missing tunable name)\n", + filename, lineno, orig_line); + return; + } + + // At this point, EQ actually points to '=' + value = eq + 1; + + while (*value && isspace(*value)) + value ++; + + if (*value == 0) + { + printf("%s:%d: syntax error, line ignored: `%s' (missing value)\n", + filename, lineno, orig_line); + return; + } + + // VALUE now points to the start of the value + + // Split the string into name and value c-strings. + *eq = 0; + // Trim trailing whitespace off NAME + while (*name && isspace (name[strlen(name)-1])) + name[strlen(name)-1] = 0; + // Trim trailing whitespace off VALUE + while (*value && isspace (name[strlen(value)-1])) + value[strlen(value)-1] = 0; + + id = -1; + for (i=0; iname = cache_store_string (name); + entry->value = cache_store_string (value); + entry->tunable_id = id; + entry->top = top; + + *entry_list_next = entry; + entry_list_next = & (entry->next); +} + +void +parse_tunconf (const char *filename, int do_chroot, char *opt_chroot) +{ + FILE *file = NULL; + char *line = NULL; + const char *canon; + size_t len = 0; + unsigned int lineno; + + if (do_chroot && opt_chroot) + { + canon = chroot_canon (opt_chroot, filename); + if (canon) + file = fopen (canon, "r"); + else + canon = filename; + } + else + { + canon = filename; + file = fopen (filename, "r"); + } + + if (file == NULL) + { + if (errno != ENOENT) + error (0, errno, _("\ +Warning: ignoring configuration file that cannot be opened: %s"), + canon); + if (canon != filename) + free ((char *) canon); + return; + } + + /* No threads use this stream. */ + __fsetlocking (file, FSETLOCKING_BYCALLER); + + if (canon != filename) + free ((char *) canon); + lineno = 0; + do + { + ssize_t n = getline (&line, &len, file); + if (n < 0) + break; + + ++lineno; + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + /* Because the file format does not know any form of quoting we + can search forward for the next '#' character and if found + make it terminating the line. */ + *strchrnul (line, '#') = '\0'; + + /* Remove leading whitespace. NUL is no whitespace character. */ + char *cp = line; + while (isspace (*cp)) + ++cp; + + /* If the line is blank it is ignored. */ + if (cp[0] == '\0') + continue; + + if (!strncmp (cp, "include", 7) && isblank (cp[7])) + { + char *dir; + cp += 8; + while ((dir = strsep (&cp, " \t")) != NULL) + if (dir[0] != '\0') + parse_tunconf_include (filename, lineno, do_chroot, dir, opt_chroot); + } + else + add_tunable (cp, filename, lineno); + } + while (!feof_unlocked (file)); + + /* Free buffer and close file. */ + free (line); + fclose (file); +} + +/* Handle one word in an `include' line, a glob pattern of additional + config files to read. */ +static void +parse_tunconf_include (const char *tunconfig_file, unsigned int lineno, + bool do_chroot, const char *pattern, const char *opt_chroot) +{ + if (opt_chroot != NULL && pattern[0] != '/') + error (EXIT_FAILURE, 0, + _("need absolute file name for configuration file when using -r")); + + char *copy = NULL; + if (pattern[0] != '/' && strchr (tunconfig_file, '/') != NULL) + { + if (asprintf (©, "%s/%s", dirname (strdupa (tunconfig_file)), + pattern) < 0) + error (EXIT_FAILURE, 0, _("memory exhausted")); + pattern = copy; + } + + glob64_t gl; + int result; + if (do_chroot && opt_chroot) + { + char *canon = chroot_canon (opt_chroot, pattern); + if (canon == NULL) + return; + result = glob64 (canon, 0, NULL, &gl); + free (canon); + } + else + result = glob64 (pattern, 0, NULL, &gl); + + switch (result) + { + case 0: + for (size_t i = 0; i < gl.gl_pathc; ++i) + parse_tunconf (gl.gl_pathv[i], false, NULL); + globfree64 (&gl); + break; + + case GLOB_NOMATCH: + break; + + case GLOB_NOSPACE: + errno = ENOMEM; + /* Fall through. */ + case GLOB_ABORTED: + if (opt_verbose) + error (0, errno, _("%s:%u: cannot read directory %s"), + tunconfig_file, lineno, pattern); + break; + + default: + abort (); + break; + } + + free (copy); +} + +struct tunable_header_cached * +get_tunconf_ext (uint32_t string_table_offset) +{ + struct tunable_entry_int *tei; + struct tunable_header_cached *thc; + size_t count; + size_t size; + + /* First, count the number of entries we have. */ + tei = entry_list; + count = 0; + while (tei != NULL) + { + ++ count; + tei = tei->next; + } + // printf("get_tunconf_ext: found %lu entries\n", count); + + /* Allocate enough space for the whole cached block. */ + size = sizeof (struct tunable_header_cached) + + sizeof (struct tunable_entry_cached) * count; + thc = (struct tunable_header_cached *) malloc (size); + + if (thc == NULL) + { + error (0, 0, _("Unable to allocate %lu bytes in get_tunable_ext"), size); + return NULL; + } + + /* Now, fill in the structures. */ + + thc->signature = TUNCONF_SIGNATURE; + thc->version = TUNCONF_VERSION; + thc->num_tunables = count; + thc->unused_1 = 0; + + tei = entry_list; + count = 0; + while (tei != NULL) + { + struct tunable_entry_cached *tec; + + tec = & ( thc->tunables[count] ); + + tec->flags = 0; + if (tei->value_was_parsed) + tec->flags |= TUNCONF_FLAG_PARSED; + if (tei->value_is_negative) + tec->flags |= TUNCONF_FLAG_NEGATIVE; + // printf("tei->top is %d\n", tei->top); + switch (tei->top) + { + case TOP_DEFAULT: + tec->flags |= TUNCONF_OVERRIDE_DEFAULT; + break; + case TOP_ALLOW: + tec->flags |= TUNCONF_OVERRIDE_ALLOW; + break; + case TOP_STRICT: + tec->flags |= TUNCONF_OVERRIDE_STRICTER; + break; + case TOP_DENY: + tec->flags |= TUNCONF_OVERRIDE_DENY; + break; + } + + 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; + tec->unused_1 = 0; + if (tei->value_is_negative) + tec->parsed_value = (uint64_t) tei->value_sll; + else + tec->parsed_value = (uint64_t) tei->value_ull; + // printf("tec->flags is %08x\n", tec->flags); + + ++ count; + tei = tei->next; + } + + return thc; +} diff --git a/elf/tunconf.h b/elf/tunconf.h new file mode 100644 index 0000000000..a6c5f0dd9a --- /dev/null +++ b/elf/tunconf.h @@ -0,0 +1,40 @@ +#define TUNCONF_SIGNATURE 0x7c3ba94f +#define TUNCONF_VERSION 0x01000000 + +#define TUNCONF_FLAG_PARSED 0x00000001 +#define TUNCONF_FLAG_NEGATIVE 0x00000002 + +#define TUNCONF_FLAG_OVERRIDABLE 0x0000000C +#define TUNCONF_OVERRIDE_DEFAULT 0x00000000 +#define TUNCONF_OVERRIDE_ALLOW 0x00000004 +#define TUNCONF_OVERRIDE_STRICTER 0x00000008 +#define TUNCONF_OVERRIDE_DENY 0x0000000C + +#define TUNCONF_FLAG_FILTER 0x0000ff00 +#define TUNCONF_FILTER_PERPROC 0x00000100 + +/* An array of [num_tunables] of these follows the below. */ +struct tunable_entry_cached { + uint32_t flags; + uint32_t tunable_id; + uint32_t name_offset; + uint32_t value_offset; + uint32_t flag_offset; + uint32_t unused_1; /* for alignment */ + uint64_t parsed_value; +}; + +/* One of these is at the beginning of the tunable data block. */ +struct tunable_header_cached { + uint32_t signature; + uint32_t version; + uint32_t num_tunables; + uint32_t unused_1; /* for alignment */ + struct tunable_entry_cached tunables[0 /* num_tunables */]; +}; + +void parse_tunconf (const char *filename, int do_chroot, char *opt_chroot); + +struct tunable_header_cached * get_tunconf_ext (uint32_t str_offset); +#define TUNCONF_SIZE(thc_p) (sizeof(struct tunable_header_cached) \ + + thc_p->num_tunables * sizeof (struct tunable_entry_cached)) diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h index 919e49ffc8..41521f5a96 100644 --- a/sysdeps/generic/dl-cache.h +++ b/sysdeps/generic/dl-cache.h @@ -220,6 +220,12 @@ enum cache_extension_tag size must be a multiple of 4. */ cache_extension_tag_glibc_hwcaps, + /* Array of system-wide tunable information. + + For this section, 8-byte alignment is required, and the section + size must be a multiple of 8. */ + cache_extension_tag_tunables, + /* Total number of known cache extension tags. */ cache_extension_count }; diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h index 7dafa791f2..31ea2ec5d6 100644 --- a/sysdeps/generic/ldconfig.h +++ b/sysdeps/generic/ldconfig.h @@ -74,6 +74,8 @@ extern void add_to_cache (const char *path, const char *filename, unsigned int isa_level, struct glibc_hwcaps_subdirectory *); +extern struct stringtable_entry *cache_store_string (const char *string); + extern void init_aux_cache (void); extern void load_aux_cache (const char *aux_cache_name);