get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2224687/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2224687,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2224687/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/983f232f353ad400cb4f8498934e21672009fd32.1776449736.git.dj@redhat.com/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<983f232f353ad400cb4f8498934e21672009fd32.1776449736.git.dj@redhat.com>",
    "list_archive_url": null,
    "date": "2023-12-05T01:48:18",
    "name": "[v7,1/4] Add system-wide tunables: ldconfig part",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "210b7eee62e965dfb4eafdd2374b7fd5bbf035fc",
    "submitter": {
        "id": 4388,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/4388/?format=api",
        "name": "DJ Delorie",
        "email": "dj@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/983f232f353ad400cb4f8498934e21672009fd32.1776449736.git.dj@redhat.com/mbox/",
    "series": [
        {
            "id": 500385,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/500385/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=500385",
            "date": "2024-02-21T23:49:50",
            "name": "Add system-wide tunables",
            "version": 7,
            "mbox": "http://patchwork.ozlabs.org/series/500385/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2224687/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2224687/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=V0gjfstf;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=V0gjfstf",
            "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "sourceware.org; spf=pass smtp.mailfrom=redhat.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fy3765bqyz1yD3\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 18 Apr 2026 04:19:14 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id EB00D4CD200F\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 18:19:12 +0000 (GMT)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 339394CCCA00\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 18:18:40 +0000 (GMT)",
            "from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-56-4ojEM5ClNfuEzZYmqbYN9Q-1; Fri,\n 17 Apr 2026 14:18:36 -0400",
            "from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id EFB741956048\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 18:18:35 +0000 (UTC)",
            "from greed.delorie.com (unknown [10.22.88.82])\n by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id AF4211800446\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 18:18:35 +0000 (UTC)",
            "from greed.delorie.com (localhost [127.0.0.1])\n by greed.delorie.com (8.16.1/8.16.1) with ESMTPS id 63HIIYeV651989\n (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT)\n for <libc-alpha@sourceware.org>; Fri, 17 Apr 2026 14:18:34 -0400",
            "(from dj@localhost)\n by greed.delorie.com (8.16.1/8.16.1/Submit) id 63HIIYPG651988;\n Fri, 17 Apr 2026 14:18:34 -0400"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org EB00D4CD200F",
            "OpenDKIM Filter v2.11.0 sourceware.org 339394CCCA00"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 339394CCCA00",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 339394CCCA00",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776449920; cv=none;\n b=HWizKcihN5alpOj3zO+hZ1t2SGXtI14MCMevWBUh8MaQkDwry0DIpHP3SFjsPnaKUHqaEho1KHUb9jxzAsOw4dIrpq5RPnM50BqMMWCDexDdBwJ2bR6FhyKBErFq+TXCX11dLlIDBOAyDCVteQ4DaXoP7cD5zYoJeawzQ/AOLVM=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776449920; c=relaxed/simple;\n bh=eOHQBIIxFrNSyZWc8KD/oF7LQA3BE0v1QiDfdYb5wtQ=;\n h=DKIM-Signature:Message-ID:From:Date:Subject:To;\n b=lOTU7XoIuHgMpSaOUe8CWucYl3K6/oIuQXPskA1oGpvAxlpjQLw24l/PpyT/kFC8NoM5QRm0IRurE7igNb369JMskyifH6c63YX/AQcrHhPYyHW6fTiVqc8djQknWyWIxcRi2tiHvpHbZ+51NW/QXFDeIq/BmZtp46cGmRmnaDI=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776449919;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:content-type:content-type:in-reply-to:in-reply-to:\n references:references; bh=zg3nEceGc9D8iJaaBTGd2EooSjfeRnBPms4nPB28KTY=;\n b=V0gjfstfgH+WJb49a+5mGO0nEo60D3hVNbeoPhh4+wr3DUqxLp+h26bxL1gOtu9DEyUG/P\n D2Q+ANcYs0d2Orzc8sbOWevvlf7MwDvdJxTR38UNJDHzFrzvleT/DTik1sJKO1mx833+G/\n beCw9MxSqtp5VZRW+H0zOAXDMMroHWA=",
        "X-MC-Unique": "4ojEM5ClNfuEzZYmqbYN9Q-1",
        "X-Mimecast-MFC-AGG-ID": "4ojEM5ClNfuEzZYmqbYN9Q_1776449916",
        "Message-ID": "\n <983f232f353ad400cb4f8498934e21672009fd32.1776449736.git.dj@redhat.com>",
        "In-Reply-To": "<cover.1776449736.git.dj@redhat.com>",
        "References": "<cover.1776449736.git.dj@redhat.com>",
        "From": "DJ Delorie <dj@redhat.com>",
        "Date": "Mon, 4 Dec 2023 20:48:18 -0500",
        "Subject": "[PATCH v7 1/4] Add system-wide tunables: ldconfig part",
        "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": "KGtfDctQaJPKvoNrxE5fgT8zOrqhREFruDC3ucSkaI4_1776449916",
        "X-Mimecast-Originator": "redhat.com",
        "Content-type": "text/plain; charset=UTF-8",
        "X-BeenThere": "libc-alpha@sourceware.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>",
        "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>",
        "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>",
        "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"
    },
    "content": "Adds support for reading /etc/tunables.conf\n\nThe file contains one line per tunable, like this:\n\nglibc.foo.bar=14\nglibc.malloc.more=0\n\nAdditionally, each line can be prefixed with a single character\nthat controls overridability by the GLIBC_TUNABLES env var:\n\n!glibc.foo=0\n   ^ May be made more secure\n+glibc.foo=0\n   ^ May be overridden\n-glibc.foo=0\n   ^ May not be overridden\n\nInternally, each tunable will later have a default \"overridability\"\nand logic for what \"more secure\" means.\n\nThe tunable cache format allows for a filter to be assigned to\neach tunable, to be used at program start to decide if a tunable\napplies to that program.  No such filters have yet been specified.\n\nThe cache format also stores a pre-parsed value for the tunable, and\nthe ID of the tunable, to improve load-time performance.\n---\n elf/Makefile               |   1 +\n elf/cache.c                |  70 +++++++++-\n elf/ldconfig.c             |  23 +++-\n elf/tunconf.c              | 267 +++++++++++++++++++++++++++++++++++++\n elf/tunconf.h              |  40 ++++++\n sysdeps/generic/dl-cache.h |   6 +\n sysdeps/generic/ldconfig.h |   6 +-\n 7 files changed, 406 insertions(+), 7 deletions(-)\n create mode 100644 elf/tunconf.c\n create mode 100644 elf/tunconf.h",
    "diff": "diff --git a/elf/Makefile b/elf/Makefile\nindex 7f039b5563..6b366df91b 100644\n--- a/elf/Makefile\n+++ b/elf/Makefile\n@@ -224,6 +224,7 @@ ldconfig-modules := \\\n   readlib \\\n   static-stubs \\\n   stringtable \\\n+  tunconf \\\n   xmalloc \\\n   xstrdup \\\n   # ldconfig-modules\ndiff --git a/elf/cache.c b/elf/cache.c\nindex a6dc85dc0f..fe8f66366f 100644\n--- a/elf/cache.c\n+++ b/elf/cache.c\n@@ -36,6 +36,7 @@\n #include <dl-cache.h>\n #include <version.h>\n #include <stringtable.h>\n+#include <tunconf.h>\n \n /* Used to store library names, paths, and other strings.  */\n static struct stringtable strings;\n@@ -275,7 +276,8 @@ check_new_cache (struct cache_file_new *cache)\n \n /* Print the extension information in *EXT.  */\n static void\n-print_extensions (struct cache_extension_all_loaded *ext)\n+print_extensions (struct cache_extension_all_loaded *ext,\n+\t\t  const char *cache_data)\n {\n   if (ext->sections[cache_extension_tag_generator].base != NULL)\n     {\n@@ -284,6 +286,34 @@ print_extensions (struct cache_extension_all_loaded *ext)\n \t      ext->sections[cache_extension_tag_generator].size, stdout);\n       putchar ('\\n');\n     }\n+  if (ext->sections[cache_extension_tag_tunables].base != NULL)\n+    {\n+      struct tunable_header_cached *thc;\n+      struct tunable_entry_cached *tec;\n+      int i, count;\n+\n+      thc = (struct tunable_header_cached *)\n+\text->sections[cache_extension_tag_tunables].base;\n+      tec = thc->tunables;\n+      count = thc->num_tunables;\n+      printf(\"tunables sig 0x%08x ver 0x%08x count %u\\n\",\n+\t     thc->signature, thc->version, thc->num_tunables);\n+      /* Check that COUNT won't overflow our data block.  */\n+      assert (ext->sections[cache_extension_tag_tunables].base\n+\t      + ext->sections[cache_extension_tag_tunables].size\n+\t      >= (void *) & tec[count]);\n+      for (i = 0; i < count; ++ i)\n+\t{\n+\t  printf(\"  [%d] %s : %s [flags 0x%08x\",\n+\t\t i,\n+\t\t cache_data + tec[i].name_offset,\n+\t\t cache_data + tec[i].value_offset,\n+\t\t tec[i].flags);\n+\t  if (tec[i].flag_offset != 0)\n+\t    printf(\" : %s\", cache_data + tec[i].flag_offset);\n+\t  printf(\"]\\n\");\n+\t}\n+    }\n }\n \n /* Print the whole cache file, if a file contains the new cache format\n@@ -394,7 +424,7 @@ print_cache (const char *cache_name)\n \t\t       cache_new->libs[i].hwcap, hwcaps_string,\n \t\t       cache_data + cache_new->libs[i].value);\n \t}\n-      print_extensions (&ext);\n+      print_extensions (&ext, cache_data);\n     }\n   /* Cleanup.  */\n   munmap (cache, cache_size);\n@@ -498,6 +528,28 @@ write_extensions (int fd, uint32_t str_offset,\n       ext->sections[xid].size = hwcaps_size;\n     }\n \n+  struct tunable_header_cached *tunable_data;\n+  size_t tunable_size;\n+  size_t tunable_aligner = 0;\n+\n+  tunable_data = get_tunconf_ext (str_offset);\n+  if (tunable_data != NULL)\n+    {\n+      uint32_t tunable_offset_ua;\n+      uint32_t tunable_offset;\n+\n+      tunable_size = TUNCONF_SIZE (tunable_data);\n+      tunable_offset_ua = generator_offset + strlen (generator);\n+      tunable_offset = ALIGN_UP (tunable_offset_ua, 8);\n+      tunable_aligner = tunable_offset - tunable_offset_ua;\n+\n+      ++xid;\n+      ext->sections[xid].tag = cache_extension_tag_tunables;\n+      ext->sections[xid].flags = 0;\n+      ext->sections[xid].offset = tunable_offset;\n+      ext->sections[xid].size = tunable_size;\n+    }\n+\n   ++xid;\n   ext->count = xid;\n   assert (xid <= cache_extension_count);\n@@ -509,6 +561,14 @@ write_extensions (int fd, uint32_t str_offset,\n       || write (fd, generator, strlen (generator)) != strlen (generator))\n     error (EXIT_FAILURE, errno, _(\"Writing of cache extension data failed\"));\n \n+  if (tunable_data)\n+    {\n+      if (write (fd, \"        \", tunable_aligner) != tunable_aligner\n+\t  || write (fd, tunable_data, tunable_size) != tunable_size)\n+\terror (EXIT_FAILURE, errno, _(\"Writing of cache tunable data failed\"));\n+      free (tunable_data);\n+    }\n+\n   free (hwcaps_array);\n   free (ext);\n }\n@@ -1106,3 +1166,9 @@ out_fail:\n   free (temp_name);\n   free (file_entries);\n }\n+\n+struct stringtable_entry *\n+cache_store_string (const char *string)\n+{\n+  return stringtable_add (&strings, string);\n+}\ndiff --git a/elf/ldconfig.c b/elf/ldconfig.c\nindex 070e933df6..11b063eb5c 100644\n--- a/elf/ldconfig.c\n+++ b/elf/ldconfig.c\n@@ -44,12 +44,17 @@\n #include <dl-cache.h>\n #include <dl-hwcaps.h>\n #include <dl-is_dso.h>\n+#include \"tunconf.h\"\n \n \n #ifndef LD_SO_CONF\n # define LD_SO_CONF SYSCONFDIR \"/ld.so.conf\"\n #endif\n \n+#ifndef TUNABLES_CONF\n+# define TUNABLES_CONF SYSCONFDIR \"/tunables.conf\"\n+#endif\n+\n /* Get libc version number.  */\n #include <version.h>\n \n@@ -107,9 +112,12 @@ static int opt_ignore_aux_cache;\n /* Cache file to use.  */\n static char *cache_file;\n \n-/* Configuration file.  */\n+/* Configuration file for libraries.  */\n static const char *config_file;\n \n+/* Configuration file for tunables.  */\n+static const char *tunconfig_file;\n+\n /* Name and version of program.  */\n static void print_version (FILE *stream, struct argp_state *state);\n void (*argp_program_version_hook) (FILE *, struct argp_state *)\n@@ -127,7 +135,8 @@ static const struct argp_option options[] =\n   { NULL, 'X', NULL, 0, N_(\"Don't update symbolic links\"), 0},\n   { NULL, 'r', N_(\"ROOT\"), 0, N_(\"Change to and use ROOT as root directory\"), 0},\n   { NULL, 'C', N_(\"CACHE\"), 0, N_(\"Use CACHE as cache file\"), 0},\n-  { NULL, 'f', N_(\"CONF\"), 0, N_(\"Use CONF as configuration file\"), 0},\n+  { NULL, 'f', N_(\"CONF\"), 0, N_(\"Use CONF as configuration file for libraries\"), 0},\n+  { NULL, 't', N_(\"TUNCONF\"), 0, N_(\"Use TUNCONF as configuration file for tunables\"), 0},\n   { NULL, 'n', NULL, 0, N_(\"Only process directories specified on the command line.  Don't build cache.\"), 0},\n   { NULL, 'l', NULL, 0, N_(\"Manually link individual libraries.\"), 0},\n   { \"format\", 'c', N_(\"FORMAT\"), 0, N_(\"Format to use: new (default), old, or compat\"), 0},\n@@ -164,6 +173,9 @@ parse_opt (int key, char *arg, struct argp_state *state)\n     case 'f':\n       config_file = arg;\n       break;\n+    case 't':\n+      tunconfig_file = arg;\n+      break;\n     case 'i':\n       opt_ignore_aux_cache = 1;\n       break;\n@@ -421,7 +433,7 @@ add_dir_1 (const char *line, const char *from_file, int from_line)\n }\n \n static void\n-add_dir_callback (const char *line, const char *from_file, int from_line)\n+add_dir_callback (char *line, const char *from_file, int from_line)\n {\n   if (!strncasecmp (line, \"hwcap\", 5) && isblank (line[5]))\n     error (0, 0, _(\"%s:%u: hwcap directive ignored\"), from_file, from_line);\n@@ -1089,6 +1101,9 @@ main (int argc, char **argv)\n   if (config_file == NULL)\n     config_file = LD_SO_CONF;\n \n+  if (tunconfig_file == NULL)\n+    tunconfig_file = TUNABLES_CONF;\n+\n   if (opt_print_cache)\n     {\n       if (opt_chroot != NULL)\n@@ -1164,6 +1179,8 @@ main (int argc, char **argv)\n \n   search_dirs ();\n \n+  parse_tunconf (tunconfig_file, opt_chroot);\n+\n   if (opt_build_cache)\n     {\n       save_cache (cache_file);\ndiff --git a/elf/tunconf.c b/elf/tunconf.c\nnew file mode 100644\nindex 0000000000..1b7bf0ac2b\n--- /dev/null\n+++ b/elf/tunconf.c\n@@ -0,0 +1,267 @@\n+/* Manage /etc/tunables.*\n+   Copyright (C) 1999-2023 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   This program is free software; you can redistribute it and/or modify\n+   it under the terms of the GNU General Public License as published\n+   by the Free Software Foundation; version 2 of the License, or\n+   (at your option) any later version.\n+\n+   This program is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU General Public License for more details.\n+\n+   You should have received a copy of the GNU General Public License\n+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */\n+\n+#include <alloca.h>\n+#include <argp.h>\n+#include <assert.h>\n+#include <error.h>\n+#include <inttypes.h>\n+#include <glob.h>\n+#include <libgen.h>\n+#include <libintl.h>\n+#include <locale.h>\n+#include <programs/xmalloc.h>\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdio_ext.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#define TUNABLES_INTERNAL\n+#include <elf/dl-tunables.h>\n+#include <unistd.h>\n+\n+#include <ldconfig.h>\n+#include <dl-cache.h>\n+#include <version.h>\n+#include <stringtable.h>\n+#include <array_length.h>\n+\n+#include \"tunconf.h\"\n+\n+/* Declared in chroot_canon.c.  */\n+extern char *chroot_canon (const char *chroot, const char *name);\n+\n+/*----------------------------------------------------------------------*/\n+\n+#ifndef TUNABLES_CONF\n+# define TUNABLES_CONF SYSCONFDIR \"/tunables.conf\"\n+#endif\n+\n+#ifndef TUNABLES_CACHE\n+# define TUNABLES_CACHE SYSCONFDIR \"/tunables.cache\"\n+#endif\n+\n+/* Tunable Override Policies.  */\n+typedef enum {\n+  TOP_DEFAULT = 0,\t/* let the internal code decide */\n+  TOP_ALLOW,\t\t/* let the environment variable override */\n+  TOP_STRICT,\t\t/* internal code will only allow \"stricter\" setting */\n+  TOP_DENY\t\t/* no override allowed */\n+} TOP;\n+\n+struct tunable_entry_int {\n+  struct stringtable_entry *name;\n+  struct stringtable_entry *value;\n+  TOP top;\n+  int tunable_id;\n+  int value_is_negative:1;\n+  int value_was_parsed:1;\n+  unsigned long long value_ull;\n+  signed long long value_sll;\n+\n+  struct tunable_entry_int *next;\n+};\n+\n+struct tunable_entry_int *entry_list;\n+struct tunable_entry_int **entry_list_next = &entry_list;\n+\n+/*----------------------------------------------------------------------*/\n+\n+static void\n+add_tunable (char *line, const char *filename, int lineno)\n+{\n+  TOP top = TOP_DEFAULT;\n+  char *name;\n+  char *value;\n+  char *eq;\n+  char *orig_line;\n+  struct tunable_entry_int *entry;\n+  int i, id;\n+\n+  orig_line = line;\n+\n+  /* Leading whitespace has already been stripped.  */\n+\n+  if (*line == '!' || *line == '+' || *line == '-')\n+    {\n+      switch (*line)\n+\t{\n+\tcase '!':\n+\t  top = TOP_STRICT;\n+\t  break;\n+\tcase '+':\n+\t  top = TOP_ALLOW;\n+\t  break;\n+\tcase '-':\n+\t  top = TOP_DENY;\n+\t  break;\n+\t}\n+      line ++;\n+      while (*line && isspace(*line))\n+\tline ++;\n+    }\n+\n+  /* NAME now points to the start of the tunable name.  */\n+  name = line;\n+\n+  /* Look for the '=' separator.  */\n+  eq = strchr (line, '=');\n+  if (eq == NULL)\n+    {\n+      error_at_line (0, 0, filename, lineno,\n+\t\t     \"syntax error, line ignored: `%s' (missing '=')\\n\",\n+\t\t     orig_line);\n+      return;\n+    }\n+\n+  if (eq == name)\n+    {\n+      error_at_line (0, 0, filename, lineno,\n+\t\t     \"syntax error, line ignored: `%s' (missing tunable name)\\n\",\n+\t\t     orig_line);\n+      return;\n+    }\n+\n+  /* At this point, EQ actually points to '='.  */\n+  value = eq + 1;\n+\n+  while (*value && isspace(*value))\n+    value ++;\n+\n+  if (*value == 0)\n+    {\n+      error_at_line (0, 0, filename, lineno,\n+\t\t     \"syntax error, line ignored: `%s' (missing value)\\n\",\n+\t\t     orig_line);\n+      return;\n+    }\n+\n+  /* VALUE now points to the start of the value.  */\n+\n+  /* Split the string into name and value c-strings.  */\n+  *eq = 0;\n+  /* Trim trailing whitespace off NAME.  */\n+  while (*name && isspace (name[strlen(name)-1]))\n+    name[strlen(name)-1] = 0;\n+  /* Trim trailing whitespace off VALUE.  */\n+  while (*value && isspace (value[strlen(value)-1]))\n+    value[strlen(value)-1] = 0;\n+\n+  id = -1;\n+  for (i = 0; i < array_length (tunable_list); i ++)\n+    if (strcmp (tunable_list[i].name, name) == 0)\n+      {\n+\tid = i;\n+\tbreak;\n+      }\n+\n+  entry = (struct tunable_entry_int *) xcalloc (sizeof (struct tunable_entry_int), 1);\n+  entry->name = cache_store_string (name);\n+  entry->value = cache_store_string (value);\n+  entry->tunable_id = id;\n+  entry->top = top;\n+\n+  *entry_list_next = entry;\n+  entry_list_next = & (entry->next);\n+}\n+\n+void\n+parse_tunconf (const char *filename, char *opt_chroot)\n+{\n+  ldconfig_parse_config (filename, opt_chroot, add_tunable);\n+}\n+\n+struct tunable_header_cached *\n+get_tunconf_ext (uint32_t string_table_offset)\n+{\n+  struct tunable_entry_int *tei;\n+  struct tunable_header_cached *thc;\n+  size_t count;\n+  size_t size;\n+\n+  /* First, count the number of entries we have.  */\n+  tei = entry_list;\n+  count = 0;\n+  while (tei != NULL)\n+    {\n+      ++ count;\n+      tei = tei->next;\n+    }\n+\n+  /* Allocate enough space for the whole cached block.  */\n+  size = sizeof (struct tunable_header_cached)\n+       + sizeof (struct tunable_entry_cached) * count;\n+  thc = (struct tunable_header_cached *) malloc (size);\n+\n+  if (thc == NULL)\n+    {\n+      error (0, 0, _(\"Unable to allocate %zu bytes in get_tunable_ext\"), size);\n+      return NULL;\n+    }\n+\n+  /* Now, fill in the structures.  */\n+\n+  thc->signature = TUNCONF_SIGNATURE;\n+  thc->version = TUNCONF_VERSION;\n+  thc->num_tunables = count;\n+  thc->unused_1 = 0;\n+\n+  tei = entry_list;\n+  count = 0;\n+  while (tei != NULL)\n+    {\n+      struct tunable_entry_cached *tec;\n+\n+      tec = & ( thc->tunables[count] );\n+\n+      tec->flags = 0;\n+      if (tei->value_was_parsed)\n+\ttec->flags |= TUNCONF_FLAG_PARSED;\n+      if (tei->value_is_negative)\n+\ttec->flags |= TUNCONF_FLAG_NEGATIVE;\n+      switch (tei->top)\n+\t{\n+\tcase TOP_DEFAULT:\n+\t  tec->flags |= TUNCONF_OVERRIDE_DEFAULT;\n+\t  break;\n+\tcase TOP_ALLOW:\n+\t  tec->flags |= TUNCONF_OVERRIDE_ALLOW;\n+\t  break;\n+\tcase TOP_STRICT:\n+\t  tec->flags |= TUNCONF_OVERRIDE_STRICTER;\n+\t  break;\n+\tcase TOP_DENY:\n+\t  tec->flags |= TUNCONF_OVERRIDE_DENY;\n+\t  break;\n+\t}\n+\n+      tec->tunable_id = tei->tunable_id;\n+      tec->name_offset = tei->name->offset + string_table_offset;\n+      tec->value_offset = tei->value->offset + string_table_offset;\n+      tec->flag_offset = 0;\n+      tec->unused_1 = 0;\n+      if (tei->value_is_negative)\n+\ttec->parsed_value = (uint64_t) tei->value_sll;\n+      else\n+\ttec->parsed_value = (uint64_t) tei->value_ull;\n+\n+      ++ count;\n+      tei = tei->next;\n+    }\n+\n+  return thc;\n+}\ndiff --git a/elf/tunconf.h b/elf/tunconf.h\nnew file mode 100644\nindex 0000000000..7578605c5a\n--- /dev/null\n+++ b/elf/tunconf.h\n@@ -0,0 +1,40 @@\n+#define TUNCONF_SIGNATURE\t\t0x7c3ba94f\n+#define TUNCONF_VERSION\t\t\t0x01000000\n+\n+#define TUNCONF_FLAG_PARSED\t\t0x00000001\n+#define TUNCONF_FLAG_NEGATIVE\t\t0x00000002\n+\n+#define TUNCONF_FLAG_OVERRIDABLE\t0x0000000C\n+#define TUNCONF_OVERRIDE_DEFAULT\t0x00000000\n+#define TUNCONF_OVERRIDE_ALLOW\t\t0x00000004\n+#define TUNCONF_OVERRIDE_STRICTER\t0x00000008\n+#define TUNCONF_OVERRIDE_DENY\t\t0x0000000C\n+\n+#define TUNCONF_FLAG_FILTER\t\t0x0000ff00\n+#define TUNCONF_FILTER_PERPROC\t\t0x00000100\n+\n+/* An array of [num_tunables] of these follows the below.  */\n+struct tunable_entry_cached {\n+  uint32_t flags;\n+  uint32_t tunable_id;\n+  uint32_t name_offset;\n+  uint32_t value_offset;\n+  uint32_t flag_offset;\n+  uint32_t unused_1; /* for alignment */\n+  uint64_t parsed_value;\n+};\n+\n+/* One of these is at the beginning of the tunable data block.  */\n+struct tunable_header_cached {\n+  uint32_t signature;\n+  uint32_t version;\n+  uint32_t num_tunables;\n+  uint32_t unused_1; /* for alignment */\n+  struct tunable_entry_cached tunables[0 /* num_tunables */];\n+};\n+\n+void parse_tunconf (const char *filename, char *opt_chroot);\n+\n+struct tunable_header_cached * get_tunconf_ext (uint32_t str_offset);\n+#define TUNCONF_SIZE(thc_p) (sizeof(struct tunable_header_cached)\t\t\\\n+\t\t     + thc_p->num_tunables * sizeof (struct tunable_entry_cached))\ndiff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h\nindex 26f0c1e0bd..f438982b6f 100644\n--- a/sysdeps/generic/dl-cache.h\n+++ b/sysdeps/generic/dl-cache.h\n@@ -220,6 +220,12 @@ enum cache_extension_tag\n       size must be a multiple of 4.  */\n    cache_extension_tag_glibc_hwcaps,\n \n+   /* Array of system-wide tunable information.\n+\n+      For this section, 8-byte alignment is required, and the section\n+      size must be a multiple of 8.  */\n+   cache_extension_tag_tunables,\n+\n    /* Total number of known cache extension tags.  */\n    cache_extension_count\n   };\ndiff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h\nindex 22d0fd0f82..800714659e 100644\n--- a/sysdeps/generic/ldconfig.h\n+++ b/sysdeps/generic/ldconfig.h\n@@ -74,6 +74,8 @@ extern void add_to_cache (const char *path, const char *filename,\n \t\t\t  unsigned int isa_level,\n \t\t\t  struct glibc_hwcaps_subdirectory *);\n \n+extern struct stringtable_entry *cache_store_string (const char *string);\n+\n extern void init_aux_cache (void);\n \n extern void load_aux_cache (const char *aux_cache_name);\n@@ -112,8 +114,8 @@ enum opt_format\n extern enum opt_format opt_format;\n \n /* Declared in ldconfig-parse.c */\n-typedef void (*ldconfig_parse_config_cb) (const char *line,\n-\t\t\t\t\t const char *from_file, int from_line);\n+typedef void (*ldconfig_parse_config_cb) (char *line,\n+\t\t\t\t\t  const char *from_file, int from_line);\n \n void ldconfig_parse_config (const char *filename, char *opt_chroot,\n \t\t\t    ldconfig_parse_config_cb cb);\n",
    "prefixes": [
        "v7",
        "1/4"
    ]
}