[PATCH v5 2/4] Add system-wide tunables: cache ld.so.cache

DJ Delorie dj@redhat.com
Sat Feb 28 04:11:34 GMT 2026


Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
> I agree with Yury here that we need to add some tests, at least some
> minimal one that stress the ld.so.cache reload (which is not the usual
> scenario).  I would suggest add test-containts tests that:
>
>   1. Construct a ld.so.cache, start the test, trigger ld.so.cache
>      reconstruct, and check if:
>
>      1.1. A new entry is used on dlopen.
>
>      1.2. If removing an entry triggers a dlopen failure.
>
>      1.3. If not modifying the ld.so.cache contents keep the same
>           contents.
>
>   2. Construct a ld.so.cache, start the test, create a invalid/corrupt
>      ld.so.cache and check if the test can load new libraries to
>      assure the cached load keeps working.

Just for discussion, here's the new test that will be part of patch 2/4.
It should be easy to check more things in do_test given the helper
functions.

diff --git a/elf/Makefile b/elf/Makefile
index 05bb2b0cd9..7004200185 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -558,6 +558,7 @@ endif
 tests-container += \
   tst-dlopen-self-container \
   tst-dlopen-tlsmodid-container \
+  tst-ldconfig-cache \
   tst-pldd \
   tst-preload-pthread-libc \
   tst-rootdir \
@@ -713,6 +714,8 @@ one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
   0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x)
 tst-tls-many-dynamic-modules := \
   $(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod)
+tst-ldconfig-cache-modules := \
+  $(foreach n,1 2 3 4 5,tst-tls-manydynamic$(n)mod)
 tst-tls-many-dynamic-modules-dep-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 \
 					    14 15 16 17 18 19
 tst-tls-many-dynamic-modules-dep = \
diff --git a/elf/tst-ldconfig-cache.c b/elf/tst-ldconfig-cache.c
new file mode 100644
index 0000000000..9f71418b3a
--- /dev/null
+++ b/elf/tst-ldconfig-cache.c
@@ -0,0 +1,134 @@
+/* Test ldconfig cache is correctly used when changed.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+/* What we're testing for: We initially load ld.so.cache at startup
+   and remember it.  If we detect that ld.so.cache has changed, and we
+   can load it successfully, we replace our remember it.  If it
+   doesn't change, or if the new version is corrupted, we continue
+   using the old remembered copy.  */
+
+#include <fcntl.h>
+
+#include <support/support.h>
+#include <support/check.h>
+
+#include <support/xstdio.h>
+#include <support/xstdlib.h>
+#include <support/xdlfcn.h>
+#include <support/xunistd.h>
+
+
+/* Verify that we can (or can't) load one of our test objects.  */
+static void
+try (int i, int invert)
+{
+  char dlname[100];
+  char symname[100];
+  int (*proc)(int);
+  void *dl;
+
+  /* These match the objects copied by tst-ldconfig-cache.script,
+     copied from tst-tls-manydynamic*.so.  */
+  sprintf (dlname, "libcache%d.so", i);
+  sprintf (symname, "set_value_%02d", i);
+
+  dl = dlopen (dlname, RTLD_NOW);
+
+  if (invert)
+    {
+      /* This is a negative test; if the object doesn't load the test
+	 passes.  */
+      TEST_VERIFY (dl == NULL);
+      return;
+    }
+  else
+    {
+      /* This is a positive test; if the object doesn't load the test
+	 fails.  */
+      if (dl == NULL)
+	FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ());
+    }
+
+  proc = xdlsym (dl, symname);
+  /* We don't need to call the symbol, just make sure it exists.  */
+  TEST_VERIFY (proc != NULL);
+
+  xdlclose (dl);
+}
+
+/* Cause corruption in the cache that should prevent loading it.  */
+static void
+corrupt (void)
+{
+  int fd = xopen ("/etc/ld.so.cache", O_RDWR, 0);
+  char bytes[] = { 15, 32, 184, 4 };
+  xwrite (fd, bytes, sizeof(bytes));
+  xclose (fd);
+}
+
+/* Regenerate the cache from ld.so.conf.  */
+static void
+ldconfig (void)
+{
+  xsystem ("/sbin/ldconfig -X");
+}
+
+/* Change ld.so.conf to refer to the new directory, and generate a new
+   cache.  */
+static void
+newpath (const char *p)
+{
+  FILE *f = xfopen ("/etc/ld.so.conf", "w");
+  fprintf (f, "%s\n", p);
+  xfclose (f);
+
+  ldconfig ();
+}
+
+static int
+do_test (void)
+{
+  /* Test that the cache we started with can still load objects in
+     /a.  */
+  try (1, 0);
+
+  /* Create a new cache that doesn't include /a but corrupt it.  Test
+     that we still use the cache with /a in it.  */
+  newpath ("/c");
+  corrupt ();
+  try (2, 0);
+
+  /* Regenerate a clean cache with /a in it and verify we can load
+     objects in /a.  */
+  newpath ("/a");
+  try (3, 0);
+
+  /* Generate a new cache with /b but not /a and make sure objects
+     in /a can't be loaded.  */
+  newpath ("/b");
+  try (3, 1);
+
+  /* But objects in /b can be loaded.  */
+  try (4, 0);
+  /* Even multiple times.  */
+  try (5, 0);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-ldconfig-cache.root/etc/ld.so.conf b/elf/tst-ldconfig-cache.root/etc/ld.so.conf
new file mode 100644
index 0000000000..2b4c2d7817
--- /dev/null
+++ b/elf/tst-ldconfig-cache.root/etc/ld.so.conf
@@ -0,0 +1,3 @@
+/lib
+/lib64
+/a
diff --git a/elf/tst-ldconfig-cache.root/ldconfig.req b/elf/tst-ldconfig-cache.root/ldconfig.req
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/elf/tst-ldconfig-cache.root/tst-ldconfig-cache.script b/elf/tst-ldconfig-cache.root/tst-ldconfig-cache.script
new file mode 100644
index 0000000000..4f258cac1e
--- /dev/null
+++ b/elf/tst-ldconfig-cache.root/tst-ldconfig-cache.script
@@ -0,0 +1,7 @@
+mkdirp 0755 /a
+cp $B/elf/tst-tls-manydynamic01mod.so /a/libcache1.so
+cp $B/elf/tst-tls-manydynamic02mod.so /a/libcache2.so
+cp $B/elf/tst-tls-manydynamic03mod.so /a/libcache3.so
+mkdirp 0755 /b
+cp $B/elf/tst-tls-manydynamic04mod.so /b/libcache4.so
+cp $B/elf/tst-tls-manydynamic05mod.so /b/libcache5.so



More information about the Libc-alpha mailing list