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.
3.5 Managing Shared Libraries & ldconfig (102.3)
Quick Summary: Linux applications rely heavily on shared libraries (Shared Objects or
.sofiles) 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 uselddto inspect program dependencies,ldconfigto update library cache files and SONAME symlinks, and environment variables likeLD_LIBRARY_PATHandLD_PRELOADto 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.
| Feature | Static Libraries (.a) | Dynamic Shared Libraries (.so) |
|---|---|---|
| Compilation Mechanism | Library 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 Size | Large (includes all library functions). | Small (contains only lightweight reference tables). |
| RAM Utilization | Inefficient (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 & Patching | Cumbersome (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). |
| Portability | Standalone 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)
- 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). - 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. - 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-lsslflag.
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 runlddon an untrusted or suspicious binary! For certain ELF binaries,lddmay attempt to execute the dynamic linker directly, potentially executing untrusted code. To safely inspect dependencies without execution, use:objdump -p /path/to/binary | grep NEEDEDorreadelf -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:
- Scans standard directories (
/lib,/lib64,/usr/lib,/usr/lib64) and directories specified in/etc/ld.so.confto create and update necessary SONAME symbolic links. - 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
| Option | Description |
|---|---|
-v / --verbose | Displays verbose progress information, including directory scan lists and link creation. |
-p / --print-cache | Prints 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. |
-N | Updates symbolic links only; does NOT rebuild the cache file. |
-X | Rebuilds 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_PATHfor 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'
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?
Which command-line tool is used to display all shared library dependencies required by a specific compiled executable binary?
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?