'How to set LD_PRELOAD in systemd

I want to hook some functions in libssl with LD_PRELOAD in systemd.

In systemd file I put

ExecStart=/etc/myscript.sh

and in /etc/myscript.sh I put

#!/bin/sh
LD_PRELOAD=/lib/inject_libssl.so /bin/run

When I look at /proc/RUN_PID/maps I can see that inject_libssl.so is realy injected to the process but the original libssl.so is loaded before the the injected library, so my hook doesn't work.

I olso tried

ExecStart=/bin/run 
Environment="LD_PRELOAD=/lib/inject_libssl.so"

But I got the same results.

If I run LD_PRELOAD=/lib/inject_libssl.so curl https://google.com the injected libssl works well.

Why is that please?



Solution 1:[1]

Can you try this script to see which one will be loaded ?

#!/usr/bin/env bash
  
cp /lib/x86_64-linux-gnu/libssl.so /tmp/inject_libssl.so
LD_PRELOAD=/tmp/inject_libssl.so /bin/run

Can you also try to put your .so in /usr/lib/x86_64-linux-gnu ?

Solution 2:[2]

The reason is probably that systemd runs your script / binary in set-user-ID mode. According to the dynamic linker documentation, LD_PRELOAD support is limited then:

For set-user-ID/set-group-ID ELF binaries, preload pathnames containing slashes are ignored, and libraries in the standard search directories are loaded only if the set-user-ID permission bit is enabled on the library file.

So you need to copy your library to the proper place and provide the permission accordingly. You might be able to work around this with a specific User= setting or by using a wrapper.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alex O