[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