5

If, when I run a script, I use LD_PRELOAD to designate a library to preload, I find that the library is in fact preloaded only if the script has a shebang line. For example, given this script:

# Not a shebang
echo Hello

and this command:

LD_PRELOAD=/path/to/preload_me.so ./script.sh

the script runs without the library being loaded at all, which I can monitor via the (non-)effects of its initialization code.

On the other hand, if I add a shebang line:

#!/bin/sh
echo Hello

... then the library is loaded when I run the script via the same command. It doesn't seem to matter exactly which interpreter is specified; certainly I can also use /bin/bash or any other sh-family shell I have tried.

Why is there a difference, and is there any way to ensure that a given library is preloaded before a given shell simple command, regardless of the command?

(Adapted from another question whose author resisted the question being couched in these terms.)

Community
  • 1
  • 1
John Bollinger
  • 160,171
  • 8
  • 81
  • 157

1 Answers1

7

(Adapted from my answer to the referenced other question.)

It is essential to understand that LD_PRELOAD variable has no special significance to the operating system or to the shell. It has meaning and effect -- if it has them at all -- only in conjunction with the dynamic linker. If the dynamic linker is not engaged, then LD_PRELOAD is just another variable in the environment. Likewise if the dynamic linker does not recognize that variable (as on OS X, for example).

It is also essential to understand that when executing a command whose name corresponds to a file that is not in an executable format but that contains a shebang line, the specified interpreter is executed, even if it is the shell itself. If the interpreter is an ELF binary, that engages the dynamic linker. On the other hand, if there is no shebang line then bash executes the contents of the file in a subshell environment, which does not require engaging the dynamic linker; instead, the shell just forks. Other shells might or might not do the same.

It is also important to recognize that executable formats other than ELF exist. You're unlikely to run into such a binary on a modern ELF-based system, but you should not rule out the possibility.

Bottom line: there is no way to ensure that a given dynamic library will be preloaded in the process space of an arbitrary shell command executed via bash or another shell chosen by the user. If you require such a library to be preloaded for any or every arbitrary command then you need to control the execution environment much more strictly, perhaps by providing a custom shell and maybe also a custom dynamic linker, and preventing any others from being used.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 2
    This is a good answer, but I think you should clarify that it applies specifically to `bash` (and probably other shells.) `dash` doesn't seem to do this, for example. (It executes the script, but the preload takes effect.) All Posix says is "the shell shall execute a command equivalent to having a shell invoked with the pathname resulting from the search as its first operand," which could apply to either behaviour. (Quick test on my system: zsh preloads, ksh doesn't. Go figure.) – rici Oct 11 '16 at 17:31
  • @rici, the answer does explicitly say that *`bash`* forks instead of exec'ing a new shell process, but I have nevertheless added a clarification. – John Bollinger Oct 11 '16 at 17:50