Using linux features disables LD_PRELOAD

In my user environment, the interceptor library is preloaded, which performs a special implementation of bind() , connect() calls, etc.

The problem that I see is when the application explicitly supports the capabilities with the setcap , the execution of the application does not allow you to preload the interceptor library and calls libc connect() by default.

Is this expected behavior? If so, what is the reason for disabling LD_PRELOAD ?

Are there any settings or methods that can be used to successfully preload the library with enabled features.

+6
source share
2 answers

As Oliver Matthews replied, LD_PRELOAD disabled for setuid binaries and for binary files that have file capabilities for security reasons.

To preload the library while still supporting the capabilities of the file, you have two options:

  • Set preloaded setuid root library

    (The Linux dynamic linker ld.so libraries even for binaries with setuid / file-capacity support if the libraries are root and are marked with set-uid.)

  • Use setuid root shell

    The wrapper receives full privileges (both real and effective identifiers of users and groups) and saves the original identifier of the real user and group, for example, an environment variable.

    A preloaded library has a constructor, for example

     static void my_library_init(void) __attribute__((constructor)); static void my_library_init(void) { /* ... */ } 

    which starts automatically before main() (but, possibly, after other constructors in other preloaded libraries or in libraries on which preloaded libraries depend).

    This constructor gets the desired features, denoted by environment variables ( getenv() , cap_from_text() ) or the binary executable itself ( cap_from_file("/proc/self/exe") ).

    The constructor should temporarily use prctl(PR_SET_KEEPCAPS, 1) to retain the ability to change the identifier, and to retain the capabilities of CAP_SETUID and CAP_SETGID in order to be able to change the identity from root to the user and group specified in the environment variables before limiting to the final set of capabilities.

Both options have obvious security concerns. I recommend a health check (and LD_PRELOAD cleanup) in a predefined library constructor. If something seems suspicious, use _exit() to abort the process immediately.

In general, I recommend the first option for simplicity (both for implementation and security), but if there is any reason it cannot be used, I can provide proof of concept code for the second case. (I checked both versions of working on Ubuntu 12.04.2 LTS running on the x86-64 kernel with a total volume of 3.8.0-27 using the ext4 file system.)

Hope this helps.

+5
source

Yes, this is for security reasons (see man sudo ).

You will have to get around this by explicitly opening the library from your code at the beginning of main() with dlopen (or by wrapping the main or the like).

+4
source

Source: https://habr.com/ru/post/951036/


All Articles