使用Linux功能是否会禁用LD_PRELOAD

Sun*_*lly 6 c linux shared-libraries linux-kernel linux-capabilities

在我的自定义环境拦截库预装它运行一个特殊的实施bind(),connect()等电话.

我看到的问题是,无论何时使用命令显式启用应用程序setcap,执行应用程序都无法预加载拦截器库并调用默认的libc connect().

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

是否有任何调整或方法可用于成功预加载启用功能的库.

Nom*_*mal 5

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

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

  1. 设置预加载的库setuid root

    (ld.so如果库由root拥有并标记为set-uid,则Linux动态链接器甚至会为setuid /文件功能启用的二进制文件预加载库.)

  2. 使用setuid根包装器

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

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

    static void my_library_init(void) __attribute__((constructor));
    static void my_library_init(void)
    {
        /* ... */
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

两种选择都有明显的安全性考虑 我建议LD_PRELOAD在预加载的库构造函数中进行完整性检查(和清除).如果有任何可疑之处,请_exit()立即中止该过程.

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

希望这可以帮助.