Linux capabilities (setcap) seems to disable LD_LIBRARY_PATH
Yes, it's disabled for security reasons.
Does using linux capabilities disable LD_PRELOAD
Like Oliver Matthews answered, LD_PRELOAD
is disabled for both setuid binaries, and for binaries having file capabilities, for security reasons.
To preload a library while still enabling file capabilities, you have two options:
Set the preloaded library setuid root
(The Linux dynamic linker
ld.so
does preload libraries even for setuid/file-capability-enabled binaries, if the libraries are owned by root and marked set-uid.)Use a setuid root wrapper
The wrapper obtains full root privileges (both real and effective user and group IDs zero), and stores the original real user and group ID to e.g. environment variable(s).
The preloaded library has a constructor, e.g.
static void my_library_init(void) __attribute__((constructor));
static void my_library_init(void)
{
/* ... */
}which is automatically run prior to
main()
(but possibly after other constructors in other preloaded libraries, or in libraries that the preloaded libraries depend on).This constructor obtains the desired capabilities, either designated via environment variables (
getenv()
,cap_from_text()
) or the binary executable file itself (cap_from_file("/proc/self/exe")
).The constructor must temporarily use
prctl(PR_SET_KEEPCAPS, 1)
to keep capabilities over an identity change, and retainCAP_SETUID
andCAP_SETGID
capabilities to be able to change identity from root to the user and group specified in the environment variables, before limiting itself to the final capability set.
Both options have obvious security considerations. I recommend sanity checking (and clearing LD_PRELOAD
) in the preloaded library constructor. If anything seems suspicious, use _exit()
to abort the process immediately.
In general, I recommend the first option for simplicity (both implementation and security issues), but if there is some reason it cannot be used, I can provide a proof of concept code for the second case too. (I have verified both options work on Ubuntu 12.04.2 LTS running a 3.8.0-27-generic x86-64 kernel, using ext4 file system.)
Hope this helps.
LD_LIBRARY_PATH in envp arg of execve() gets removed even if the calling setuid parent prog dropped its privileged
Now that I have found the problem comes from the capabilities and not from the setuid, it seems it is also a desired behaviour as mentioned in this post https://stackoverflow.com/a/10215158/10801865
Trying to perform setcap from Qt program
The best thing to do, as @G.M. suggests, is to provide the full path to the binary. You can find setcap
's location on your system with:
$ sudo which setcap
On Debian and Fedora, that returns /usr/sbin/setcap
. On your system it might also be /sbin/setcap
. Then embed that string in your program explicitly:
command = "/sbin/setcap";
Setcap over SSHFS
File capabilities are implemented on Linux with extended attributes (specifically the security.capability
attribute), and not all filesystems implement extended attributes.
sshfs
in particular does not.
Is there a way for non-root processes to bind to privileged ports on Linux?
Okay, thanks to the people who pointed out the capabilities system and CAP_NET_BIND_SERVICE
capability. If you have a recent kernel, it is indeed possible to use this to start a service as non-root but bind low ports. The short answer is that you do:
setcap 'cap_net_bind_service=+ep' /path/to/program
And then anytime program
is executed thereafter it will have the CAP_NET_BIND_SERVICE
capability. setcap
is in the debian package libcap2-bin
.
Now for the caveats:
- You will need at least a 2.6.24 kernel
- This won't work if your file is a script. (i.e. uses a
#!
line to launch an interpreter). In this case, as far I as understand, you'd have to apply the capability to the interpreter executable itself, which of course is a security nightmare, since any program using that interpreter will have the capability. I wasn't able to find any clean, easy way to work around this problem. - Linux will disable
LD_LIBRARY_PATH
on anyprogram
that has elevated privileges likesetcap
orsuid
. So if yourprogram
uses its own.../lib/
, you might have to look into another option like port forwarding.
Resources:
- capabilities(7) man page. Read this long and hard if you're going to use capabilities in a production environment. There are some really tricky details of how capabilities are inherited across exec() calls that are detailed here.
- setcap man page
- "Bind ports below 1024 without root on GNU/Linux": The document that first pointed me towards
setcap
.
Note: RHEL first added this in v6.
Java symbol lookup error for JLI_InitArgProcessing when running with setcap capabilities
I was able to resolve this by adding this file:
/etc/ld.so.conf.d/java.conf
With the single-line contents:
/usr/lib/jvm/java-11-openjdk-11.0.1.13-3.0.1.el7_6.x86_64/lib/jli
And rebooting the server.
Obviously, that directory path should point to your specific JDK
Related Topics
Get String Length in Inline Gnu Assembler
Don't Fail Jenkins Build If Execute Shell Fails
How to Run a Windows Executable from Wsl (Ubuntu) Bash
How to Set Rpath and Runpath with Gcc/Ld
What's the Point of Eval/Bash -C as Opposed to Just Evaluating a Variable
How to Run Nginx Within a Docker Container Without Halting
Start Script After Another One (Already Running) Finishes
Signed Executables Under Linux
Why No Output Is Shown When Using Grep Twice
How to Reference Files Relative to Application Root in Node.Js
How to Debug Linux Kernel Modules with Qemu
Using Ls to List Directories and Their Total Sizes
Linux: Compute a Single Hash for a Given Folder & Contents
How to Run a Cron Job Inside a Docker Container
What Are the Real Rules for Linux Usernames on Centos 6 and Rhel 6