I have the same exact problem as this question previously posted, where /etc/ld.so.preload does not intercept the right architecture. A little background: I have compiled a shared object (64-bit) that is referenced in the ld.so.preload file on any binary execution. The problem was that I was getting a ERROR: ld.so: object '/usr/local/lib/mysharedobject.so' from /etc/ld.so.preload cannot be preloaded (wrong ELF class: ELFCLASS64): ignored. when executing 32-bit programs.

To fix the issue according to the answer in that question, I had to make two directories (lib/i386-linux-gnu and x86_64-linux-gnu, for example, in /var/opt) and specify /var/opt/$LIB/mysharedobject.so in /etc/ld.so.preload so the right library will be preloaded depending in program architecture.

So in that case, in Debian based systems, /var/opt/$LIB/mysharedobject.so would expand to:

  • /var/opt/lib/i386-linux-gnu/mysharedobject.so for 32-bit programs;
  • /var/opt/x86_64-linux-gnu/mysharedobject.so for 64-bit programs.

However, after applying this, any binary I run (such as ls) will output the following 'error':
ERROR: ld.so: object '/var/opt/$LIB/mysharedobject.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.

As you can see, $LIB did not expand to anything. I have also set $LD_LIBRARY_PATH to /var/opt and ran ldconfig to update the system with this libs, but with no success. What is the problem here?


The shell would expand $LIB, but it was not possible when you did this:

specify /var/opt/$LIB/mysharedobject.so in /etc/ld.so.preload

The manual page mentioning /etc/ld.so.preload doesn't mention the possibility of glob-expansions or environment variables:

File containing a whitespace-separated list of ELF shared objects to be loaded before the program. See the discussion of LD_PRELOAD above. If both LD_PRELOAD and /etc/ld.so.preload are employed, the libraries specified by LD_PRELOAD are preloaded first. /etc/ld.so.preload has a system-wide effect, causing the specified libraries to be preloaded for all programs that are executed on the system. (This is usually undesirable, and is typically employed only as an emergency remedy, for example, as a temporary workaround to a library misconfiguration issue.)

nor would that be likely, when you stop to think about how the data is used:

  • glob-expansions would be a security problem, since the data (being inexplicit) could match all sorts of interesting files, and
  • environment variables would have to be set somewhere, and would easily differ for different users.

Now... the manual page mentions that $LIB can be used in rpath and LD_PRELOAD, but it also says

In secure-execution mode, preload pathnames containing slashes are ignored. Furthermore, shared objects are preloaded only from the standard search directories and only if they have set-user-ID mode bit enabled (which is not typical).

That's one pitfall which would affect you since /var/opt probably isn't a standard search directory.

  • Apparently, the $LIB was being expanded but it was only shown in strace rather than the 'error' message: lib32 directory for 32-bit programs and lib/x86_64-linux-gnu for 64-bit programs (as /usr/$LIB/mysharedobject.so in /etc/ld.so.preload) – bashbin Jan 12 '19 at 2:51
  • 1
    strace might also show an error message (a failed open/openat) for the library, though not the actual cause if the machine is running in secure-execution mode. – Thomas Dickey Jan 12 '19 at 18:34

Finally fixed the problem.$LIB environment variable expands to lib32 directory for 32-bit programs and lib/x86_64-linux-gnu for 64-bit programs (as /usr/$LIB/mysharedlibrary.so in /etc/ld.so.preload) - as shown in strace. This is for Debian based systems, as for other systems it will expand to lib64 and lib (could always confirm with strace, more specifically the openat() system call).

So the solution would be to compile the shared library with both -m32 and -m64 and put the relevant architecture files to their respective referenced folders from $LIB.

In summary (example):

$ mkdir {32,64}
$ gcc -Wall -m32 -fPIC -shared -o 32/mysharedlibrary.so mysharedlibrary.c -ldl
$ gcc -Wall -fPIC -shared -o 64/mysharedlibrary.so mysharedlibrary.c -ldl
$ sudo mv 32/mysharedlibrary.so /usr/lib32/mysharedlibrary.so
$ sudo mv 64/mysharedlibrary.so /usr/lib/x86_64-linux-gnu/mysharedlibrary.so
$ sudo echo '/usr/$LIB/mysharedlibrary.so' > /etc/ld.so.preload

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.