Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't LD_PRELOAD take effect with scripts having no shebang?

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.)

like image 391
John Bollinger Avatar asked Oct 11 '16 16:10

John Bollinger


People also ask

Can we write shell script without shebang?

shebang line is needed in the file and only if it's meant to be run as executable (as opposed to sh file.sh invocation. It is not actually needed by script, it is for the system to know how to find interpreter.

What is the purpose of a shebang in a script file?

What is the shebang? The shebang is a special character sequence in a script file that specifies which program should be called to run the script. The shebang is always on the first line of the file, and is composed of the characters #! followed by the path to the interpreter program.

Why shebang is required?

shebang is used to tell the kernel which interpreter should be used to run the commands present in the file. When we run a file starting with #! , the kernel opens the file and takes the contents written right after the #!

Is shebang ignored?

The shebang line is usually ignored by the interpreter, because the "#" character is a comment marker in many scripting languages; some language interpreters that do not use the hash mark to begin comments still may ignore the shebang line in recognition of its purpose.


Video Answer


1 Answers

(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.

like image 106
John Bollinger Avatar answered Nov 14 '22 22:11

John Bollinger