【问题标题】:Linux capabilities (setcap) seems to disable LD_LIBRARY_PATHLinux 功能 (setcap) 似乎禁用了 LD_LIBRARY_PATH
【发布时间】:2025-11-28 16:35:01
【问题描述】:

我使用LD_LIBRARY_PATH 为应用程序设置某个用户库的路径。但是如果我在这个应用程序上设置功能

sudo setcap CAP_NET_BIND_SERVICE=eip myapplication

然后LD_LIBRARY_PATH 似乎被忽略了。当我启动该程序时,Linux 抱怨它找不到某个共享库。

我猜想有某种保护措施开始起作用,以防止具有扩展权限的应用程序被劫持。有解决办法吗?

【问题讨论】:

    标签: linux shared-libraries linux-capabilities


    【解决方案1】:

    正如其他答案中已经说明的那样,这种行为是有意的。如果您可以自己编译(或至少链接)应用程序,则有某种解决方法。然后您可以将-Wl,-rpath <yourDynamicLibraryPath> 传递给gcc 或-rpath <yourDynamicLibraryPath> 传递给ld,并且您在执行时根本不需要指定LD_LIBRARY_PATH

    【讨论】:

    • 即使使用 -rpath,Linux 也会在调用 setcap 后阻止加载共享库。
    【解决方案2】:

    这个问题在linux上的解决方法如下:

    进入目录 $cd /etc/ld.so.conf.d/ 创建一个新文件 $touch xyz.conf 使用任何编辑器打开此文件 $vi xyz.conf

    在此文件中逐行添加您的动态库路径,例如如果你的路径如下:

    /home/xyz/libs1:/home/xyz/libs2/:/home/xyz/libs3/ 那么这个文件中应该有三个条目,如下所示: /home/xyz/libs1/ /home/xyz/libs2/ /home/xyz/libs3/

    然后保存此文件并执行以下命令: $ldconfig

    以上所有操作都需要从root登录进行

    【讨论】:

    • 而 yum 会坏掉的。
    【解决方案3】:

    man pagesudo 解释:

    请注意,大多数操作系统上的动态链接器将删除 可以从环境中控制动态链接的变量 setuid 可执行文件,包括 sudo。取决于操作系统 这可能包括 RLD*、DYLD*、LD_、LDR_、LIBPATH、SHLIB_PATH 和 其他。这些类型的变量从环境中删除 在 sudo 甚至开始执行之前,因此不可能 sudo 来保存它们。

    作为this link explains,执行此操作的实际机制在 glibc 中。如果 UID 与 EUID 不匹配(任何setuid 程序都是这种情况,包括sudo),则删除所有“不安全的环境变量”。因此,具有提升权限的程序无需更改即可运行。

    【讨论】:

    • 这一切都很好,但是 setcap 不会更改 UID 或 EUID。它确实增加了功能(“提升的权限”)。
    【解决方案4】:

    是的,出于安全原因,它已被禁用。

    【讨论】:

      【解决方案5】:

      要考虑的替代方法是使用 patchelf 设置 rpath 来“纠正”编译不佳的 ELF 共享库和/或可执行文件。 https://nixos.org/patchelf.html

      ld.so.conf 并不总是可靠的。如果您正在运行的任何内容都正确编译,它将起作用。在我的例子中,对于一个特别打包的供应商的 apache 产品,它的编译非常糟糕:他们甚至没有使用唯一的 .so 文件名,因此它们与基础 RHEL 存储库中的 RPM 中的 .so 文件名冲突,这些存储库提供了一些非常关键的常用库.因此,这是隔离它们的使用方式的唯一选择。对供应商的 lib 路径中的那些共享对象使用 ld.so.conf 会炸毁很多东西,包括 yum,以及系统范围内的 glibc 共享库故障。

      【讨论】:

      • 请注意,您必须在已编辑的二进制文件上重新运行 setcap 命令。尽管如此,这是最有用的答案——尤其是如果供应商的构建管道配置错误