Search code examples
c++csetuidexecve

LD_LIBRARY_PATH in envp arg of execve() gets removed even if the calling setuid parent prog dropped its privileged


Background: I understood that a parent program with setuid cannot keep the LD_LIBRARY_PATH as part of the env for security reasons, hence any child process will also not "see" the LD_LIBRARY_PATH.

Context : My parent program (see https://github.com/shadow-robot/ethercat_grant/blob/kinetic-devel/src/ethercat_grant.cpp ) needs setuid to change capabilities like CAP_NET_RAW of a child program. However the child program (under my control for instance this https://github.com/shadow-robot/ros_ethercat/blob/kinetic-devel/ros_ethercat_loop/src/main.cpp) uses libs, found with RPATH, that themselves need access to dependency libs, not under my control and only found through LD_LIBRARY_PATH (due to newly enforced RUNPATH in ubuntu bionic https://github.com/shadow-robot/ethercat_grant/issues/4).

So I need a workaround to pass LD_LIBRARY_PATH to the child process. I thought execve() should help and my question is only on that here.

Workaround: I putenv() LD_LIBRARY_PATH=/my/path/ in the parent app, drop the privileges, and then call execve() with the new env. I suppose this is safe as the LD_LIBRARY_PATH re-added in the env is only used as standard user not as privileged one. See code here https://github.com/ubi-agni/ethercat_grant/blob/env_append/src/ethercat_grant.cpp

Problem : LD_LIBRARY_PATH gets dropped again in the execve(). [EDIT] It appears to behave correctly (as long as privileged are dropped before calling execve) if cap_set_file is not used before, so problem is a relation between capabilities and execve somehow [/EDIT]

Research: I found some old still open report of that unwanted behaviour http://austingroupbugs.net/view.php?id=922 , but it is not explicitely explained (in man ld.so or other) that even if setuid matches seteuid (same for groups) after dropping privileges, the execve() will again drop LD_LIBRARY_PATH.

Question: I would like to know it this behaviour is still intended, or if I missed some proc/thread capabilities I should change as well so that the child process does not inherit the parent "secure" execution, and hence keep my new env intact ? [EDIT] It really seems to be related to the capabilities affecting the child process[/EDIT]

thanks.


Solution

  • 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