LD_PRELOAD is a process injection channel that secure-execution mode narrows
On Linux, LD_PRELOAD tells the dynamic loader to preload shared objects into a process. It is a legitimate debugging, instrumentation, and compatibility feature. It is also a code-loading instruction in the process environment. A service that starts from an untrusted environment can inherit an injection path even when the service's own binary and configuration are protected.
The ld.so manual lists preload objects among the mechanisms the loader considers. Secure-execution mode narrows the behavior for programs that need it, stripping or ignoring a set of dangerous environment variables. The exact rules depend on the loader and on how the process acquired privilege. Reviewers should not generalize that mode to every child or every service.
Why an environment variable matters
The dynamic loader runs before main. A preloaded object can interpose functions, inspect process memory, create files, or change the behavior of a library call. The process may still look normal to its own application logs because its first instructions were replaced or wrapped.
Inheritance is the practical problem. A shell, supervisor, CI runner, or web application can launch a long-lived service with an environment assembled from user input. Even if the final executable is trusted, the environment is not. Container images, systemd units, and process managers can also preserve variables that were intended for a one-off diagnostic session.
The loader's secure-execution behavior is a useful mitigation, but it is not a complete sandbox. A process that remains unprivileged can still attack a privileged API through IPC, local sockets, or shared files. Protect the launcher and the privileged endpoint as a pair; the setuid binary is one part of that boundary.
Find the inherited environment
Inventory service definitions and identify every place an environment is constructed. Look for broad pass-through rules, EnvironmentFile entries writable by unprivileged users, container runtime defaults, wrappers that use sudo, and scripts that launch helpers from a web request. Record whether the process can be restarted by a tenant or by a lower-privileged operator.
Inspect running processes for their effective environment and loaded objects. On Linux, process environment visibility is restricted by ownership and kernel settings, so use the host's approved inspection method. Compare the loaded-object list with the expected set. An object loaded from a writable directory, a home directory, or a temporary path deserves investigation.
Check system-wide loader configuration as well. /etc/ld.so.preload and other trusted configuration paths can affect many processes. Their content and ACLs belong in host integrity monitoring. A per-process variable is not the only injection path.
Design a trusted launch
Construct a minimal environment for every service. Do not forward variables such as LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, or their architecture-specific variants from an untrusted parent. Start the process with an explicit working directory and executable path. Use a service manager or launcher that supports a clean environment rather than a shell that expands user text.
Keep service configuration, library directories, and loader configuration writable only by trusted administrators. Mount application code read-only where possible. Separate debug instrumentation from production launch paths, and require a controlled restart to enable it.
For privileged operations, accept requests over a narrow API rather than letting an untrusted process become the privileged process. Authenticate the caller, validate the operation, and execute it in a small trusted component. The caller's loaded libraries should not determine the privileged component's code.
Verify the boundary
In an isolated test, launch a non-privileged helper with a harmless preload library that writes a marker. Confirm that the service's clean launcher does not forward the variable. Repeat for a privileged executable and record whether secure-execution mode ignores the path as expected. Test the child processes the service starts, because a clean parent can still pass a bad environment onward.
Monitor loaded objects and process starts for unusual paths. Correlate changes with package updates, debugging sessions, and service restarts. An alert on every preload would be noisy; the useful signal is an unexpected path or a privileged service loading code from a writable location.
Defensive baseline
Treat LD_PRELOAD as code, not configuration. Start services with a clean environment, protect loader configuration and library paths, verify child-process inheritance, and keep privileged operations behind a narrow API. Secure-execution mode reduces one class of risk; it does not make an untrusted environment safe.
