3.5 Managing Shared Libraries & ldconfig (102.3)

Key Takeaways

  • Dynamic shared libraries (.so) reduce executable file sizes and memory consumption by allowing multiple running processes to share a single library code segment in RAM.
  • The ldd command inspects an executable binary and prints all required shared libraries along with their resolved filesystem paths and memory addresses.
  • The dynamic linker (ld-linux.so.2 for 32-bit, ld-linux-x86-64.so.2 for 64-bit) relies on the binary cache /etc/ld.so.cache for high-speed library resolution.
  • The ldconfig command scans directories listed in /etc/ld.so.conf and /etc/ld.so.conf.d/*.conf, creates required SONAME symlinks, and rebuilds /etc/ld.so.cache.
  • The LD_LIBRARY_PATH environment variable overrides default library search paths, while LD_PRELOAD forces the dynamic linker to load specified libraries before all others.
Last updated: August 2026

3.5 Managing Shared Libraries & ldconfig (102.3)

Quick Summary: Linux applications rely heavily on shared libraries (Shared Objects or .so files) to modularize code, optimize memory usage, and simplify security updates. The dynamic linker (ld-linux.so) resolves shared dependencies at runtime using the pre-compiled binary cache /etc/ld.so.cache. Administrators use ldd to inspect program dependencies, ldconfig to update library cache files and SONAME symlinks, and environment variables like LD_LIBRARY_PATH and LD_PRELOAD to control runtime loading behavior.


1. Static vs. Dynamic Linking

When source code is compiled into an executable binary, external functions (e.g., standard C library calls like printf) can be bound to the application through either static or dynamic linking.

FeatureStatic Libraries (.a)Dynamic Shared Libraries (.so)
Compilation MechanismLibrary code is copied directly into the executable binary file at compile time by ar and ld.The binary contains only symbolic references and required SONAME strings; library code is loaded at runtime.
Binary File SizeLarge (includes all library functions).Small (contains only lightweight reference tables).
RAM UtilizationInefficient (every running process maintains its own duplicate copy of library code in RAM).Highly efficient (a single copy of the shared library text segment is loaded into physical RAM and shared across all processes).
Security & PatchingCumbersome (fixing a vulnerability requires recompiling every application linked against the static library).Seamless (updating the .so file on disk immediately patches all applications upon their next launch).
PortabilityStandalone binary runs without external dependencies.Requires compatible shared libraries installed on the target system.

2. Shared Library Naming Schemes & Versioning

Shared libraries utilize a standardized three-tier naming convention to support Application Binary Interface (ABI) versioning without breaking existing software.

  Linker Name:  libcrypto.so ────────┐ (Used by gcc during compilation)
                                     ▼
  SONAME:       libcrypto.so.1.1 ────┤ (Symlink; defines ABI compatibility)
                                     ▼
  Real Name:    libcrypto.so.1.1.1k ─── (Actual binary file on disk)
  1. Real Name (lib<name>.so.<major>.<minor>.<release>): The actual compiled shared object binary containing the machine code (e.g., libssl.so.1.1.1k).
  2. SONAME (lib<name>.so.<major>): A symbolic link pointing to the real name (e.g., libssl.so.1.1 -> libssl.so.1.1.1k). When an application is compiled, this SONAME string is embedded into its ELF header. As long as the major ABI version does not break, updating the real file and pointing the SONAME symlink to it preserves application compatibility.
  3. Linker Name (lib<name>.so): A symbolic link pointing to the SONAME (e.g., libssl.so -> libssl.so.1.1). Used by compilers when developers pass the -lssl flag.

3. Dynamic Linker & Dependency Inspection (ldd)

When a dynamic executable launches, the Linux kernel reads the ELF binary's INTERP header and executes the dynamic linker/loader:

  • 64-bit x86_64: /lib64/ld-linux-x86-64.so.2
  • 32-bit x86: /lib/ld-linux.so.2
  • ARM64 (aarch64): /lib/ld-linux-aarch64.so.1

Inspecting Dependencies with ldd

The ldd (List Dynamic Dependencies) utility prints the shared libraries required by an executable, along with the resolved disk paths and memory load locations.

# Inspect dependencies of /bin/ls
ldd /bin/ls
	linux-vdso.so.1 (0x00007ffe3dbcd000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f35b2e9e000)
	libcap.so.2 => /lib64/libcap.so.2 (0x00007f35b2e94000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f35b2c8c000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f35b2ed1000)

If a required library is missing from the system or unresolvable in the cache, ldd outputs not found, and attempting to launch the binary will fail with: error while loading shared libraries: libcustom.so.2: cannot open shared object file: No such file or directory.

⚠️ Security Warning regarding ldd: Never run ldd on an untrusted or suspicious binary! For certain ELF binaries, ldd may attempt to execute the dynamic linker directly, potentially executing untrusted code. To safely inspect dependencies without execution, use: objdump -p /path/to/binary | grep NEEDED or readelf -d /path/to/binary.


4. Library Cache & Configuration: /etc/ld.so.conf and ldconfig

Searching dozens of filesystem directories on disk for every library during every program launch would severely degrade system performance. To eliminate this overhead, Linux dynamic linkers read a pre-indexed binary cache file: /etc/ld.so.cache.

Configuration Files

  • /etc/ld.so.conf: The primary configuration file listing library search directories. In modern systems, it typically contains an include directive: include /etc/ld.so.conf.d/*.conf.
  • /etc/ld.so.conf.d/*.conf: Modular configuration files containing directory paths (one path per line), such as /usr/local/lib, /opt/custom/lib64, or /usr/lib64/mariadb.
# Sample /etc/ld.so.conf
include ld.so.conf.d/*.conf

# Sample /etc/ld.so.conf.d/custom-apps.conf
/opt/myapp/lib
/usr/local/lib64

The ldconfig Command

The ldconfig command must be executed by root whenever new shared libraries are installed to non-standard directories or /etc/ld.so.conf is modified. ldconfig performs two critical tasks:

  1. Scans standard directories (/lib, /lib64, /usr/lib, /usr/lib64) and directories specified in /etc/ld.so.conf to create and update necessary SONAME symbolic links.
  2. Rebuilds the binary cache file /etc/ld.so.cache.
# Rebuild library cache and update symlinks
sudo ldconfig

# Rebuild cache with verbose output showing directories scanned
sudo ldconfig -v

# Print the current contents of the binary cache (/etc/ld.so.cache)
ldconfig -p | grep libssl
	libssl3.so (libc6,x86-64) => /lib64/libssl3.so
	libssl.so.1.1 (libc6,x86-64) => /lib64/libssl.so.1.1
	libssl.so (libc6,x86-64) => /lib64/libssl.so

ldconfig Command Options Matrix

OptionDescription
-v / --verboseDisplays verbose progress information, including directory scan lists and link creation.
-p / --print-cachePrints the complete formatted list of libraries stored in /etc/ld.so.cache.
-f <file>Uses an alternate configuration file instead of default /etc/ld.so.conf.
-C <cachefile>Uses an alternate cache file instead of default /etc/ld.so.cache.
-NUpdates symbolic links only; does NOT rebuild the cache file.
-XRebuilds the cache file only; does NOT update symbolic links.

💡 LPIC-1 Exam Fill-in-the-Blank Alert: When asked which command and option prints the entire list of shared libraries currently indexed in the system cache, the answer is ldconfig -p.


5. Dynamic Linker Environment Variables

Administrators and developers can override default library search and binding behaviors using special environment variables interpreted by the dynamic linker.

1. LD_LIBRARY_PATH

A colon-separated list of directories searched by the dynamic linker before searching /etc/ld.so.cache and standard paths (/lib, /usr/lib).

# Temporarily run an application against a custom library build
export LD_LIBRARY_PATH=/opt/testing/lib:/custom/lib:$LD_LIBRARY_PATH
./my_application

⚠️ Security Feature: For security reasons, the dynamic linker automatically ignores LD_LIBRARY_PATH for SetUID and SetGID binaries to prevent unprivileged users from injecting malicious libraries into privileged processes.

2. LD_PRELOAD

A list of specific shared libraries loaded before all other libraries, including the C standard library. Allows developers and administrators to intercept and override (hook) standard library functions.

# Intercept memory allocations or fake system time
LD_PRELOAD=/usr/lib64/libfaketime.so.1 FAKETIME="-15d" date

3. LD_DEBUG

Provides detailed debugging output from the dynamic linker when troubleshooting unresolved symbols or binding order.

# Debug library loading resolution for ls
LD_DEBUG=libs ls -l
# Trace symbol binding
LD_DEBUG=bindings /usr/bin/python3 -c 'import ssl'
Loading diagram...
Dynamic Shared Library Resolution Process in Linux
Test Your Knowledge

A developer has installed a proprietary shared library into /opt/custom/lib. Although the path has been added to /etc/ld.so.conf.d/custom.conf, executing an application that depends on this library fails with a 'cannot open shared object file' error. What command must the administrator run to resolve this issue?

A
B
C
D
Test Your Knowledge

Which command-line tool is used to display all shared library dependencies required by a specific compiled executable binary?

A
B
C
D
Test Your Knowledge

Which environment variable can an administrator or developer set to force the dynamic linker to load custom shared libraries from non-standard directories before checking /etc/ld.so.cache and standard system directories?

A
B
C
D