使用Linuxfunction是否禁用LD_PRELOAD

在我的自定义环境中,预加载了一个拦截器库,它运行bind()connect()等调用的特殊实现。

我看到的问题是每当一个应用程序使用命令setcap明确启用function,执行应用程序将无法预加载拦截器库并调用默认的libc connect()

这是一个预期的行为? 如果是的话,可能是什么原因来禁用LD_PRELOAD

他们的任何调整或方法可以成功地预加载function库启用。

就像Oliver Matthews所回答的那样,出于安全原因, LD_PRELOAD对于setuid二进制文件和具有文件功能的二进制文件都是禁用的。

要预加载库,同时仍启用文件功能,您有两个选择:

  1. 设置预加载的库setuid root

    (即使对于启用了setuid /文件功能的二进制文件,Linux动态链接程序ld.so也会预加载库,前提是这些库属于root并标记为set-uid。)

  2. 使用setuid根包装

    包装器获得完整的root权限(真实和有效的用户和组ID为零),并将原始的真实用户和组ID存储到例如环境变量中。

    预加载的库有一个构造函数,例如

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

    它在main()之前自动运行(但可能在其他预加载库中的其他构造函数之后,或在预加载库依赖的库中)。

    此构造函数通过环境变量( getenv()cap_from_text() )或二进制可执行文件本身( cap_from_file("/proc/self/exe") )来获得所需的功能。

    构造函数必须临时使用prctl(PR_SET_KEEPCAPS, 1)来保持能力超过身份更改,并保留CAP_SETUIDCAP_SETGID功能,以便能够将自身限制为最终的环境变量中指定的用户和组的root身份能力集。

两个选项都有明显的安全考虑。 我建议在预加载的库构造函数中进行完整性检查(并清除LD_PRELOAD )。 如果有什么可疑的,使用_exit()立即中止该过程。

一般来说,我推荐第一种简单的方法(实现和安全问题),但是如果有某些原因不能使用,我可以为第二种情况提供一个概念验证码。 (我已经验证了这两个选项在使用ext4文件系统运行3.8.0-27-通用x86-64内核的Ubuntu 12.04.2 LTS上工作。)

希望这可以帮助。

是的,这是出于安全原因(见man sudo )。

你必须通过在main()的开始处使用dlopen (或者通过包装main或类似的)来显式地打开你的代码库来解决这个问题。