LD_LIBRARY_PATH 在 envp 中 execve() 的 arg 被删除,即使调用 setuid parent prog 放弃了它的特权

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

背景: 我知道出于安全原因,带有 setuid 的父程序不能将 LD_LIBRARY_PATH 作为 env 的一部分,因此任何子进程也不会 "see" LD_LIBRARY_PATH。

上下文: 我的父程序(参见 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)。

所以我需要一个解决方法来将 LD_LIBRARY_PATH 传递给子进程。 我认为 execve() 应该有所帮助,我的问题只在此处。

解决方法: 我在父应用程序中 putenv() LD_LIBRARY_PATH=/my/path/ ,放弃特权,然后使用新环境调用 execve() 。我想这是安全的,因为在 env 中重新添加的 LD_LIBRARY_PATH 仅用作标准用户而不是特权用户。请在此处查看代码 https://github.com/ubi-agni/ethercat_grant/blob/env_append/src/ethercat_grant.cpp

问题: LD_LIBRARY_PATH 在 execve() 中再次被丢弃。 [编辑] 如果之前未使用 cap_set_file,它似乎表现正确(只要特权在调用 execve 之前被删除),所以问题是功能和 execve 之间的某种关系 [/EDIT]

研究: 我发现了一些关于这种不良行为的旧报告 http://austingroupbugs.net/view.php?id=922 ,但没有明确解释(在 man ld.so 或其他) 即使在删除权限后 setuid 与 seteuid 匹配(对于组也是如此),execve() 将再次删除 LD_LIBRARY_PATH.

问题: 我想知道这种行为仍然是有意的,或者如果我错过了一些 proc/thread 功能,我也应该改变以便子进程不继承父 "secure" 执行,因此保持我的新环境完好无损? [编辑] 这似乎真的与影响子进程的能力有关[/编辑]

谢谢。

现在我发现问题来自 capabilities 而不是来自 setuid,这似乎也是一种期望的行为如本文所述 post